Subversion Repositories HelenOS

Rev

Rev 2716 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*  $NetBSD: mksyntax.c,v 1.23 2000/07/18 19:13:21 cgd Exp $    */
  2.  
  3. /*-
  4.  * Copyright (c) 1991, 1993
  5.  *  The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Kenneth Almquist.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *  This product includes software developed by the University of
  21.  *  California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. #ifndef lint
  40. static const char copyright[] =
  41.     "@(#) Copyright (c) 1991, 1993\n\
  42.     The Regents of the University of California.  All rights reserved.\n";
  43. #endif /* not lint */
  44.  
  45. #ifndef lint
  46. #if 0
  47. static char sccsid[] = "@(#)mksyntax.c  8.2 (Berkeley) 5/4/95";
  48. #else
  49. static const char rcsid[] =
  50.     "$NetBSD: mksyntax.c,v 1.23 2000/07/18 19:13:21 cgd Exp $";
  51. #endif
  52. #endif /* not lint */
  53.  
  54. /*
  55.  * This program creates syntax.h and syntax.c.
  56.  */
  57.  
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <sys/types.h>
  62. #include "../parser.h"
  63.  
  64.  
  65. struct synclass {
  66.     char *name;
  67.     char *comment;
  68. };
  69.  
  70. /* Syntax classes */
  71. struct synclass synclass[] = {
  72.     { "CWORD",  "character is nothing special" },
  73.     { "CNL",    "newline character" },
  74.     { "CBACK",  "a backslash character" },
  75.     { "CSQUOTE",    "single quote" },
  76.     { "CDQUOTE",    "double quote" },
  77.     { "CENDQUOTE",  "a terminating quote" },
  78.     { "CBQUOTE",    "backwards single quote" },
  79.     { "CVAR",   "a dollar sign" },
  80.     { "CENDVAR",    "a '}' character" },
  81.     { "CLP",    "a left paren in arithmetic" },
  82.     { "CRP",    "a right paren in arithmetic" },
  83.     { "CEOF",   "end of file" },
  84.     { "CCTL",   "like CWORD, except it must be escaped" },
  85.     { "CSPCL",  "these terminate a word" },
  86.     { NULL,     NULL }
  87. };
  88.  
  89.  
  90. /*
  91.  * Syntax classes for is_ functions.  Warning:  if you add new classes
  92.  * you may have to change the definition of the is_in_name macro.
  93.  */
  94. struct synclass is_entry[] = {
  95.     { "ISDIGIT",    "a digit" },
  96.     { "ISUPPER",    "an upper case letter" },
  97.     { "ISLOWER",    "a lower case letter" },
  98.     { "ISUNDER",    "an underscore" },
  99.     { "ISSPECL",    "the name of a special parameter" },
  100.     { NULL,     NULL }
  101. };
  102.  
  103. static char writer[] = "\
  104. /*\n\
  105. * This file was generated by the mksyntax program.\n\
  106. */\n\
  107. \n";
  108.  
  109.  
  110. static FILE *cfile;
  111. static FILE *hfile;
  112. static char *syntax[513];
  113. static int base;
  114. static int size;    /* number of values which a char variable can have */
  115. static int nbits;   /* number of bits in a character */
  116. static int digit_contig;/* true if digits are contiguous */
  117.  
  118. static void filltable(char *);
  119. static void init(void);
  120. static void add(char *, char *);
  121. static void print(char *);
  122. static void output_type_macros(void);
  123. static void digit_convert(void);
  124. int main(int, char **);
  125.  
  126. int
  127. main(argc, argv)
  128.     int argc;
  129.     char **argv;
  130. {
  131. #ifdef  TARGET_CHAR
  132.     TARGET_CHAR c;
  133.     TARGET_CHAR d;
  134. #else
  135.     char c;
  136.     char d;
  137. #endif
  138.     int sign;
  139.     int i;
  140.     char buf[80];
  141.     int pos;
  142.     static char digit[] = "0123456789";
  143.  
  144.     /* Create output files */
  145.     if ((cfile = fopen("syntax.c", "w")) == NULL) {
  146.         perror("syntax.c");
  147.         exit(2);
  148.     }
  149.     if ((hfile = fopen("syntax.h", "w")) == NULL) {
  150.         perror("syntax.h");
  151.         exit(2);
  152.     }
  153.     fputs(writer, hfile);
  154.     fputs(writer, cfile);
  155.  
  156.     /* Determine the characteristics of chars. */
  157.     c = -1;
  158.     if (c <= 0)
  159.         sign = 1;
  160.     else
  161.         sign = 0;
  162.     for (nbits = 1 ; ; nbits++) {
  163.         d = (1 << nbits) - 1;
  164.         if (d == c)
  165.             break;
  166.     }
  167.     printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
  168.     if (nbits > 9) {
  169.         fputs("Characters can't have more than 9 bits\n", stderr);
  170.         exit(2);
  171.     }
  172.     size = (1 << nbits) + 1;
  173.     base = 1;
  174.     if (sign)
  175.         base += 1 << (nbits - 1);
  176.     digit_contig = 1;
  177.     for (i = 0 ; i < 10 ; i++) {
  178.         if (digit[i] != '0' + i)
  179.             digit_contig = 0;
  180.     }
  181.  
  182.     fputs("#include <sys/cdefs.h>\n", hfile);
  183.     fputs("#include <ctype.h>\n", hfile);
  184.  
  185.     /* Generate the #define statements in the header file */
  186.     fputs("/* Syntax classes */\n", hfile);
  187.     for (i = 0 ; synclass[i].name ; i++) {
  188.         sprintf(buf, "#define %s %d", synclass[i].name, i);
  189.         fputs(buf, hfile);
  190.         for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
  191.             putc('\t', hfile);
  192.         fprintf(hfile, "/* %s */\n", synclass[i].comment);
  193.     }
  194.     putc('\n', hfile);
  195.     fputs("/* Syntax classes for is_ functions */\n", hfile);
  196.     for (i = 0 ; is_entry[i].name ; i++) {
  197.         sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
  198.         fputs(buf, hfile);
  199.         for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
  200.             putc('\t', hfile);
  201.         fprintf(hfile, "/* %s */\n", is_entry[i].comment);
  202.     }
  203.     putc('\n', hfile);
  204.     fprintf(hfile, "#define SYNBASE %d\n", base);
  205.     fprintf(hfile, "#define PEOF %d\n\n", -base);
  206.     if (sign)
  207.         fprintf(hfile, "#define UPEOF %d\n\n", -base);
  208.     else
  209.         fprintf(hfile, "#define UPEOF ((unsigned char) %d)\n\n", -base);
  210.     putc('\n', hfile);
  211.     fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
  212.     fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
  213.     fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
  214.     fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
  215.     putc('\n', hfile);
  216.     output_type_macros();       /* is_digit, etc. */
  217.     putc('\n', hfile);
  218.  
  219.     /* Generate the syntax tables. */
  220.     fputs("#include \"shell.h\"\n", cfile);
  221.     fputs("#include \"syntax.h\"\n\n", cfile);
  222.     init();
  223.     fputs("/* syntax table used when not in quotes */\n", cfile);
  224.     add("\n", "CNL");
  225.     add("\\", "CBACK");
  226.     add("'", "CSQUOTE");
  227.     add("\"", "CDQUOTE");
  228.     add("`", "CBQUOTE");
  229.     add("$", "CVAR");
  230.     add("}", "CENDVAR");
  231.     add("<>();&| \t", "CSPCL");
  232.     print("basesyntax");
  233.     init();
  234.     fputs("\n/* syntax table used when in double quotes */\n", cfile);
  235.     add("\n", "CNL");
  236.     add("\\", "CBACK");
  237.     add("\"", "CENDQUOTE");
  238.     add("`", "CBQUOTE");
  239.     add("$", "CVAR");
  240.     add("}", "CENDVAR");
  241.     /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
  242.     add("!*?[=~:/-]", "CCTL");
  243.     print("dqsyntax");
  244.     init();
  245.     fputs("\n/* syntax table used when in single quotes */\n", cfile);
  246.     add("\n", "CNL");
  247.     add("'", "CENDQUOTE");
  248.     /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
  249.     add("!*?[=~:/-]\\", "CCTL");
  250.     print("sqsyntax");
  251.     init();
  252.     fputs("\n/* syntax table used when in arithmetic */\n", cfile);
  253.     add("\n", "CNL");
  254.     add("\\", "CBACK");
  255.     add("`", "CBQUOTE");
  256.     add("'", "CSQUOTE");
  257.     add("\"", "CDQUOTE");
  258.     add("$", "CVAR");
  259.     add("}", "CENDVAR");
  260.     add("(", "CLP");
  261.     add(")", "CRP");
  262.     print("arisyntax");
  263.     filltable("0");
  264.     fputs("\n/* character classification table */\n", cfile);
  265.     add("0123456789", "ISDIGIT");
  266.     add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
  267.     add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
  268.     add("_", "ISUNDER");
  269.     add("#?$!-*@", "ISSPECL");
  270.     print("is_type");
  271.     if (! digit_contig)
  272.         digit_convert();
  273.     exit(0);
  274.     /* NOTREACHED */
  275. }
  276.  
  277.  
  278.  
  279. /*
  280.  * Clear the syntax table.
  281.  */
  282.  
  283. static void
  284. filltable(dftval)
  285.     char *dftval;
  286. {
  287.     int i;
  288.  
  289.     for (i = 0 ; i < size ; i++)
  290.         syntax[i] = dftval;
  291. }
  292.  
  293.  
  294. /*
  295.  * Initialize the syntax table with default values.
  296.  */
  297.  
  298. static void
  299. init()
  300. {
  301.     filltable("CWORD");
  302.     syntax[0] = "CEOF";
  303. #ifdef TARGET_CHAR
  304.     syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
  305.     syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
  306.     syntax[base + (TARGET_CHAR)CTLENDVAR] = "CCTL";
  307.     syntax[base + (TARGET_CHAR)CTLBACKQ] = "CCTL";
  308.     syntax[base + (TARGET_CHAR)CTLBACKQ + (TARGET_CHAR)CTLQUOTE] = "CCTL";
  309.     syntax[base + (TARGET_CHAR)CTLARI] = "CCTL";
  310.     syntax[base + (TARGET_CHAR)CTLENDARI] = "CCTL";
  311.     syntax[base + (TARGET_CHAR)CTLQUOTEMARK] = "CCTL";
  312. #else
  313.     syntax[base + CTLESC] = "CCTL";
  314.     syntax[base + CTLVAR] = "CCTL";
  315.     syntax[base + CTLENDVAR] = "CCTL";
  316.     syntax[base + CTLBACKQ] = "CCTL";
  317.     syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
  318.     syntax[base + CTLARI] = "CCTL";
  319.     syntax[base + CTLENDARI] = "CCTL";
  320.     syntax[base + CTLQUOTEMARK] = "CCTL";
  321. #endif /* TARGET_CHAR */
  322. }
  323.  
  324.  
  325. /*
  326.  * Add entries to the syntax table.
  327.  */
  328.  
  329. static void
  330. add(p, type)
  331.     char *p, *type;
  332. {
  333.     while (*p)
  334.         syntax[*p++ + base] = type;
  335. }
  336.  
  337.  
  338.  
  339. /*
  340.  * Output the syntax table.
  341.  */
  342.  
  343. static void
  344. print(name)
  345.     char *name;
  346. {
  347.     int i;
  348.     int col;
  349.  
  350.     fprintf(hfile, "extern const char %s[];\n", name);
  351.     fprintf(cfile, "const char %s[%d] = {\n", name, size);
  352.     col = 0;
  353.     for (i = 0 ; i < size ; i++) {
  354.         if (i == 0) {
  355.             fputs("      ", cfile);
  356.         } else if ((i & 03) == 0) {
  357.             fputs(",\n      ", cfile);
  358.             col = 0;
  359.         } else {
  360.             putc(',', cfile);
  361.             while (++col < 9 * (i & 03))
  362.                 putc(' ', cfile);
  363.         }
  364.         fputs(syntax[i], cfile);
  365.         col += strlen(syntax[i]);
  366.     }
  367.     fputs("\n};\n", cfile);
  368. }
  369.  
  370.  
  371.  
  372. /*
  373.  * Output character classification macros (e.g. is_digit).  If digits are
  374.  * contiguous, we can test for them quickly.
  375.  */
  376.  
  377. static char *macro[] = {
  378.     "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
  379.     "#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
  380.     "#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
  381.     "#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
  382.     "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
  383.     NULL
  384. };
  385.  
  386. static void
  387. output_type_macros()
  388. {
  389.     char **pp;
  390.  
  391.     if (digit_contig)
  392.         macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
  393.     for (pp = macro ; *pp ; pp++)
  394.         fprintf(hfile, "%s\n", *pp);
  395.     if (digit_contig)
  396.         fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
  397.     else
  398.         fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
  399. }
  400.  
  401.  
  402.  
  403. /*
  404.  * Output digit conversion table (if digits are not contiguous).
  405.  */
  406.  
  407. static void
  408. digit_convert()
  409. {
  410.     int maxdigit;
  411.     static char digit[] = "0123456789";
  412.     char *p;
  413.     int i;
  414.  
  415.     maxdigit = 0;
  416.     for (p = digit ; *p ; p++)
  417.         if (*p > maxdigit)
  418.             maxdigit = *p;
  419.     fputs("extern const char digit_value[];\n", hfile);
  420.     fputs("\n\nconst char digit_value[] = {\n", cfile);
  421.     for (i = 0 ; i <= maxdigit ; i++) {
  422.         for (p = digit ; *p && *p != i ; p++);
  423.         if (*p == '\0')
  424.             p = digit;
  425.         fprintf(cfile, "      %ld,\n", (long)(p - digit));
  426.     }
  427.     fputs("};\n", cfile);
  428. }
  429.