mksyntax.c revision 176392
14Srgrimes/*- 24Srgrimes * Copyright (c) 1991, 1993 3295Sjtc * The Regents of the University of California. All rights reserved. 44Srgrimes * 5295Sjtc * This code is derived from software contributed to Berkeley by 6295Sjtc * Kenneth Almquist. 7295Sjtc * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 13295Sjtc * 2. Redistributions in binary form must reproduce the above copyright 1431Salm * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 4. Neither the name of the University nor the names of its contributors 174Srgrimes * may be used to endorse or promote products derived from this software 1831Salm * without specific prior written permission. 194Srgrimes * 204Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 214Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 244Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2531Salm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304Srgrimes * SUCH DAMAGE. 314Srgrimes */ 324Srgrimes 334Srgrimes#if 0 344Srgrimes#ifndef lint 354Srgrimesstatic char const copyright[] = 364Srgrimes"@(#) Copyright (c) 1991, 1993\n\ 374Srgrimes The Regents of the University of California. All rights reserved.\n"; 384Srgrimes#endif /* not lint */ 394Srgrimes 404Srgrimes#ifndef lint 414Srgrimesstatic char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95"; 424Srgrimes#endif /* not lint */ 434Srgrimes#endif 444Srgrimes#include <sys/cdefs.h> 454Srgrimes__FBSDID("$FreeBSD: head/bin/sh/mksyntax.c 176392 2008-02-18 20:01:33Z marcel $"); 464Srgrimes 474Srgrimes/* 484Srgrimes * This program creates syntax.h and syntax.c. 494Srgrimes */ 504Srgrimes 514Srgrimes#include <stdio.h> 524Srgrimes#include <stdlib.h> 534Srgrimes#include <string.h> 544Srgrimes#include "parser.h" 554Srgrimes 564Srgrimes 574Srgrimesstruct synclass { 584Srgrimes char *name; 594Srgrimes char *comment; 604Srgrimes}; 614Srgrimes 624Srgrimes/* Syntax classes */ 634Srgrimesstruct synclass synclass[] = { 644Srgrimes { "CWORD", "character is nothing special" }, 654Srgrimes { "CNL", "newline character" }, 664Srgrimes { "CBACK", "a backslash character" }, 674Srgrimes { "CSQUOTE", "single quote" }, 684Srgrimes { "CDQUOTE", "double quote" }, 694Srgrimes { "CENDQUOTE", "a terminating quote" }, 704Srgrimes { "CBQUOTE", "backwards single quote" }, 714Srgrimes { "CVAR", "a dollar sign" }, 724Srgrimes { "CENDVAR", "a '}' character" }, 734Srgrimes { "CLP", "a left paren in arithmetic" }, 744Srgrimes { "CRP", "a right paren in arithmetic" }, 754Srgrimes { "CEOF", "end of file" }, 764Srgrimes { "CCTL", "like CWORD, except it must be escaped" }, 774Srgrimes { "CSPCL", "these terminate a word" }, 784Srgrimes { NULL, NULL } 794Srgrimes}; 804Srgrimes 814Srgrimes 824Srgrimes/* 834Srgrimes * Syntax classes for is_ functions. Warning: if you add new classes 844Srgrimes * you may have to change the definition of the is_in_name macro. 854Srgrimes */ 864Srgrimesstruct synclass is_entry[] = { 874Srgrimes { "ISDIGIT", "a digit" }, 884Srgrimes { "ISUPPER", "an upper case letter" }, 894Srgrimes { "ISLOWER", "a lower case letter" }, 904Srgrimes { "ISUNDER", "an underscore" }, 914Srgrimes { "ISSPECL", "the name of a special parameter" }, 924Srgrimes { NULL, NULL } 934Srgrimes}; 944Srgrimes 954Srgrimesstatic char writer[] = "\ 96295Sjtc/*\n\ 974Srgrimes * This file was generated by the mksyntax program.\n\ 984Srgrimes */\n\ 994Srgrimes\n"; 1004Srgrimes 1014Srgrimes 1024Srgrimesstatic FILE *cfile; 1034Srgrimesstatic FILE *hfile; 1044Srgrimesstatic char *syntax[513]; 1054Srgrimesstatic int base; 1064Srgrimesstatic int size; /* number of values which a char variable can have */ 1074Srgrimesstatic int nbits; /* number of bits in a character */ 1084Srgrimesstatic int digit_contig;/* true if digits are contiguous */ 1094Srgrimes 1104Srgrimesstatic void filltable(char *); 1114Srgrimesstatic void init(void); 112295Sjtcstatic void add(char *, char *); 1134Srgrimesstatic void print(char *); 1144Srgrimesstatic void output_type_macros(void); 1154Srgrimesstatic void digit_convert(void); 1164Srgrimes 1174Srgrimesint 1184Srgrimesmain(int argc __unused, char **argv __unused) 1194Srgrimes{ 1204Srgrimes char c; 1214Srgrimes char d; 1224Srgrimes int sign; 1234Srgrimes int i; 1244Srgrimes char buf[80]; 1254Srgrimes int pos; 1264Srgrimes static char digit[] = "0123456789"; 1274Srgrimes 1284Srgrimes /* Create output files */ 1294Srgrimes if ((cfile = fopen("syntax.c", "w")) == NULL) { 1304Srgrimes perror("syntax.c"); 1314Srgrimes exit(2); 1324Srgrimes } 1334Srgrimes if ((hfile = fopen("syntax.h", "w")) == NULL) { 1344Srgrimes perror("syntax.h"); 1354Srgrimes exit(2); 1364Srgrimes } 1374Srgrimes fputs(writer, hfile); 1384Srgrimes fputs(writer, cfile); 1394Srgrimes 1404Srgrimes /* Determine the characteristics of chars. */ 1414Srgrimes c = -1; 1424Srgrimes sign = (c > 0) ? 0 : 1; 1434Srgrimes for (nbits = 1 ; ; nbits++) { 1444Srgrimes d = (1 << nbits) - 1; 1454Srgrimes if (d == c) 1464Srgrimes break; 1474Srgrimes } 1484Srgrimes#if 0 1494Srgrimes printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits); 1504Srgrimes#endif 1514Srgrimes if (nbits > 9) { 1524Srgrimes fputs("Characters can't have more than 9 bits\n", stderr); 1534Srgrimes exit(2); 1544Srgrimes } 1554Srgrimes size = (1 << nbits) + 1; 1564Srgrimes base = 1; 1574Srgrimes if (sign) 1584Srgrimes base += 1 << (nbits - 1); 1594Srgrimes digit_contig = 1; 1604Srgrimes for (i = 0 ; i < 10 ; i++) { 1614Srgrimes if (digit[i] != '0' + i) 1624Srgrimes digit_contig = 0; 1634Srgrimes } 1644Srgrimes 1654Srgrimes fputs("#include <sys/cdefs.h>\n", hfile); 1664Srgrimes fputs("#include <ctype.h>\n", hfile); 1674Srgrimes 1684Srgrimes /* Generate the #define statements in the header file */ 1694Srgrimes fputs("/* Syntax classes */\n", hfile); 1704Srgrimes for (i = 0 ; synclass[i].name ; i++) { 1714Srgrimes sprintf(buf, "#define %s %d", synclass[i].name, i); 1724Srgrimes fputs(buf, hfile); 1734Srgrimes for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1744Srgrimes putc('\t', hfile); 175295Sjtc fprintf(hfile, "/* %s */\n", synclass[i].comment); 1764Srgrimes } 1774Srgrimes putc('\n', hfile); 1784Srgrimes fputs("/* Syntax classes for is_ functions */\n", hfile); 1794Srgrimes for (i = 0 ; is_entry[i].name ; i++) { 1804Srgrimes sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); 1814Srgrimes fputs(buf, hfile); 1824Srgrimes for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1834Srgrimes putc('\t', hfile); 1844Srgrimes fprintf(hfile, "/* %s */\n", is_entry[i].comment); 1854Srgrimes } 1864Srgrimes putc('\n', hfile); 1874Srgrimes fprintf(hfile, "#define SYNBASE %d\n", base); 1884Srgrimes fprintf(hfile, "#define PEOF %d\n\n", -base); 1894Srgrimes putc('\n', hfile); 1904Srgrimes fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); 1914Srgrimes fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); 1924Srgrimes fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); 1934Srgrimes fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); 1944Srgrimes putc('\n', hfile); 1954Srgrimes output_type_macros(); /* is_digit, etc. */ 1964Srgrimes putc('\n', hfile); 1974Srgrimes 1984Srgrimes /* Generate the syntax tables. */ 1994Srgrimes fputs("#include \"shell.h\"\n", cfile); 2004Srgrimes fputs("#include \"syntax.h\"\n\n", cfile); 2014Srgrimes init(); 2024Srgrimes fputs("/* syntax table used when not in quotes */\n", cfile); 2034Srgrimes add("\n", "CNL"); 2044Srgrimes add("\\", "CBACK"); 2054Srgrimes add("'", "CSQUOTE"); 2064Srgrimes add("\"", "CDQUOTE"); 2074Srgrimes add("`", "CBQUOTE"); 2084Srgrimes add("$", "CVAR"); 2094Srgrimes add("}", "CENDVAR"); 2104Srgrimes add("<>();&| \t", "CSPCL"); 2114Srgrimes print("basesyntax"); 2124Srgrimes init(); 2134Srgrimes fputs("\n/* syntax table used when in double quotes */\n", cfile); 2144Srgrimes add("\n", "CNL"); 2154Srgrimes add("\\", "CBACK"); 2164Srgrimes add("\"", "CENDQUOTE"); 2174Srgrimes add("`", "CBQUOTE"); 2184Srgrimes add("$", "CVAR"); 2194Srgrimes add("}", "CENDVAR"); 2204Srgrimes /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 2214Srgrimes add("!*?[=~:/-", "CCTL"); 2224Srgrimes print("dqsyntax"); 2234Srgrimes init(); 2244Srgrimes fputs("\n/* syntax table used when in single quotes */\n", cfile); 225181Sconklin add("\n", "CNL"); 2264Srgrimes add("'", "CENDQUOTE"); 2274Srgrimes /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 2284Srgrimes add("!*?[=~:/-", "CCTL"); 2294Srgrimes print("sqsyntax"); 2304Srgrimes init(); 2314Srgrimes fputs("\n/* syntax table used when in arithmetic */\n", cfile); 2324Srgrimes add("\n", "CNL"); 2334Srgrimes add("\\", "CBACK"); 2344Srgrimes add("`", "CBQUOTE"); 2354Srgrimes add("'", "CSQUOTE"); 2364Srgrimes add("\"", "CDQUOTE"); 2374Srgrimes add("$", "CVAR"); 2384Srgrimes add("}", "CENDVAR"); 2394Srgrimes add("(", "CLP"); 2404Srgrimes add(")", "CRP"); 2414Srgrimes print("arisyntax"); 2424Srgrimes filltable("0"); 2434Srgrimes fputs("\n/* character classification table */\n", cfile); 2444Srgrimes add("0123456789", "ISDIGIT"); 2454Srgrimes add("abcdefghijklmnopqrstucvwxyz", "ISLOWER"); 2464Srgrimes add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER"); 2474Srgrimes add("_", "ISUNDER"); 2484Srgrimes add("#?$!-*@", "ISSPECL"); 2494Srgrimes print("is_type"); 2504Srgrimes if (! digit_contig) 2514Srgrimes digit_convert(); 2524Srgrimes exit(0); 2534Srgrimes} 254295Sjtc 2554Srgrimes 2564Srgrimes 2574Srgrimes/* 2584Srgrimes * Clear the syntax table. 2594Srgrimes */ 2604Srgrimes 2614Srgrimesstatic void 2624Srgrimesfilltable(char *dftval) 2634Srgrimes{ 2644Srgrimes int i; 2654Srgrimes 2664Srgrimes for (i = 0 ; i < size ; i++) 2674Srgrimes syntax[i] = dftval; 2684Srgrimes} 2694Srgrimes 2704Srgrimes 2714Srgrimes/* 2724Srgrimes * Initialize the syntax table with default values. 2734Srgrimes */ 2744Srgrimes 2754Srgrimesstatic void 2764Srgrimesinit(void) 2774Srgrimes{ 2784Srgrimes filltable("CWORD"); 2794Srgrimes syntax[0] = "CEOF"; 2804Srgrimes syntax[base + CTLESC] = "CCTL"; 2814Srgrimes syntax[base + CTLVAR] = "CCTL"; 2824Srgrimes syntax[base + CTLENDVAR] = "CCTL"; 2834Srgrimes syntax[base + CTLBACKQ] = "CCTL"; 2844Srgrimes syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL"; 2854Srgrimes syntax[base + CTLARI] = "CCTL"; 2864Srgrimes syntax[base + CTLENDARI] = "CCTL"; 2874Srgrimes syntax[base + CTLQUOTEMARK] = "CCTL"; 2884Srgrimes} 2894Srgrimes 2904Srgrimes 2914Srgrimes/* 2924Srgrimes * Add entries to the syntax table. 2934Srgrimes */ 294295Sjtc 2954Srgrimesstatic void 2964Srgrimesadd(char *p, char *type) 2974Srgrimes{ 2984Srgrimes while (*p) 2994Srgrimes syntax[*p++ + base] = type; 3004Srgrimes} 3014Srgrimes 3024Srgrimes 3034Srgrimes 3044Srgrimes/* 3054Srgrimes * Output the syntax table. 3064Srgrimes */ 3074Srgrimes 3084Srgrimesstatic void 3094Srgrimesprint(char *name) 3104Srgrimes{ 3114Srgrimes int i; 3124Srgrimes int col; 313295Sjtc 3144Srgrimes fprintf(hfile, "extern const char %s[];\n", name); 3154Srgrimes fprintf(cfile, "const char %s[%d] = {\n", name, size); 3164Srgrimes col = 0; 3174Srgrimes for (i = 0 ; i < size ; i++) { 3184Srgrimes if (i == 0) { 3194Srgrimes fputs(" ", cfile); 3204Srgrimes } else if ((i & 03) == 0) { 3214Srgrimes fputs(",\n ", cfile); 3224Srgrimes col = 0; 3234Srgrimes } else { 3244Srgrimes putc(',', cfile); 3254Srgrimes while (++col < 9 * (i & 03)) 3264Srgrimes putc(' ', cfile); 3274Srgrimes } 3284Srgrimes fputs(syntax[i], cfile); 3294Srgrimes col += strlen(syntax[i]); 3304Srgrimes } 3314Srgrimes fputs("\n};\n", cfile); 332295Sjtc} 3334Srgrimes 3344Srgrimes 3354Srgrimes 3364Srgrimes/* 3374Srgrimes * Output character classification macros (e.g. is_digit). If digits are 3384Srgrimes * contiguous, we can test for them quickly. 3394Srgrimes */ 3404Srgrimes 3414Srgrimesstatic char *macro[] = { 3424Srgrimes "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)", 3434Srgrimes "#define is_eof(c)\t((c) == PEOF)", 3444Srgrimes "#define is_alpha(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && isalpha((unsigned char) (c)))", 3454Srgrimes "#define is_name(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalpha((unsigned char) (c))))", 3464Srgrimes "#define is_in_name(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && ((c) == '_' || isalnum((unsigned char) (c))))", 3474Srgrimes "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))", 3484Srgrimes NULL 3494Srgrimes}; 3504Srgrimes 351295Sjtcstatic void 3524Srgrimesoutput_type_macros(void) 3534Srgrimes{ 3544Srgrimes char **pp; 3554Srgrimes 3564Srgrimes if (digit_contig) 3574Srgrimes macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)"; 3584Srgrimes for (pp = macro ; *pp ; pp++) 3594Srgrimes fprintf(hfile, "%s\n", *pp); 3604Srgrimes if (digit_contig) 3614Srgrimes fputs("#define digit_val(c)\t((c) - '0')\n", hfile); 3624Srgrimes else 3634Srgrimes fputs("#define digit_val(c)\t(digit_value[c])\n", hfile); 3644Srgrimes} 3654Srgrimes 3664Srgrimes 3674Srgrimes 3684Srgrimes/* 3694Srgrimes * Output digit conversion table (if digits are not contiguous). 370295Sjtc */ 3714Srgrimes 3724Srgrimesstatic void 3734Srgrimesdigit_convert(void) 3744Srgrimes{ 3754Srgrimes int maxdigit; 3764Srgrimes static char digit[] = "0123456789"; 3774Srgrimes char *p; 3784Srgrimes int i; 3794Srgrimes 3804Srgrimes maxdigit = 0; 3814Srgrimes for (p = digit ; *p ; p++) 3824Srgrimes if (*p > maxdigit) 3834Srgrimes maxdigit = *p; 3844Srgrimes fputs("extern const char digit_value[];\n", hfile); 3854Srgrimes fputs("\n\nconst char digit_value[] = {\n", cfile); 3864Srgrimes for (i = 0 ; i <= maxdigit ; i++) { 3874Srgrimes for (p = digit ; *p && *p != i ; p++); 3884Srgrimes if (*p == '\0') 389295Sjtc p = digit; 3904Srgrimes fprintf(cfile, " %d,\n", (int)(p - digit)); 3914Srgrimes } 3924Srgrimes fputs("};\n", cfile); 3934Srgrimes} 3944Srgrimes