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