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