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$"); 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" }, 67221513Sjilles { "CSBACK", "a backslash character in single quotes" }, 6817987Speter { "CSQUOTE", "single quote" }, 6917987Speter { "CDQUOTE", "double quote" }, 7017987Speter { "CENDQUOTE", "a terminating quote" }, 7117987Speter { "CBQUOTE", "backwards single quote" }, 7217987Speter { "CVAR", "a dollar sign" }, 7317987Speter { "CENDVAR", "a '}' character" }, 7417987Speter { "CLP", "a left paren in arithmetic" }, 7517987Speter { "CRP", "a right paren in arithmetic" }, 7617987Speter { "CEOF", "end of file" }, 7717987Speter { "CCTL", "like CWORD, except it must be escaped" }, 7817987Speter { "CSPCL", "these terminate a word" }, 79214305Sjilles { "CIGN", "character should be ignored" }, 8017987Speter { NULL, NULL } 811556Srgrimes}; 821556Srgrimes 831556Srgrimes 841556Srgrimes/* 851556Srgrimes * Syntax classes for is_ functions. Warning: if you add new classes 861556Srgrimes * you may have to change the definition of the is_in_name macro. 871556Srgrimes */ 881556Srgrimesstruct synclass is_entry[] = { 8917987Speter { "ISDIGIT", "a digit" }, 9017987Speter { "ISUPPER", "an upper case letter" }, 9117987Speter { "ISLOWER", "a lower case letter" }, 9217987Speter { "ISUNDER", "an underscore" }, 9317987Speter { "ISSPECL", "the name of a special parameter" }, 9417987Speter { NULL, NULL } 951556Srgrimes}; 961556Srgrimes 9717987Speterstatic char writer[] = "\ 981556Srgrimes/*\n\ 991556Srgrimes * This file was generated by the mksyntax program.\n\ 1001556Srgrimes */\n\ 1011556Srgrimes\n"; 1021556Srgrimes 1031556Srgrimes 10417987Speterstatic FILE *cfile; 10517987Speterstatic FILE *hfile; 1061556Srgrimes 107247163Sjillesstatic void add_default(void); 108247163Sjillesstatic void finish(void); 109247163Sjillesstatic void init(const char *); 110201053Sjillesstatic void add(const char *, const char *); 11190111Simpstatic void output_type_macros(void); 1121556Srgrimes 11317987Speterint 11490111Simpmain(int argc __unused, char **argv __unused) 11517987Speter{ 1161556Srgrimes int i; 1171556Srgrimes char buf[80]; 1181556Srgrimes int pos; 1191556Srgrimes 1201556Srgrimes /* Create output files */ 1211556Srgrimes if ((cfile = fopen("syntax.c", "w")) == NULL) { 1221556Srgrimes perror("syntax.c"); 1231556Srgrimes exit(2); 1241556Srgrimes } 1251556Srgrimes if ((hfile = fopen("syntax.h", "w")) == NULL) { 1261556Srgrimes perror("syntax.h"); 1271556Srgrimes exit(2); 1281556Srgrimes } 1291556Srgrimes fputs(writer, hfile); 1301556Srgrimes fputs(writer, cfile); 1311556Srgrimes 13220425Ssteve fputs("#include <sys/cdefs.h>\n", hfile); 133247163Sjilles fputs("#include <limits.h>\n\n", hfile); 1341556Srgrimes 1351556Srgrimes /* Generate the #define statements in the header file */ 1361556Srgrimes fputs("/* Syntax classes */\n", hfile); 1371556Srgrimes for (i = 0 ; synclass[i].name ; i++) { 1381556Srgrimes sprintf(buf, "#define %s %d", synclass[i].name, i); 1391556Srgrimes fputs(buf, hfile); 14017987Speter for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1411556Srgrimes putc('\t', hfile); 1421556Srgrimes fprintf(hfile, "/* %s */\n", synclass[i].comment); 1431556Srgrimes } 1441556Srgrimes putc('\n', hfile); 1451556Srgrimes fputs("/* Syntax classes for is_ functions */\n", hfile); 1461556Srgrimes for (i = 0 ; is_entry[i].name ; i++) { 1471556Srgrimes sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); 1481556Srgrimes fputs(buf, hfile); 14917987Speter for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) 1501556Srgrimes putc('\t', hfile); 1511556Srgrimes fprintf(hfile, "/* %s */\n", is_entry[i].comment); 1521556Srgrimes } 1531556Srgrimes putc('\n', hfile); 154247163Sjilles fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile); 155247163Sjilles fputs("#define PEOF -SYNBASE\n\n", hfile); 1561556Srgrimes putc('\n', hfile); 1571556Srgrimes fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); 1581556Srgrimes fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); 1591556Srgrimes fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); 1601556Srgrimes fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); 1611556Srgrimes putc('\n', hfile); 1621556Srgrimes output_type_macros(); /* is_digit, etc. */ 1631556Srgrimes putc('\n', hfile); 1641556Srgrimes 1651556Srgrimes /* Generate the syntax tables. */ 166247163Sjilles fputs("#include \"parser.h\"\n", cfile); 1671556Srgrimes fputs("#include \"shell.h\"\n", cfile); 1681556Srgrimes fputs("#include \"syntax.h\"\n\n", cfile); 169247163Sjilles 1701556Srgrimes fputs("/* syntax table used when not in quotes */\n", cfile); 171247163Sjilles init("basesyntax"); 172247163Sjilles add_default(); 1731556Srgrimes add("\n", "CNL"); 1741556Srgrimes add("\\", "CBACK"); 1751556Srgrimes add("'", "CSQUOTE"); 1761556Srgrimes add("\"", "CDQUOTE"); 1771556Srgrimes add("`", "CBQUOTE"); 1781556Srgrimes add("$", "CVAR"); 1791556Srgrimes add("}", "CENDVAR"); 1801556Srgrimes add("<>();&| \t", "CSPCL"); 181247163Sjilles finish(); 182247163Sjilles 1831556Srgrimes fputs("\n/* syntax table used when in double quotes */\n", cfile); 184247163Sjilles init("dqsyntax"); 185247163Sjilles add_default(); 1861556Srgrimes add("\n", "CNL"); 1871556Srgrimes add("\\", "CBACK"); 1881556Srgrimes add("\"", "CENDQUOTE"); 1891556Srgrimes add("`", "CBQUOTE"); 1901556Srgrimes add("$", "CVAR"); 1911556Srgrimes add("}", "CENDVAR"); 19217987Speter /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 19317987Speter add("!*?[=~:/-", "CCTL"); 194247163Sjilles finish(); 195247163Sjilles 1961556Srgrimes fputs("\n/* syntax table used when in single quotes */\n", cfile); 197247163Sjilles init("sqsyntax"); 198247163Sjilles add_default(); 1991556Srgrimes add("\n", "CNL"); 200221513Sjilles add("\\", "CSBACK"); 2011556Srgrimes add("'", "CENDQUOTE"); 20217987Speter /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ 20317987Speter add("!*?[=~:/-", "CCTL"); 204247163Sjilles finish(); 205247163Sjilles 2061556Srgrimes fputs("\n/* syntax table used when in arithmetic */\n", cfile); 207247163Sjilles init("arisyntax"); 208247163Sjilles add_default(); 2091556Srgrimes add("\n", "CNL"); 2101556Srgrimes add("\\", "CBACK"); 2111556Srgrimes add("`", "CBQUOTE"); 212214305Sjilles add("\"", "CIGN"); 2131556Srgrimes add("$", "CVAR"); 2141556Srgrimes add("}", "CENDVAR"); 2151556Srgrimes add("(", "CLP"); 2161556Srgrimes add(")", "CRP"); 217247163Sjilles finish(); 218247163Sjilles 2191556Srgrimes fputs("\n/* character classification table */\n", cfile); 220247163Sjilles init("is_type"); 2211556Srgrimes add("0123456789", "ISDIGIT"); 222211084Sjilles add("abcdefghijklmnopqrstuvwxyz", "ISLOWER"); 223211084Sjilles add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER"); 2241556Srgrimes add("_", "ISUNDER"); 2251556Srgrimes add("#?$!-*@", "ISSPECL"); 226247163Sjilles finish(); 227247163Sjilles 2281556Srgrimes exit(0); 2291556Srgrimes} 2301556Srgrimes 2311556Srgrimes 2321556Srgrimes/* 233247163Sjilles * Output the header and declaration of a syntax table. 2341556Srgrimes */ 2351556Srgrimes 23617987Speterstatic void 237247163Sjillesinit(const char *name) 23817987Speter{ 239247163Sjilles fprintf(hfile, "extern const char %s[];\n", name); 240247163Sjilles fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name); 241247163Sjilles} 2421556Srgrimes 243247163Sjilles 244247163Sjillesstatic void 245247163Sjillesadd_one(const char *key, const char *type) 246247163Sjilles{ 247247163Sjilles fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type); 2481556Srgrimes} 2491556Srgrimes 2501556Srgrimes 2511556Srgrimes/* 252247163Sjilles * Add default values to the syntax table. 2531556Srgrimes */ 2541556Srgrimes 25517987Speterstatic void 256247163Sjillesadd_default(void) 25717987Speter{ 258247163Sjilles add_one("PEOF", "CEOF"); 259247163Sjilles add_one("CTLESC", "CCTL"); 260247163Sjilles add_one("CTLVAR", "CCTL"); 261247163Sjilles add_one("CTLENDVAR", "CCTL"); 262247163Sjilles add_one("CTLBACKQ", "CCTL"); 263247163Sjilles add_one("CTLBACKQ + CTLQUOTE", "CCTL"); 264247163Sjilles add_one("CTLARI", "CCTL"); 265247163Sjilles add_one("CTLENDARI", "CCTL"); 266247163Sjilles add_one("CTLQUOTEMARK", "CCTL"); 267247163Sjilles add_one("CTLQUOTEEND", "CCTL"); 2681556Srgrimes} 2691556Srgrimes 2701556Srgrimes 2711556Srgrimes/* 272247163Sjilles * Output the footer of a syntax table. 2731556Srgrimes */ 2741556Srgrimes 27517987Speterstatic void 276247163Sjillesfinish(void) 27717987Speter{ 278247163Sjilles fputs("};\n", cfile); 2791556Srgrimes} 2801556Srgrimes 2811556Srgrimes 2821556Srgrimes/* 283247163Sjilles * Add entries to the syntax table. 2841556Srgrimes */ 2851556Srgrimes 28617987Speterstatic void 287247163Sjillesadd(const char *p, const char *type) 28817987Speter{ 289247163Sjilles for (; *p; ++p) { 290247163Sjilles char c = *p; 291247163Sjilles switch (c) { 292247163Sjilles case '\t': c = 't'; break; 293247163Sjilles case '\n': c = 'n'; break; 294247163Sjilles case '\'': c = '\''; break; 295247163Sjilles case '\\': c = '\\'; break; 2961556Srgrimes 297247163Sjilles default: 298247163Sjilles fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type); 299247163Sjilles continue; 3001556Srgrimes } 301247163Sjilles fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type); 3021556Srgrimes } 3031556Srgrimes} 3041556Srgrimes 3051556Srgrimes 3061556Srgrimes/* 3071556Srgrimes * Output character classification macros (e.g. is_digit). If digits are 3081556Srgrimes * contiguous, we can test for them quickly. 3091556Srgrimes */ 3101556Srgrimes 311201053Sjillesstatic const char *macro[] = { 312247058Sjilles "#define is_digit(c)\t((unsigned int)((c) - '0') <= 9)", 313149026Sstefanf "#define is_eof(c)\t((c) == PEOF)", 314215568Sjilles "#define is_alpha(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER))", 315215568Sjilles "#define is_name(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER))", 316215568Sjilles "#define is_in_name(c)\t((is_type+SYNBASE)[(int)c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))", 317212190Sjilles "#define is_special(c)\t((is_type+SYNBASE)[(int)c] & (ISSPECL|ISDIGIT))", 318247058Sjilles "#define digit_val(c)\t((c) - '0')", 3191556Srgrimes NULL 3201556Srgrimes}; 3211556Srgrimes 32217987Speterstatic void 32390111Simpoutput_type_macros(void) 32417987Speter{ 325201053Sjilles const char **pp; 3261556Srgrimes 3271556Srgrimes for (pp = macro ; *pp ; pp++) 3281556Srgrimes fprintf(hfile, "%s\n", *pp); 3291556Srgrimes} 330