1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)mksyntax.c 5.3 (Berkeley) 04/30/92"; 19 #endif /* not lint */ 20 21 /* 22 * This program creates syntax.h and syntax.c. 23 */ 24 25 #include <stdio.h> 26 #include "parser.h" 27 28 29 struct synclass { 30 char *name; 31 char *comment; 32 }; 33 34 /* Syntax classes */ 35 struct synclass synclass[] = { 36 "CWORD", "character is nothing special", 37 "CNL", "newline character", 38 "CBACK", "a backslash character", 39 "CSQUOTE", "single quote", 40 "CDQUOTE", "double quote", 41 "CENDQUOTE", "a terminating quote", 42 "CBQUOTE", "backwards single quote", 43 "CVAR", "a dollar sign", 44 "CENDVAR", "a '}' character", 45 "CLP", "a left paren in arithmetic", 46 "CRP", "a right paren in arithmetic", 47 "CEOF", "end of file", 48 "CCTL", "like CWORD, except it must be escaped", 49 "CSPCL", "these terminate a word", 50 NULL, NULL 51 }; 52 53 54 /* 55 * Syntax classes for is_ functions. Warning: if you add new classes 56 * you may have to change the definition of the is_in_name macro. 57 */ 58 struct synclass is_entry[] = { 59 "ISDIGIT", "a digit", 60 "ISUPPER", "an upper case letter", 61 "ISLOWER", "a lower case letter", 62 "ISUNDER", "an underscore", 63 "ISSPECL", "the name of a special parameter", 64 NULL, NULL, 65 }; 66 67 char writer[] = "\ 68 /*\n\ 69 * This file was generated by the mksyntax program.\n\ 70 */\n\ 71 \n"; 72 73 74 FILE *cfile; 75 FILE *hfile; 76 char *syntax[513]; 77 int base; 78 int size; /* number of values which a char variable can have */ 79 int nbits; /* number of bits in a character */ 80 int digit_contig; /* true if digits are contiguous */ 81 82 83 main() { 84 char c; 85 char d; 86 int sign; 87 int i; 88 char buf[80]; 89 int pos; 90 static char digit[] = "0123456789"; 91 92 /* Create output files */ 93 if ((cfile = fopen("syntax.c", "w")) == NULL) { 94 perror("syntax.c"); 95 exit(2); 96 } 97 if ((hfile = fopen("syntax.h", "w")) == NULL) { 98 perror("syntax.h"); 99 exit(2); 100 } 101 fputs(writer, hfile); 102 fputs(writer, cfile); 103 104 /* Determine the characteristics of chars. */ 105 c = -1; 106 if (c < 0) 107 sign = 1; 108 else 109 sign = 0; 110 for (nbits = 1 ; ; nbits++) { 111 d = (1 << nbits) - 1; 112 if (d == c) 113 break; 114 } 115 printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits); 116 if (nbits > 9) { 117 fputs("Characters can't have more than 9 bits\n", stderr); 118 exit(2); 119 } 120 size = (1 << nbits) + 1; 121 base = 1; 122 if (sign) 123 base += 1 << (nbits - 1); 124 digit_contig = 1; 125 for (i = 0 ; i < 10 ; i++) { 126 if (digit[i] != '0' + i) 127 digit_contig = 0; 128 } 129 130 fputs("#include <sys/cdefs.h>\n", hfile); 131 132 /* Generate the #define statements in the header file */ 133 fputs("/* Syntax classes */\n", hfile); 134 for (i = 0 ; synclass[i].name ; i++) { 135 sprintf(buf, "#define %s %d", synclass[i].name, i); 136 fputs(buf, hfile); 137 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07) 138 putc('\t', hfile); 139 fprintf(hfile, "/* %s */\n", synclass[i].comment); 140 } 141 putc('\n', hfile); 142 fputs("/* Syntax classes for is_ functions */\n", hfile); 143 for (i = 0 ; is_entry[i].name ; i++) { 144 sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); 145 fputs(buf, hfile); 146 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07) 147 putc('\t', hfile); 148 fprintf(hfile, "/* %s */\n", is_entry[i].comment); 149 } 150 putc('\n', hfile); 151 fprintf(hfile, "#define SYNBASE %d\n", base); 152 fprintf(hfile, "#define PEOF %d\n\n", -base); 153 putc('\n', hfile); 154 fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); 155 fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); 156 fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); 157 fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); 158 putc('\n', hfile); 159 output_type_macros(); /* is_digit, etc. */ 160 putc('\n', hfile); 161 162 /* Generate the syntax tables. */ 163 fputs("#include \"shell.h\"\n", cfile); 164 fputs("#include \"syntax.h\"\n\n", cfile); 165 init(); 166 fputs("/* syntax table used when not in quotes */\n", cfile); 167 add("\n", "CNL"); 168 add("\\", "CBACK"); 169 add("'", "CSQUOTE"); 170 add("\"", "CDQUOTE"); 171 add("`", "CBQUOTE"); 172 add("$", "CVAR"); 173 add("}", "CENDVAR"); 174 add("<>();&| \t", "CSPCL"); 175 print("basesyntax"); 176 init(); 177 fputs("\n/* syntax table used when in double quotes */\n", cfile); 178 add("\n", "CNL"); 179 add("\\", "CBACK"); 180 add("\"", "CENDQUOTE"); 181 add("`", "CBQUOTE"); 182 add("$", "CVAR"); 183 add("}", "CENDVAR"); 184 add("!*?[=~:/", "CCTL"); /* ':/' for tilde - yuck */ 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 add("!*?[=~:/", "CCTL"); /* ':/' for tilde - yuck */ 191 print("sqsyntax"); 192 init(); 193 fputs("\n/* syntax table used when in arithmetic */\n", cfile); 194 add("\n", "CNL"); 195 add("\\", "CBACK"); 196 add("`", "CBQUOTE"); 197 add("'", "CSQUOTE"); 198 add("\"", "CDQUOTE"); 199 add("$", "CVAR"); 200 add("}", "CENDVAR"); 201 add("(", "CLP"); 202 add(")", "CRP"); 203 print("arisyntax"); 204 filltable("0"); 205 fputs("\n/* character classification table */\n", cfile); 206 add("0123456789", "ISDIGIT"); 207 add("abcdefghijklmnopqrstucvwxyz", "ISLOWER"); 208 add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER"); 209 add("_", "ISUNDER"); 210 add("#?$!-*@", "ISSPECL"); 211 print("is_type"); 212 if (! digit_contig) 213 digit_convert(); 214 exit(0); 215 } 216 217 218 219 /* 220 * Clear the syntax table. 221 */ 222 223 filltable(dftval) 224 char *dftval; 225 { 226 int i; 227 228 for (i = 0 ; i < size ; i++) 229 syntax[i] = dftval; 230 } 231 232 233 /* 234 * Initialize the syntax table with default values. 235 */ 236 237 init() { 238 filltable("CWORD"); 239 syntax[0] = "CEOF"; 240 syntax[base + CTLESC] = "CCTL"; 241 syntax[base + CTLVAR] = "CCTL"; 242 syntax[base + CTLENDVAR] = "CCTL"; 243 syntax[base + CTLBACKQ] = "CCTL"; 244 syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL"; 245 syntax[base + CTLARI] = "CCTL"; 246 syntax[base + CTLENDARI] = "CCTL"; 247 } 248 249 250 /* 251 * Add entries to the syntax table. 252 */ 253 254 add(p, type) 255 char *p, *type; 256 { 257 while (*p) 258 syntax[*p++ + base] = type; 259 } 260 261 262 263 /* 264 * Output the syntax table. 265 */ 266 267 print(name) 268 char *name; 269 { 270 int i; 271 int col; 272 273 fprintf(hfile, "extern const char %s[];\n", name); 274 fprintf(cfile, "const char %s[%d] = {\n", name, size); 275 col = 0; 276 for (i = 0 ; i < size ; i++) { 277 if (i == 0) { 278 fputs(" ", cfile); 279 } else if ((i & 03) == 0) { 280 fputs(",\n ", cfile); 281 col = 0; 282 } else { 283 putc(',', cfile); 284 while (++col < 9 * (i & 03)) 285 putc(' ', cfile); 286 } 287 fputs(syntax[i], cfile); 288 col += strlen(syntax[i]); 289 } 290 fputs("\n};\n", cfile); 291 } 292 293 294 295 /* 296 * Output character classification macros (e.g. is_digit). If digits are 297 * contiguous, we can test for them quickly. 298 */ 299 300 char *macro[] = { 301 "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)", 302 "#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))", 303 "#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))", 304 "#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))", 305 "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))", 306 NULL 307 }; 308 309 output_type_macros() { 310 char **pp; 311 312 if (digit_contig) 313 macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)"; 314 for (pp = macro ; *pp ; pp++) 315 fprintf(hfile, "%s\n", *pp); 316 if (digit_contig) 317 fputs("#define digit_val(c)\t((c) - '0')\n", hfile); 318 else 319 fputs("#define digit_val(c)\t(digit_value[c])\n", hfile); 320 } 321 322 323 324 /* 325 * Output digit conversion table (if digits are not contiguous). 326 */ 327 328 digit_convert() { 329 int maxdigit; 330 static char digit[] = "0123456789"; 331 char *p; 332 int i; 333 334 maxdigit = 0; 335 for (p = digit ; *p ; p++) 336 if (*p > maxdigit) 337 maxdigit = *p; 338 fputs("extern const char digit_value[];\n", hfile); 339 fputs("\n\nconst char digit_value[] = {\n", cfile); 340 for (i = 0 ; i <= maxdigit ; i++) { 341 for (p = digit ; *p && *p != i ; p++); 342 if (*p == '\0') 343 p = digit; 344 fprintf(cfile, " %d,\n", p - digit); 345 } 346 fputs("};\n", cfile); 347 } 348