mksyntax.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1991 The Regents of the University of California.
00003  * All rights reserved.
00004  *
00005  * This code is derived from software contributed to Berkeley by
00006  * Kenneth Almquist.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. All advertising materials mentioning features or use of this software
00017  *    must display the following acknowledgement:
00018  *      This product includes software developed by the University of
00019  *      California, Berkeley and its contributors.
00020  * 4. Neither the name of the University nor the names of its contributors
00021  *    may be used to endorse or promote products derived from this software
00022  *    without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00025  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00027  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00028  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00030  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00031  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00033  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00034  * SUCH DAMAGE.
00035  */
00036 
00037 #ifndef lint
00038 char copyright[] =
00039 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\
00040  All rights reserved.\n";
00041 #endif /* not lint */
00042 
00043 #ifndef lint
00044 static char sccsid[] = "@(#)mksyntax.c  5.2 (Berkeley) 3/8/91";
00045 #endif /* not lint */
00046 
00047 /*
00048  * This program creates syntax.h and syntax.c.
00049  */
00050 
00051 #include <stdio.h>
00052 #include "parser.h"
00053 
00054 
00055 struct synclass {
00056         char *name;
00057         char *comment;
00058 };
00059 
00060 /* Syntax classes */
00061 struct synclass synclass[] = {
00062         "CWORD",                "character is nothing special",
00063         "CNL",          "newline character",
00064         "CBACK",                "a backslash character",
00065         "CSQUOTE",      "single quote",
00066         "CDQUOTE",      "double quote",
00067         "CENDQUOTE",    "a terminating quote",
00068         "CBQUOTE",      "backwards single quote",
00069         "CVAR",         "a dollar sign",
00070         "CENDVAR",      "a '}' character",
00071         "CEOF",         "end of file",
00072         "CCTL",         "like CWORD, except it must be escaped",
00073         "CSPCL",                "these terminate a word",
00074         NULL, NULL
00075 };
00076 
00077 
00078 /*
00079  * Syntax classes for is_ functions.  Warning:  if you add new classes
00080  * you may have to change the definition of the is_in_name macro.
00081  */
00082 struct synclass is_entry[] = {
00083         "ISDIGIT",      "a digit",
00084         "ISUPPER",      "an upper case letter",
00085         "ISLOWER",      "a lower case letter",
00086         "ISUNDER",      "an underscore",
00087         "ISSPECL",      "the name of a special parameter",
00088         NULL, NULL,
00089 };
00090 
00091 char writer[] = "\
00092 /*\n\
00093  * This file was generated by the mksyntax program.\n\
00094  */\n\
00095 \n";
00096 
00097 
00098 FILE *cfile;
00099 FILE *hfile;
00100 char *syntax[513];
00101 int base;
00102 int size;               /* number of values which a char variable can have */
00103 int nbits;              /* number of bits in a character */
00104 int digit_contig;       /* true if digits are contiguous */
00105 
00106 
00107 main() {
00108         char c;
00109         char d;
00110         int sign;
00111         int i;
00112         char buf[80];
00113         int pos;
00114         static char digit[] = "0123456789";
00115 
00116         /* Create output files */
00117         if ((cfile = fopen("syntax.c", "w")) == NULL) {
00118                 perror("syntax.c");
00119                 exit(2);
00120         }
00121         if ((hfile = fopen("syntax.h", "w")) == NULL) {
00122                 perror("syntax.h");
00123                 exit(2);
00124         }
00125         fputs(writer, hfile);
00126         fputs(writer, cfile);
00127 
00128         /* Determine the characteristics of chars. */
00129         c = -1;
00130         if (c < 0)
00131                 sign = 1;
00132         else
00133                 sign = 0;
00134         for (nbits = 1 ; ; nbits++) {
00135                 d = (1 << nbits) - 1;
00136                 if (d == c)
00137                         break;
00138         }
00139         printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
00140         if (nbits > 9) {
00141                 fputs("Characters can't have more than 9 bits\n", stderr);
00142                 exit(2);
00143         }
00144         size = (1 << nbits) + 1;
00145         base = 1;
00146         if (sign)
00147                 base += 1 << (nbits - 1);
00148         digit_contig = 1;
00149         for (i = 0 ; i < 10 ; i++) {
00150                 if (digit[i] != '0' + i)
00151                         digit_contig = 0;
00152         }
00153 
00154         fputs("#include <sys/cdefs.h>\n", hfile);
00155 
00156         /* Generate the #define statements in the header file */
00157         fputs("/* Syntax classes */\n", hfile);
00158         for (i = 0 ; synclass[i].name ; i++) {
00159                 sprintf(buf, "#define %s %d", synclass[i].name, i);
00160                 fputs(buf, hfile);
00161                 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
00162                         putc('\t', hfile);
00163                 fprintf(hfile, "/* %s */\n", synclass[i].comment);
00164         }
00165         putc('\n', hfile);
00166         fputs("/* Syntax classes for is_ functions */\n", hfile);
00167         for (i = 0 ; is_entry[i].name ; i++) {
00168                 sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
00169                 fputs(buf, hfile);
00170                 for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
00171                         putc('\t', hfile);
00172                 fprintf(hfile, "/* %s */\n", is_entry[i].comment);
00173         }
00174         putc('\n', hfile);
00175         fprintf(hfile, "#define SYNBASE %d\n", base);
00176         fprintf(hfile, "#define PEOF %d\n\n", -base);
00177         putc('\n', hfile);
00178         fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
00179         fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
00180         fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
00181         putc('\n', hfile);
00182         output_type_macros();           /* is_digit, etc. */
00183         putc('\n', hfile);
00184 
00185         /* Generate the syntax tables. */
00186         fputs("#include \"shell.h\"\n", cfile);
00187         fputs("#include \"syntax.h\"\n\n", cfile);
00188         init();
00189         fputs("/* syntax table used when not in quotes */\n", cfile);
00190         add("\n", "CNL");
00191         add("\\", "CBACK");
00192         add("'", "CSQUOTE");
00193         add("\"", "CDQUOTE");
00194         add("`", "CBQUOTE");
00195         add("$", "CVAR");
00196         add("}", "CENDVAR");
00197         add("<>();&| \t", "CSPCL");
00198         print("basesyntax");
00199         init();
00200         fputs("\n/* syntax table used when in double quotes */\n", cfile);
00201         add("\n", "CNL");
00202         add("\\", "CBACK");
00203         add("\"", "CENDQUOTE");
00204         add("`", "CBQUOTE");
00205         add("$", "CVAR");
00206         add("}", "CENDVAR");
00207         add("!*?[=", "CCTL");
00208         print("dqsyntax");
00209         init();
00210         fputs("\n/* syntax table used when in single quotes */\n", cfile);
00211         add("\n", "CNL");
00212         add("'", "CENDQUOTE");
00213         add("!*?[=", "CCTL");
00214         print("sqsyntax");
00215         filltable("0");
00216         fputs("\n/* character classification table */\n", cfile);
00217         add("0123456789", "ISDIGIT");
00218         add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
00219         add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
00220         add("_", "ISUNDER");
00221         add("#?$!-*@", "ISSPECL");
00222         print("is_type");
00223         if (! digit_contig)
00224                 digit_convert();
00225         exit(0);
00226 }
00227 
00228 
00229 
00230 /*
00231  * Clear the syntax table.
00232  */
00233 
00234 filltable(dftval)
00235         char *dftval;
00236         {
00237         int i;
00238 
00239         for (i = 0 ; i < size ; i++)
00240                 syntax[i] = dftval;
00241 }
00242 
00243 
00244 /*
00245  * Initialize the syntax table with default values.
00246  */
00247 
00248 init() {
00249         filltable("CWORD");
00250         syntax[0] = "CEOF";
00251         syntax[base + CTLESC] = "CCTL";
00252         syntax[base + CTLVAR] = "CCTL";
00253         syntax[base + CTLENDVAR] = "CCTL";
00254         syntax[base + CTLBACKQ] = "CCTL";
00255         syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
00256 }
00257 
00258 
00259 /*
00260  * Add entries to the syntax table.
00261  */
00262 
00263 add(p, type)
00264         char *p, *type;
00265         {
00266         while (*p)
00267                 syntax[*p++ + base] = type;
00268 }
00269 
00270 
00271 
00272 /*
00273  * Output the syntax table.
00274  */
00275 
00276 print(name)
00277         char *name;
00278         {
00279         int i;
00280         int col;
00281 
00282         fprintf(hfile, "extern const char %s[];\n", name);
00283         fprintf(cfile, "const char %s[%d] = {\n", name, size);
00284         col = 0;
00285         for (i = 0 ; i < size ; i++) {
00286                 if (i == 0) {
00287                         fputs("      ", cfile);
00288                 } else if ((i & 03) == 0) {
00289                         fputs(",\n      ", cfile);
00290                         col = 0;
00291                 } else {
00292                         putc(',', cfile);
00293                         while (++col < 9 * (i & 03))
00294                                 putc(' ', cfile);
00295                 }
00296                 fputs(syntax[i], cfile);
00297                 col += strlen(syntax[i]);
00298         }
00299         fputs("\n};\n", cfile);
00300 }
00301 
00302 
00303 
00304 /*
00305  * Output character classification macros (e.g. is_digit).  If digits are
00306  * contiguous, we can test for them quickly.
00307  */
00308 
00309 char *macro[] = {
00310         "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
00311         "#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
00312         "#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
00313         "#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
00314         "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
00315         NULL
00316 };
00317 
00318 output_type_macros() {
00319         char **pp;
00320 
00321         if (digit_contig)
00322                 macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
00323         for (pp = macro ; *pp ; pp++)
00324                 fprintf(hfile, "%s\n", *pp);
00325         if (digit_contig)
00326                 fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
00327         else
00328                 fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
00329 }
00330 
00331 
00332 
00333 /*
00334  * Output digit conversion table (if digits are not contiguous).
00335  */
00336 
00337 digit_convert() {
00338         int maxdigit;
00339         static char digit[] = "0123456789";
00340         char *p;
00341         int i;
00342 
00343         maxdigit = 0;
00344         for (p = digit ; *p ; p++)
00345                 if (*p > maxdigit)
00346                         maxdigit = *p;
00347         fputs("extern const char digit_value[];\n", hfile);
00348         fputs("\n\nconst char digit_value[] = {\n", cfile);
00349         for (i = 0 ; i <= maxdigit ; i++) {
00350                 for (p = digit ; *p && *p != i ; p++);
00351                 if (*p == '\0')
00352                         p = digit;
00353                 fprintf(cfile, "      %d,\n", p - digit);
00354         }
00355         fputs("};\n", cfile);
00356 }

Generated on Fri Apr 14 22:56:41 2006 for minix by  doxygen 1.4.6