mksyntax.c revision 214305
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 * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 33114433Sobrien#if 0 341556Srgrimes#ifndef lint 3520425Sstevestatic char const copyright[] = 361556Srgrimes"@(#) Copyright (c) 1991, 1993\n\ 371556Srgrimes The Regents of the University of California. All rights reserved.\n"; 381556Srgrimes#endif /* not lint */ 391556Srgrimes 401556Srgrimes#ifndef lint 4136150Scharnierstatic char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95"; 42114433Sobrien#endif /* not lint */ 4336150Scharnier#endif 4499110Sobrien#include <sys/cdefs.h> 4599110Sobrien__FBSDID("$FreeBSD: head/bin/sh/mksyntax.c 214305 2010-10-24 22:25:38Z jilles $"); 461556Srgrimes 471556Srgrimes/* 481556Srgrimes * This program creates syntax.h and syntax.c. 491556Srgrimes */ 501556Srgrimes 511556Srgrimes#include <stdio.h> 5278469Sdes#include <stdlib.h> 5317987Speter#include <string.h> 541556Srgrimes#include "parser.h" 551556Srgrimes 561556Srgrimes 571556Srgrimesstruct synclass { 58201053Sjilles const char *name; 59201053Sjilles const char *comment; 601556Srgrimes}; 611556Srgrimes 621556Srgrimes/* Syntax classes */ 631556Srgrimesstruct synclass synclass[] = { 6417987Speter { "CWORD", "character is nothing special" }, 6517987Speter { "CNL", "newline character" }, 6617987Speter { "CBACK", "a backslash character" }, 6717987Speter { "CSQUOTE", "single quote" }, 6817987Speter { "CDQUOTE", "double quote" }, 6917987Speter { "CENDQUOTE", "a terminating quote" }, 7017987Speter { "CBQUOTE", "backwards single quote" }, 7117987Speter { "CVAR", "a dollar sign" }, 7217987Speter { "CENDVAR", "a '}' character" }, 7317987Speter { "CLP", "a left paren in arithmetic" }, 7417987Speter { "CRP", "a right paren in arithmetic" }, 7517987Speter { "CEOF", "end of file" }, 7617987Speter { "CCTL", "like CWORD, except it must be escaped" }, 7717987Speter { "CSPCL", "these terminate a word" }, 78214305Sjilles { "CIGN", "character should be ignored" }, 7917987Speter { NULL, NULL } 801556Srgrimes}; 811556Srgrimes 821556Srgrimes 831556Srgrimes/* 841556Srgrimes * Syntax classes for is_ functions. Warning: if you add new classes 851556Srgrimes * you may have to change the definition of the is_in_name macro. 861556Srgrimes */ 871556Srgrimesstruct synclass is_entry[] = { 8817987Speter { "ISDIGIT", "a digit" }, 8917987Speter { "ISUPPER", "an upper case letter" }, 9017987Speter { "ISLOWER", "a lower case letter" }, 9117987Speter { "ISUNDER", "an underscore" }, 9217987Speter { "ISSPECL", "the name of a special parameter" }, 9317987Speter { NULL, NULL } 941556Srgrimes}; 951556Srgrimes 9617987Speterstatic char writer[] = "\ 971556Srgrimes/*\n\ 981556Srgrimes * This file was generated by the mksyntax program.\n\ 991556Srgrimes */\n\ 1001556Srgrimes\n"; 1011556Srgrimes 1021556Srgrimes 10317987Speterstatic FILE *cfile; 10417987Speterstatic FILE *hfile; 105201053Sjillesstatic const char *syntax[513]; 10617987Speterstatic int base; 10717987Speterstatic int size; /* number of values which a char variable can have */ 10817987Speterstatic int nbits; /* number of bits in a character */ 10917987Speterstatic int digit_contig;/* true if digits are contiguous */ 1101556Srgrimes 111201053Sjillesstatic void filltable(const char *); 11290111Simpstatic void init(void); 113201053Sjillesstatic void add(const char *, const char *); 114201053Sjillesstatic void print(const char *); 11590111Simpstatic void output_type_macros(void); 11690111Simpstatic void digit_convert(void); 1171556Srgrimes 11817987Speterint 11990111Simpmain(int argc __unused, char **argv __unused) 12017987Speter{ 1211556Srgrimes char c; 1221556Srgrimes char d; 1231556Srgrimes int sign; 1241556Srgrimes int i; 1251556Srgrimes char buf[80]; 1261556Srgrimes int pos; 1271556Srgrimes static char digit[] = "0123456789"; 1281556Srgrimes 1291556Srgrimes /* Create output files */ 1301556Srgrimes if ((cfile = fopen("syntax.c", "w")) == NULL) { 1311556Srgrimes perror("syntax.c"); 1321556Srgrimes exit(2); 1331556Srgrimes } 1341556Srgrimes if ((hfile = fopen("syntax.h", "w")) == NULL) { 1351556Srgrimes perror("syntax.h"); 1361556Srgrimes exit(2); 1371556Srgrimes } 1381556Srgrimes fputs(writer, hfile); 1391556Srgrimes fputs(writer, cfile); 1401556Srgrimes 1411556Srgrimes /* Determine the characteristics of chars. */ 1421556Srgrimes c = -1; 143176392Smarcel sign = (c > 0) ? 0 : 1; 1441556Srgrimes for (nbits = 1 ; ; nbits++) { 1451556Srgrimes d = (1 << nbits) - 1; 1461556Srgrimes if (d == c) 1471556Srgrimes break; 1481556Srgrimes } 14920425Ssteve#if 0 1501556Srgrimes printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits); 15120425Ssteve#endif 1521556Srgrimes if (nbits > 9) { 1531556Srgrimes fputs("Characters can't have more than 9 bits\n", stderr); 1541556Srgrimes exit(2); 1551556Srgrimes } 1561556Srgrimes size = (1 << nbits) + 1; 1571556Srgrimes base = 1; 1581556Srgrimes if (sign) 1591556Srgrimes base += 1 << (nbits - 1); 1601556Srgrimes digit_contig = 1; 1611556Srgrimes for (i = 0 ; i < 10 ; i++) { 1621556Srgrimes if (digit[i] != '0' + i) 1631556Srgrimes digit_contig = 0; 1641556Srgrimes } 1651556Srgrimes 16620425Ssteve fputs("#include <sys/cdefs.h>\n", hfile); 16717525Sache fputs("#include <ctype.h>\n", hfile); 1681556Srgrimes 1691556Srgrimes /* Generate the #define statements in the header file */ 1701556Srgrimes fputs("/* Syntax classes */\n", hfile); 1711556Srgrimes for (i = 0 ; synclass[i].name ; i++) { 1721556Srgrimes sprintf(buf, "#define %s %d", synclass[i].name, i); 1731556Srgrimes fputs(buf, hfile); 17417987Speter for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1751556Srgrimes putc('\t', hfile); 1761556Srgrimes fprintf(hfile, "/* %s */\n", synclass[i].comment); 1771556Srgrimes } 1781556Srgrimes putc('\n', hfile); 1791556Srgrimes fputs("/* Syntax classes for is_ functions */\n", hfile); 1801556Srgrimes for (i = 0 ; is_entry[i].name ; i++) { 1811556Srgrimes sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); 1821556Srgrimes fputs(buf, hfile); 18317987Speter for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1841556Srgrimes putc('\t', hfile); 1851556Srgrimes fprintf(hfile, "/* %s */\n", is_entry[i].comment); 1861556Srgrimes } 1871556Srgrimes putc('\n', hfile); 1881556Srgrimes fprintf(hfile, "#define SYNBASE %d\n", base); 1891556Srgrimes fprintf(hfile, "#define PEOF %d\n\n", -base); 1901556Srgrimes putc('\n', hfile); 1911556Srgrimes fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); 1921556Srgrimes fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); 1931556Srgrimes fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); 1941556Srgrimes fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); 1951556Srgrimes putc('\n', hfile); 1961556Srgrimes output_type_macros(); /* is_digit, etc. */ 1971556Srgrimes putc('\n', hfile); 1981556Srgrimes 1991556Srgrimes /* Generate the syntax tables. */ 2001556Srgrimes fputs("#include \"shell.h\"\n", cfile); 2011556Srgrimes fputs("#include \"syntax.h\"\n\n", cfile); 2021556Srgrimes init(); 2031556Srgrimes fputs("/* syntax table used when not in quotes */\n", cfile); 2041556Srgrimes add("\n", "CNL"); 2051556Srgrimes add("\\", "CBACK"); 2061556Srgrimes add("'", "CSQUOTE"); 2071556Srgrimes add("\"", "CDQUOTE"); 2081556Srgrimes add("`", "CBQUOTE"); 2091556Srgrimes add("$", "CVAR"); 2101556Srgrimes add("}", "CENDVAR"); 2111556Srgrimes add("<>();&| \t", "CSPCL"); 2121556Srgrimes print("basesyntax"); 2131556Srgrimes init(); 2141556Srgrimes fputs("\n/* syntax table used when in double quotes */\n", cfile); 2151556Srgrimes add("\n", "CNL"); 2161556Srgrimes add("\\", "CBACK"); 2171556Srgrimes add("\"", "CENDQUOTE"); 2181556Srgrimes add("`", "CBQUOTE"); 2191556Srgrimes add("$", "CVAR"); 2201556Srgrimes add("}", "CENDVAR"); 22117987Speter /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 22217987Speter add("!*?[=~:/-", "CCTL"); 2231556Srgrimes print("dqsyntax"); 2241556Srgrimes init(); 2251556Srgrimes fputs("\n/* syntax table used when in single quotes */\n", cfile); 2261556Srgrimes add("\n", "CNL"); 2271556Srgrimes add("'", "CENDQUOTE"); 22817987Speter /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 22917987Speter add("!*?[=~:/-", "CCTL"); 2301556Srgrimes print("sqsyntax"); 2311556Srgrimes init(); 2321556Srgrimes fputs("\n/* syntax table used when in arithmetic */\n", cfile); 2331556Srgrimes add("\n", "CNL"); 2341556Srgrimes add("\\", "CBACK"); 2351556Srgrimes add("`", "CBQUOTE"); 236214305Sjilles add("\"", "CIGN"); 2371556Srgrimes add("$", "CVAR"); 2381556Srgrimes add("}", "CENDVAR"); 2391556Srgrimes add("(", "CLP"); 2401556Srgrimes add(")", "CRP"); 2411556Srgrimes print("arisyntax"); 2421556Srgrimes filltable("0"); 2431556Srgrimes fputs("\n/* character classification table */\n", cfile); 2441556Srgrimes add("0123456789", "ISDIGIT"); 245211084Sjilles add("abcdefghijklmnopqrstuvwxyz", "ISLOWER"); 246211084Sjilles add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER"); 2471556Srgrimes add("_", "ISUNDER"); 2481556Srgrimes add("#?$!-*@", "ISSPECL"); 2491556Srgrimes print("is_type"); 2501556Srgrimes if (! digit_contig) 2511556Srgrimes digit_convert(); 2521556Srgrimes exit(0); 2531556Srgrimes} 2541556Srgrimes 2551556Srgrimes 2561556Srgrimes 2571556Srgrimes/* 2581556Srgrimes * Clear the syntax table. 2591556Srgrimes */ 2601556Srgrimes 26117987Speterstatic void 262201053Sjillesfilltable(const char *dftval) 26317987Speter{ 2641556Srgrimes int i; 2651556Srgrimes 2661556Srgrimes for (i = 0 ; i < size ; i++) 2671556Srgrimes syntax[i] = dftval; 2681556Srgrimes} 2691556Srgrimes 2701556Srgrimes 2711556Srgrimes/* 2721556Srgrimes * Initialize the syntax table with default values. 2731556Srgrimes */ 2741556Srgrimes 27517987Speterstatic void 27690111Simpinit(void) 27717987Speter{ 2781556Srgrimes filltable("CWORD"); 2791556Srgrimes syntax[0] = "CEOF"; 2801556Srgrimes syntax[base + CTLESC] = "CCTL"; 2811556Srgrimes syntax[base + CTLVAR] = "CCTL"; 2821556Srgrimes syntax[base + CTLENDVAR] = "CCTL"; 2831556Srgrimes syntax[base + CTLBACKQ] = "CCTL"; 2841556Srgrimes syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL"; 2851556Srgrimes syntax[base + CTLARI] = "CCTL"; 2861556Srgrimes syntax[base + CTLENDARI] = "CCTL"; 28738887Stegge syntax[base + CTLQUOTEMARK] = "CCTL"; 2881556Srgrimes} 2891556Srgrimes 2901556Srgrimes 2911556Srgrimes/* 2921556Srgrimes * Add entries to the syntax table. 2931556Srgrimes */ 2941556Srgrimes 29517987Speterstatic void 296201053Sjillesadd(const char *p, const char *type) 29717987Speter{ 2981556Srgrimes while (*p) 2991556Srgrimes syntax[*p++ + base] = type; 3001556Srgrimes} 3011556Srgrimes 3021556Srgrimes 3031556Srgrimes 3041556Srgrimes/* 3051556Srgrimes * Output the syntax table. 3061556Srgrimes */ 3071556Srgrimes 30817987Speterstatic void 309201053Sjillesprint(const char *name) 31017987Speter{ 3111556Srgrimes int i; 3121556Srgrimes int col; 3131556Srgrimes 3141556Srgrimes fprintf(hfile, "extern const char %s[];\n", name); 3151556Srgrimes fprintf(cfile, "const char %s[%d] = {\n", name, size); 3161556Srgrimes col = 0; 3171556Srgrimes for (i = 0 ; i < size ; i++) { 3181556Srgrimes if (i == 0) { 3191556Srgrimes fputs(" ", cfile); 3201556Srgrimes } else if ((i & 03) == 0) { 3211556Srgrimes fputs(",\n ", cfile); 3221556Srgrimes col = 0; 3231556Srgrimes } else { 3241556Srgrimes putc(',', cfile); 3251556Srgrimes while (++col < 9 * (i & 03)) 3261556Srgrimes putc(' ', cfile); 3271556Srgrimes } 3281556Srgrimes fputs(syntax[i], cfile); 3291556Srgrimes col += strlen(syntax[i]); 3301556Srgrimes } 3311556Srgrimes fputs("\n};\n", cfile); 3321556Srgrimes} 3331556Srgrimes 3341556Srgrimes 3351556Srgrimes 3361556Srgrimes/* 3371556Srgrimes * Output character classification macros (e.g. is_digit). If digits are 3381556Srgrimes * contiguous, we can test for them quickly. 3391556Srgrimes */ 3401556Srgrimes 341201053Sjillesstatic const char *macro[] = { 342212190Sjilles "#define is_digit(c)\t((is_type+SYNBASE)[(int)c] & ISDIGIT)", 343149026Sstefanf "#define is_eof(c)\t((c) == PEOF)", 344212190Sjilles "#define is_alpha(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && (is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER))", 345212190Sjilles "#define is_name(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && (is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER))", 346212190Sjilles "#define is_in_name(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && (is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))", 347212190Sjilles "#define is_special(c)\t((is_type+SYNBASE)[(int)c] & (ISSPECL|ISDIGIT))", 3481556Srgrimes NULL 3491556Srgrimes}; 3501556Srgrimes 35117987Speterstatic void 35290111Simpoutput_type_macros(void) 35317987Speter{ 354201053Sjilles const char **pp; 3551556Srgrimes 3561556Srgrimes if (digit_contig) 357193225Srse macro[0] = "#define is_digit(c)\t((unsigned int)((c) - '0') <= 9)"; 3581556Srgrimes for (pp = macro ; *pp ; pp++) 3591556Srgrimes fprintf(hfile, "%s\n", *pp); 3601556Srgrimes if (digit_contig) 3611556Srgrimes fputs("#define digit_val(c)\t((c) - '0')\n", hfile); 3621556Srgrimes else 3631556Srgrimes fputs("#define digit_val(c)\t(digit_value[c])\n", hfile); 3641556Srgrimes} 3651556Srgrimes 3661556Srgrimes 3671556Srgrimes 3681556Srgrimes/* 3691556Srgrimes * Output digit conversion table (if digits are not contiguous). 3701556Srgrimes */ 3711556Srgrimes 37217987Speterstatic void 37390111Simpdigit_convert(void) 37417987Speter{ 3751556Srgrimes int maxdigit; 3761556Srgrimes static char digit[] = "0123456789"; 3771556Srgrimes char *p; 3781556Srgrimes int i; 3791556Srgrimes 3801556Srgrimes maxdigit = 0; 3811556Srgrimes for (p = digit ; *p ; p++) 3821556Srgrimes if (*p > maxdigit) 3831556Srgrimes maxdigit = *p; 3841556Srgrimes fputs("extern const char digit_value[];\n", hfile); 3851556Srgrimes fputs("\n\nconst char digit_value[] = {\n", cfile); 3861556Srgrimes for (i = 0 ; i <= maxdigit ; i++) { 3871556Srgrimes for (p = digit ; *p && *p != i ; p++); 3881556Srgrimes if (*p == '\0') 3891556Srgrimes p = digit; 390104367Stjr fprintf(cfile, " %d,\n", (int)(p - digit)); 3911556Srgrimes } 3921556Srgrimes fputs("};\n", cfile); 3931556Srgrimes} 394