mksyntax.c revision 78469
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 351556Srgrimes */ 361556Srgrimes 371556Srgrimes#ifndef lint 3820425Sstevestatic char const copyright[] = 391556Srgrimes"@(#) Copyright (c) 1991, 1993\n\ 401556Srgrimes The Regents of the University of California. All rights reserved.\n"; 411556Srgrimes#endif /* not lint */ 421556Srgrimes 431556Srgrimes#ifndef lint 4436150Scharnier#if 0 4536150Scharnierstatic char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95"; 4636150Scharnier#endif 4736150Scharnierstatic const char rcsid[] = 4850471Speter "$FreeBSD: head/bin/sh/mksyntax.c 78469 2001-06-19 15:41:57Z des $"; 491556Srgrimes#endif /* not lint */ 501556Srgrimes 511556Srgrimes/* 521556Srgrimes * This program creates syntax.h and syntax.c. 531556Srgrimes */ 541556Srgrimes 551556Srgrimes#include <stdio.h> 5678469Sdes#include <stdlib.h> 5717987Speter#include <string.h> 581556Srgrimes#include "parser.h" 591556Srgrimes 601556Srgrimes 611556Srgrimesstruct synclass { 621556Srgrimes char *name; 631556Srgrimes char *comment; 641556Srgrimes}; 651556Srgrimes 661556Srgrimes/* Syntax classes */ 671556Srgrimesstruct synclass synclass[] = { 6817987Speter { "CWORD", "character is nothing special" }, 6917987Speter { "CNL", "newline character" }, 7017987Speter { "CBACK", "a backslash character" }, 7117987Speter { "CSQUOTE", "single quote" }, 7217987Speter { "CDQUOTE", "double quote" }, 7317987Speter { "CENDQUOTE", "a terminating quote" }, 7417987Speter { "CBQUOTE", "backwards single quote" }, 7517987Speter { "CVAR", "a dollar sign" }, 7617987Speter { "CENDVAR", "a '}' character" }, 7717987Speter { "CLP", "a left paren in arithmetic" }, 7817987Speter { "CRP", "a right paren in arithmetic" }, 7917987Speter { "CEOF", "end of file" }, 8017987Speter { "CCTL", "like CWORD, except it must be escaped" }, 8117987Speter { "CSPCL", "these terminate a word" }, 8217987Speter { NULL, NULL } 831556Srgrimes}; 841556Srgrimes 851556Srgrimes 861556Srgrimes/* 871556Srgrimes * Syntax classes for is_ functions. Warning: if you add new classes 881556Srgrimes * you may have to change the definition of the is_in_name macro. 891556Srgrimes */ 901556Srgrimesstruct synclass is_entry[] = { 9117987Speter { "ISDIGIT", "a digit" }, 9217987Speter { "ISUPPER", "an upper case letter" }, 9317987Speter { "ISLOWER", "a lower case letter" }, 9417987Speter { "ISUNDER", "an underscore" }, 9517987Speter { "ISSPECL", "the name of a special parameter" }, 9617987Speter { NULL, NULL } 971556Srgrimes}; 981556Srgrimes 9917987Speterstatic char writer[] = "\ 1001556Srgrimes/*\n\ 1011556Srgrimes * This file was generated by the mksyntax program.\n\ 1021556Srgrimes */\n\ 1031556Srgrimes\n"; 1041556Srgrimes 1051556Srgrimes 10617987Speterstatic FILE *cfile; 10717987Speterstatic FILE *hfile; 10817987Speterstatic char *syntax[513]; 10917987Speterstatic int base; 11017987Speterstatic int size; /* number of values which a char variable can have */ 11117987Speterstatic int nbits; /* number of bits in a character */ 11217987Speterstatic int digit_contig;/* true if digits are contiguous */ 1131556Srgrimes 11417987Speterstatic void filltable __P((char *)); 11517987Speterstatic void init __P((void)); 11617987Speterstatic void add __P((char *, char *)); 11717987Speterstatic void print __P((char *)); 11817987Speterstatic void output_type_macros __P((void)); 11917987Speterstatic void digit_convert __P((void)); 1201556Srgrimes 12117987Speterint 12217987Spetermain(argc, argv) 12325905Ssteve int argc __unused; 12425905Ssteve char **argv __unused; 12517987Speter{ 1261556Srgrimes char c; 1271556Srgrimes char d; 1281556Srgrimes int sign; 1291556Srgrimes int i; 1301556Srgrimes char buf[80]; 1311556Srgrimes int pos; 1321556Srgrimes static char digit[] = "0123456789"; 1331556Srgrimes 1341556Srgrimes /* Create output files */ 1351556Srgrimes if ((cfile = fopen("syntax.c", "w")) == NULL) { 1361556Srgrimes perror("syntax.c"); 1371556Srgrimes exit(2); 1381556Srgrimes } 1391556Srgrimes if ((hfile = fopen("syntax.h", "w")) == NULL) { 1401556Srgrimes perror("syntax.h"); 1411556Srgrimes exit(2); 1421556Srgrimes } 1431556Srgrimes fputs(writer, hfile); 1441556Srgrimes fputs(writer, cfile); 1451556Srgrimes 1461556Srgrimes /* Determine the characteristics of chars. */ 1471556Srgrimes c = -1; 1481556Srgrimes if (c < 0) 1491556Srgrimes sign = 1; 1501556Srgrimes else 1511556Srgrimes sign = 0; 1521556Srgrimes for (nbits = 1 ; ; nbits++) { 1531556Srgrimes d = (1 << nbits) - 1; 1541556Srgrimes if (d == c) 1551556Srgrimes break; 1561556Srgrimes } 15720425Ssteve#if 0 1581556Srgrimes printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits); 15920425Ssteve#endif 1601556Srgrimes if (nbits > 9) { 1611556Srgrimes fputs("Characters can't have more than 9 bits\n", stderr); 1621556Srgrimes exit(2); 1631556Srgrimes } 1641556Srgrimes size = (1 << nbits) + 1; 1651556Srgrimes base = 1; 1661556Srgrimes if (sign) 1671556Srgrimes base += 1 << (nbits - 1); 1681556Srgrimes digit_contig = 1; 1691556Srgrimes for (i = 0 ; i < 10 ; i++) { 1701556Srgrimes if (digit[i] != '0' + i) 1711556Srgrimes digit_contig = 0; 1721556Srgrimes } 1731556Srgrimes 17420425Ssteve fputs("#include <sys/cdefs.h>\n", hfile); 17517525Sache fputs("#include <ctype.h>\n", hfile); 1761556Srgrimes 1771556Srgrimes /* Generate the #define statements in the header file */ 1781556Srgrimes fputs("/* Syntax classes */\n", hfile); 1791556Srgrimes for (i = 0 ; synclass[i].name ; i++) { 1801556Srgrimes sprintf(buf, "#define %s %d", synclass[i].name, i); 1811556Srgrimes fputs(buf, hfile); 18217987Speter for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1831556Srgrimes putc('\t', hfile); 1841556Srgrimes fprintf(hfile, "/* %s */\n", synclass[i].comment); 1851556Srgrimes } 1861556Srgrimes putc('\n', hfile); 1871556Srgrimes fputs("/* Syntax classes for is_ functions */\n", hfile); 1881556Srgrimes for (i = 0 ; is_entry[i].name ; i++) { 1891556Srgrimes sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); 1901556Srgrimes fputs(buf, hfile); 19117987Speter for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1921556Srgrimes putc('\t', hfile); 1931556Srgrimes fprintf(hfile, "/* %s */\n", is_entry[i].comment); 1941556Srgrimes } 1951556Srgrimes putc('\n', hfile); 1961556Srgrimes fprintf(hfile, "#define SYNBASE %d\n", base); 1971556Srgrimes fprintf(hfile, "#define PEOF %d\n\n", -base); 1981556Srgrimes putc('\n', hfile); 1991556Srgrimes fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); 2001556Srgrimes fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); 2011556Srgrimes fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); 2021556Srgrimes fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); 2031556Srgrimes putc('\n', hfile); 2041556Srgrimes output_type_macros(); /* is_digit, etc. */ 2051556Srgrimes putc('\n', hfile); 2061556Srgrimes 2071556Srgrimes /* Generate the syntax tables. */ 2081556Srgrimes fputs("#include \"shell.h\"\n", cfile); 2091556Srgrimes fputs("#include \"syntax.h\"\n\n", cfile); 2101556Srgrimes init(); 2111556Srgrimes fputs("/* syntax table used when not in quotes */\n", cfile); 2121556Srgrimes add("\n", "CNL"); 2131556Srgrimes add("\\", "CBACK"); 2141556Srgrimes add("'", "CSQUOTE"); 2151556Srgrimes add("\"", "CDQUOTE"); 2161556Srgrimes add("`", "CBQUOTE"); 2171556Srgrimes add("$", "CVAR"); 2181556Srgrimes add("}", "CENDVAR"); 2191556Srgrimes add("<>();&| \t", "CSPCL"); 2201556Srgrimes print("basesyntax"); 2211556Srgrimes init(); 2221556Srgrimes fputs("\n/* syntax table used when in double quotes */\n", cfile); 2231556Srgrimes add("\n", "CNL"); 2241556Srgrimes add("\\", "CBACK"); 2251556Srgrimes add("\"", "CENDQUOTE"); 2261556Srgrimes add("`", "CBQUOTE"); 2271556Srgrimes add("$", "CVAR"); 2281556Srgrimes add("}", "CENDVAR"); 22917987Speter /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 23017987Speter add("!*?[=~:/-", "CCTL"); 2311556Srgrimes print("dqsyntax"); 2321556Srgrimes init(); 2331556Srgrimes fputs("\n/* syntax table used when in single quotes */\n", cfile); 2341556Srgrimes add("\n", "CNL"); 2351556Srgrimes add("'", "CENDQUOTE"); 23617987Speter /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 23717987Speter add("!*?[=~:/-", "CCTL"); 2381556Srgrimes print("sqsyntax"); 2391556Srgrimes init(); 2401556Srgrimes fputs("\n/* syntax table used when in arithmetic */\n", cfile); 2411556Srgrimes add("\n", "CNL"); 2421556Srgrimes add("\\", "CBACK"); 2431556Srgrimes add("`", "CBQUOTE"); 2441556Srgrimes add("'", "CSQUOTE"); 2451556Srgrimes add("\"", "CDQUOTE"); 2461556Srgrimes add("$", "CVAR"); 2471556Srgrimes add("}", "CENDVAR"); 2481556Srgrimes add("(", "CLP"); 2491556Srgrimes add(")", "CRP"); 2501556Srgrimes print("arisyntax"); 2511556Srgrimes filltable("0"); 2521556Srgrimes fputs("\n/* character classification table */\n", cfile); 2531556Srgrimes add("0123456789", "ISDIGIT"); 2541556Srgrimes add("abcdefghijklmnopqrstucvwxyz", "ISLOWER"); 2551556Srgrimes add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER"); 2561556Srgrimes add("_", "ISUNDER"); 2571556Srgrimes add("#?$!-*@", "ISSPECL"); 2581556Srgrimes print("is_type"); 2591556Srgrimes if (! digit_contig) 2601556Srgrimes digit_convert(); 2611556Srgrimes exit(0); 2621556Srgrimes} 2631556Srgrimes 2641556Srgrimes 2651556Srgrimes 2661556Srgrimes/* 2671556Srgrimes * Clear the syntax table. 2681556Srgrimes */ 2691556Srgrimes 27017987Speterstatic void 2711556Srgrimesfilltable(dftval) 2721556Srgrimes char *dftval; 27317987Speter{ 2741556Srgrimes int i; 2751556Srgrimes 2761556Srgrimes for (i = 0 ; i < size ; i++) 2771556Srgrimes syntax[i] = dftval; 2781556Srgrimes} 2791556Srgrimes 2801556Srgrimes 2811556Srgrimes/* 2821556Srgrimes * Initialize the syntax table with default values. 2831556Srgrimes */ 2841556Srgrimes 28517987Speterstatic void 28617987Speterinit() 28717987Speter{ 2881556Srgrimes filltable("CWORD"); 2891556Srgrimes syntax[0] = "CEOF"; 2901556Srgrimes syntax[base + CTLESC] = "CCTL"; 2911556Srgrimes syntax[base + CTLVAR] = "CCTL"; 2921556Srgrimes syntax[base + CTLENDVAR] = "CCTL"; 2931556Srgrimes syntax[base + CTLBACKQ] = "CCTL"; 2941556Srgrimes syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL"; 2951556Srgrimes syntax[base + CTLARI] = "CCTL"; 2961556Srgrimes syntax[base + CTLENDARI] = "CCTL"; 29738887Stegge syntax[base + CTLQUOTEMARK] = "CCTL"; 2981556Srgrimes} 2991556Srgrimes 3001556Srgrimes 3011556Srgrimes/* 3021556Srgrimes * Add entries to the syntax table. 3031556Srgrimes */ 3041556Srgrimes 30517987Speterstatic void 3061556Srgrimesadd(p, type) 3071556Srgrimes char *p, *type; 30817987Speter{ 3091556Srgrimes while (*p) 3101556Srgrimes syntax[*p++ + base] = type; 3111556Srgrimes} 3121556Srgrimes 3131556Srgrimes 3141556Srgrimes 3151556Srgrimes/* 3161556Srgrimes * Output the syntax table. 3171556Srgrimes */ 3181556Srgrimes 31917987Speterstatic void 3201556Srgrimesprint(name) 3211556Srgrimes char *name; 32217987Speter{ 3231556Srgrimes int i; 3241556Srgrimes int col; 3251556Srgrimes 3261556Srgrimes fprintf(hfile, "extern const char %s[];\n", name); 3271556Srgrimes fprintf(cfile, "const char %s[%d] = {\n", name, size); 3281556Srgrimes col = 0; 3291556Srgrimes for (i = 0 ; i < size ; i++) { 3301556Srgrimes if (i == 0) { 3311556Srgrimes fputs(" ", cfile); 3321556Srgrimes } else if ((i & 03) == 0) { 3331556Srgrimes fputs(",\n ", cfile); 3341556Srgrimes col = 0; 3351556Srgrimes } else { 3361556Srgrimes putc(',', cfile); 3371556Srgrimes while (++col < 9 * (i & 03)) 3381556Srgrimes putc(' ', cfile); 3391556Srgrimes } 3401556Srgrimes fputs(syntax[i], cfile); 3411556Srgrimes col += strlen(syntax[i]); 3421556Srgrimes } 3431556Srgrimes fputs("\n};\n", cfile); 3441556Srgrimes} 3451556Srgrimes 3461556Srgrimes 3471556Srgrimes 3481556Srgrimes/* 3491556Srgrimes * Output character classification macros (e.g. is_digit). If digits are 3501556Srgrimes * contiguous, we can test for them quickly. 3511556Srgrimes */ 3521556Srgrimes 35317987Speterstatic char *macro[] = { 35454631Scracauer "#define is_digit(c)\t((c >= 0 && is_type+SYNBASE)[c] & ISDIGIT)", 35517562Sache "#define is_alpha(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))", 35617562Sache "#define is_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))", 35717562Sache "#define is_in_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))", 3581556Srgrimes "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))", 3591556Srgrimes NULL 3601556Srgrimes}; 3611556Srgrimes 36217987Speterstatic void 36320425Ssteveoutput_type_macros() 36417987Speter{ 3651556Srgrimes char **pp; 3661556Srgrimes 3671556Srgrimes if (digit_contig) 3681556Srgrimes macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)"; 3691556Srgrimes for (pp = macro ; *pp ; pp++) 3701556Srgrimes fprintf(hfile, "%s\n", *pp); 3711556Srgrimes if (digit_contig) 3721556Srgrimes fputs("#define digit_val(c)\t((c) - '0')\n", hfile); 3731556Srgrimes else 3741556Srgrimes fputs("#define digit_val(c)\t(digit_value[c])\n", hfile); 3751556Srgrimes} 3761556Srgrimes 3771556Srgrimes 3781556Srgrimes 3791556Srgrimes/* 3801556Srgrimes * Output digit conversion table (if digits are not contiguous). 3811556Srgrimes */ 3821556Srgrimes 38317987Speterstatic void 38420425Sstevedigit_convert() 38517987Speter{ 3861556Srgrimes int maxdigit; 3871556Srgrimes static char digit[] = "0123456789"; 3881556Srgrimes char *p; 3891556Srgrimes int i; 3901556Srgrimes 3911556Srgrimes maxdigit = 0; 3921556Srgrimes for (p = digit ; *p ; p++) 3931556Srgrimes if (*p > maxdigit) 3941556Srgrimes maxdigit = *p; 3951556Srgrimes fputs("extern const char digit_value[];\n", hfile); 3961556Srgrimes fputs("\n\nconst char digit_value[] = {\n", cfile); 3971556Srgrimes for (i = 0 ; i <= maxdigit ; i++) { 3981556Srgrimes for (p = digit ; *p && *p != i ; p++); 3991556Srgrimes if (*p == '\0') 4001556Srgrimes p = digit; 4011556Srgrimes fprintf(cfile, " %d,\n", p - digit); 4021556Srgrimes } 4031556Srgrimes fputs("};\n", cfile); 4041556Srgrimes} 405