1/*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1997-2005 5 * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35/* 36 * This program creates syntax.h and syntax.c. 37 */ 38 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <sys/types.h> 43#include "parser.h" 44 45 46struct synclass { 47 char *name; 48 char *comment; 49}; 50 51/* Syntax classes */ 52struct synclass synclass[] = { 53 { "CWORD", "character is nothing special" }, 54 { "CNL", "newline character" }, 55 { "CBACK", "a backslash character" }, 56 { "CSQUOTE", "single quote" }, 57 { "CDQUOTE", "double quote" }, 58 { "CENDQUOTE", "a terminating quote" }, 59 { "CBQUOTE", "backwards single quote" }, 60 { "CVAR", "a dollar sign" }, 61 { "CENDVAR", "a '}' character" }, 62 { "CLP", "a left paren in arithmetic" }, 63 { "CRP", "a right paren in arithmetic" }, 64 { "CEOF", "end of file" }, 65 { "CCTL", "like CWORD, except it must be escaped" }, 66 { "CSPCL", "these terminate a word" }, 67 { "CIGN", "character should be ignored" }, 68 { NULL, NULL } 69}; 70 71 72/* 73 * Syntax classes for is_ functions. Warning: if you add new classes 74 * you may have to change the definition of the is_in_name macro. 75 */ 76struct synclass is_entry[] = { 77 { "ISDIGIT", "a digit" }, 78 { "ISUPPER", "an upper case letter" }, 79 { "ISLOWER", "a lower case letter" }, 80 { "ISUNDER", "an underscore" }, 81 { "ISSPECL", "the name of a special parameter" }, 82 { NULL, NULL } 83}; 84 85static char writer[] = "\ 86/*\n\ 87 * This file was generated by the mksyntax program.\n\ 88 */\n\ 89\n"; 90 91 92static FILE *cfile; 93static FILE *hfile; 94static char *syntax[513]; 95 96static void filltable(char *); 97static void init(void); 98static void add(char *, char *); 99static void print(char *); 100static void output_type_macros(void); 101int main(int, char **); 102 103int 104main(int argc, char **argv) 105{ 106 int i; 107 char buf[80]; 108 int pos; 109 110 /* Create output files */ 111 if ((cfile = fopen("syntax.c", "w")) == NULL) { 112 perror("syntax.c"); 113 exit(2); 114 } 115 if ((hfile = fopen("syntax.h", "w")) == NULL) { 116 perror("syntax.h"); 117 exit(2); 118 } 119 fputs(writer, hfile); 120 fputs(writer, cfile); 121 122 fputs("#include <ctype.h>\n", hfile); 123 fputs("\n", hfile); 124 fputs("#ifdef CEOF\n", hfile); 125 fputs("#undef CEOF\n", hfile); 126 fputs("#endif\n", hfile); 127 fputs("\n", hfile); 128 129 /* Generate the #define statements in the header file */ 130 fputs("/* Syntax classes */\n", hfile); 131 for (i = 0 ; synclass[i].name ; i++) { 132 sprintf(buf, "#define %s %d", synclass[i].name, i); 133 fputs(buf, hfile); 134 for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 135 putc('\t', hfile); 136 fprintf(hfile, "/* %s */\n", synclass[i].comment); 137 } 138 putc('\n', hfile); 139 fputs("/* Syntax classes for is_ functions */\n", hfile); 140 for (i = 0 ; is_entry[i].name ; i++) { 141 sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); 142 fputs(buf, hfile); 143 for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 144 putc('\t', hfile); 145 fprintf(hfile, "/* %s */\n", is_entry[i].comment); 146 } 147 putc('\n', hfile); 148 fprintf(hfile, "#define SYNBASE %d\n", 130); 149 fprintf(hfile, "#define PEOF %d\n\n", -130); 150 fprintf(hfile, "#define PEOA %d\n\n", -129); 151 putc('\n', hfile); 152 fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); 153 fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); 154 fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); 155 fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); 156 putc('\n', hfile); 157 output_type_macros(); /* is_digit, etc. */ 158 putc('\n', hfile); 159 160 /* Generate the syntax tables. */ 161 fputs("#include \"shell.h\"\n", cfile); 162 fputs("#include \"syntax.h\"\n\n", cfile); 163 init(); 164 fputs("/* syntax table used when not in quotes */\n", cfile); 165 add("\n", "CNL"); 166 add("\\", "CBACK"); 167 add("'", "CSQUOTE"); 168 add("\"", "CDQUOTE"); 169 add("`", "CBQUOTE"); 170 add("$", "CVAR"); 171 add("}", "CENDVAR"); 172 add("<>();&| \t", "CSPCL"); 173 syntax[1] = "CSPCL"; 174 print("basesyntax"); 175 init(); 176 fputs("\n/* syntax table used when in double quotes */\n", cfile); 177 add("\n", "CNL"); 178 add("\\", "CBACK"); 179 add("\"", "CENDQUOTE"); 180 add("`", "CBQUOTE"); 181 add("$", "CVAR"); 182 add("}", "CENDVAR"); 183 /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 184 add("!*?[=~:/-]", "CCTL"); 185 print("dqsyntax"); 186 init(); 187 fputs("\n/* syntax table used when in single quotes */\n", cfile); 188 add("\n", "CNL"); 189 add("'", "CENDQUOTE"); 190 /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 191 add("!*?[=~:/-]\\", "CCTL"); 192 print("sqsyntax"); 193 init(); 194 fputs("\n/* syntax table used when in arithmetic */\n", cfile); 195 add("\n", "CNL"); 196 add("\\", "CBACK"); 197 add("`", "CBQUOTE"); 198 add("$", "CVAR"); 199 add("}", "CENDVAR"); 200 add("(", "CLP"); 201 add(")", "CRP"); 202 print("arisyntax"); 203 filltable("0"); 204 fputs("\n/* character classification table */\n", cfile); 205 add("0123456789", "ISDIGIT"); 206 add("abcdefghijklmnopqrstucvwxyz", "ISLOWER"); 207 add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER"); 208 add("_", "ISUNDER"); 209 add("#?$!-*@", "ISSPECL"); 210 print("is_type"); 211 exit(0); 212 /* NOTREACHED */ 213} 214 215 216 217/* 218 * Clear the syntax table. 219 */ 220 221static void 222filltable(char *dftval) 223{ 224 int i; 225 226 for (i = 0 ; i < 258; i++) 227 syntax[i] = dftval; 228} 229 230 231/* 232 * Initialize the syntax table with default values. 233 */ 234 235static void 236init(void) 237{ 238 int ctl; 239 240 filltable("CWORD"); 241 syntax[0] = "CEOF"; 242 syntax[1] = "CIGN"; 243 for (ctl = CTL_FIRST; ctl <= CTL_LAST; ctl++ ) 244 syntax[130 + ctl] = "CCTL"; 245} 246 247 248/* 249 * Add entries to the syntax table. 250 */ 251 252static void 253add(char *p, char *type) 254{ 255 while (*p) 256 syntax[(signed char)*p++ + 130] = type; 257} 258 259 260 261/* 262 * Output the syntax table. 263 */ 264 265static void 266print(char *name) 267{ 268 int i; 269 int col; 270 271 fprintf(hfile, "extern const char %s[];\n", name); 272 fprintf(cfile, "const char %s[] = {\n", name); 273 col = 0; 274 for (i = 0 ; i < 258; i++) { 275 if (i == 0) { 276 fputs(" ", cfile); 277 } else if ((i & 03) == 0) { 278 fputs(",\n ", cfile); 279 col = 0; 280 } else { 281 putc(',', cfile); 282 while (++col < 9 * (i & 03)) 283 putc(' ', cfile); 284 } 285 fputs(syntax[i], cfile); 286 col += strlen(syntax[i]); 287 } 288 fputs("\n};\n", cfile); 289} 290 291 292 293/* 294 * Output character classification macros (e.g. is_digit). If digits are 295 * contiguous, we can test for them quickly. 296 */ 297 298static char *macro[] = { 299 "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)\n", 300 "#define is_alpha(c)\tisalpha((unsigned char)(c))\n", 301 "#define is_name(c)\t((c) == '_' || isalpha((unsigned char)(c)))\n", 302 "#define is_in_name(c)\t((c) == '_' || isalnum((unsigned char)(c)))\n", 303 "#define is_special(c)\t((is_type+SYNBASE)[(signed char)(c)] & (ISSPECL|ISDIGIT))\n", 304 NULL 305}; 306 307static void 308output_type_macros(void) 309{ 310 char **pp; 311 312 for (pp = macro ; *pp ; pp++) 313 fputs(*pp, hfile); 314 fputs("#define digit_val(c)\t((c) - '0')\n", hfile); 315} 316