Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | 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 <string.h>
  60. #include <sys/types.h>
  61. #include "../parser.h"
  62.  
  63.  
  64. struct synclass {
  65.     char *name;
  66.     char *comment;
  67. };
  68.  
  69. /* Syntax classes */
  70. struct synclass synclass[] = {
  71.     { "CWORD",  "character is nothing special" },
  72.     { "CNL",    "newline character" },
  73.     { "CBACK",  "a backslash character" },
  74.     { "CSQUOTE",    "single quote" },
  75.     { "CDQUOTE",    "double quote" },
  76.     { "CENDQUOTE",  "a terminating quote" },
  77.     { "CBQUOTE",    "backwards single quote" },
  78.     { "CVAR",   "a dollar sign" },
  79.     { "CENDVAR",    "a '}' character" },
  80.     { "CLP",    "a left paren in arithmetic" },
  81.     { "CRP",    "a right paren in arithmetic" },
  82.     { "CEOF",   "end of file" },
  83.     { "CCTL",   "like CWORD, except it must be escaped" },
  84.     { "CSPCL",  "these terminate a word" },
  85.     { NULL,     NULL }
  86. };
  87.  
  88.  
  89. /*
  90.  * Syntax classes for is_ functions.  Warning:  if you add new classes
  91.  * you may have to change the definition of the is_in_name macro.
  92.  */
  93. struct synclass is_entry[] = {
  94.     { "ISDIGIT",    "a digit" },
  95.     { "ISUPPER",    "an upper case letter" },
  96.     { "ISLOWER",    "a lower case letter" },
  97.     { "ISUNDER",    "an underscore" },
  98.     { "ISSPECL",    "the name of a special parameter" },
  99.     { NULL,     NULL }
  100. };
  101.  
  102. static char writer[] = "\
  103. /*\n\
  104. * This file was generated by the mksyntax program.\n\
  105. */\n\
  106. \n";
  107.  
  108.  
  109. static FILE *cfile;
  110. static FILE *hfile;
  111. static char *syntax[513];
  112. static int base;
  113. static int size;    /* number of values which a char variable can have */
  114. static int nbits;   /* number of bits in a character */
  115. static int digit_contig;/* true if digits are contiguous */
  116.  
  117. static void filltable(char *);
  118. static void init(void);
  119. static void add(char *, char *);
  120. static void print(char *);
  121. static void output_type_macros(void);
  122. static void digit_convert(void);
  123. int main(int, char **);
  124.  
  125. int
  126. main(argc, argv)
  127.     int argc;
  128.     char **argv;
  129. {
  130. #ifdef  TARGET_CHAR
  131.     TARGET_CHAR c;
  132.     TARGET_CHAR d;
  133. #else
  134.     char c;
  135.     char d;
  136. #endif
  137.     int sign;
  138.     int i;
  139.     char buf[80];
  140.     int pos;
  141.     static char digit[] = "0123456789";
  142.  
  143.     /* Create output files */
  144.     if ((cfile = fopen("syntax.c", "w")) == NULL) {
  145.         perror("syntax.c");
  146.         exit(2);
  147.     }
  148.     if ((hfile = fopen("syntax.h", "w")) == NULL) {
  149.         perror("syntax.h");
  150.         exit(2);
  151.     }
  152.     fputs(writer, hfile);
  153.     fputs(writer, cfile);
  154.  
  155.     /* Determine the characteristics of chars. */
  156.     c = -1;
  157.     if (c <= 0)
  158.         sign = 1;
  159.     else
  160.         sign = 0;
  161.     for (nbits = 1 ; ; nbits++) {
  162.         d = (1 << nbits) - 1;
  163.         if (d == c)
  164.             break;
  165.     }
  166.     printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
  167.     if (nbits > 9) {
  168.         fputs("Characters can't have more than 9 bits\n", stderr);
  169.         exit(2);
  170.     }
  171.     size = (1 << nbits) + 1;
  172.     base = 1;
  173.     if (sign)
  174.         base += 1 << (nbits - 1);
  175.     digit_contig = 1;
  176.     for (i = 0 ; i < 10 ; i++) {
  177.         if (digit[i] != '0' + i)
  178.             digit_contig = 0;
  179.     }
  180.  
  181.     fputs("#include <sys/cdefs.h>\n", hfile);
  182.     fputs("#include <ctype.h>\n", hfile);
  183.  
  184.     /* Generate the #define statements in the header file */
  185.     fputs("/* Syntax classes */\n", hfile);
  186.     for (i = 0 ; synclass[i].name ; i++) {
  187.         sprintf(buf, "#define %s %d", synclass[i].name, i);
  188.         fputs(buf, hfile);
  189.         for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
  190.             putc('\t', hfile);
  191.         fprintf(hfile, "/* %s */\n", synclass[i].comment);
  192.     }
  193.     putc('\n', hfile);
  194.     fputs("/* Syntax classes for is_ functions */\n", hfile);
  195.     for (i = 0 ; is_entry[i].name ; i++) {
  196.         sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
  197.         fputs(buf, hfile);
  198.         for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
  199.             putc('\t', hfile);
  200.         fprintf(hfile, "/* %s */\n", is_entry[i].comment);
  201.     }
  202.     putc('\n', hfile);
  203.     fprintf(hfile, "#define SYNBASE %d\n", base);
  204.     fprintf(hfile, "#define PEOF %d\n\n", -base);
  205.     if (sign)
  206.         fprintf(hfile, "#define UPEOF %d\n\n", -base);
  207.     else
  208.         fprintf(hfile, "#define UPEOF ((unsigned char) %d)\n\n", -base);
  209.     putc('\n', hfile);
  210.     fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
  211.     fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
  212.     fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
  213.     fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
  214.     putc('\n', hfile);
  215.     output_type_macros();       /* is_digit, etc. */
  216.     putc('\n', hfile);
  217.  
  218.     /* Generate the syntax tables. */
  219.     fputs("#include \"shell.h\"\n", cfile);
  220.     fputs("#include \"syntax.h\"\n\n", cfile);
  221.     init();
  222.     fputs("/* syntax table used when not in quotes */\n", cfile);
  223.     add("\n", "CNL");
  224.     add("\\", "CBACK");
  225.     add("'", "CSQUOTE");
  226.     add("\"", "CDQUOTE");
  227.     add("`", "CBQUOTE");
  228.     add("$", "CVAR");
  229.     add("}", "CENDVAR");
  230.     add("<>();&| \t", "CSPCL");
  231.     print("basesyntax");
  232.     init();
  233.     fputs("\n/* syntax table used when in double quotes */\n", cfile);
  234.     add("\n", "CNL");
  235.     add("\\", "CBACK");
  236.     add("\"", "CENDQUOTE");
  237.     add("`", "CBQUOTE");
  238.     add("$", "CVAR");
  239.     add("}", "CENDVAR");
  240.     /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
  241.     add("!*?[=~:/-]", "CCTL");
  242.     print("dqsyntax");
  243.     init();
  244.     fputs("\n/* syntax table used when in single quotes */\n", cfile);
  245.     add("\n", "CNL");
  246.     add("'", "CENDQUOTE");
  247.     /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
  248.     add("!*?[=~:/-]\\", "CCTL");
  249.     print("sqsyntax");
  250.     init();
  251.     fputs("\n/* syntax table used when in arithmetic */\n", cfile);
  252.     add("\n", "CNL");
  253.     add("\\", "CBACK");
  254.     add("`", "CBQUOTE");
  255.     add("'", "CSQUOTE");
  256.     add("\"", "CDQUOTE");
  257.     add("$", "CVAR");
  258.     add("}", "CENDVAR");
  259.     add("(", "CLP");
  260.     add(")", "CRP");
  261.     print("arisyntax");
  262.     filltable("0");
  263.     fputs("\n/* character classification table */\n", cfile);
  264.     add("0123456789", "ISDIGIT");
  265.     add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
  266.     add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
  267.     add("_", "ISUNDER");
  268.     add("#?$!-*@", "ISSPECL");
  269.     print("is_type");
  270.     if (! digit_contig)
  271.         digit_convert();
  272.     exit(0);
  273.     /* NOTREACHED */
  274. }
  275.  
  276.  
  277.  
  278. /*
  279.  * Clear the syntax table.
  280.  */
  281.  
  282. static void
  283. filltable(dftval)
  284.     char *dftval;
  285. {
  286.     int i;
  287.  
  288.     for (i = 0 ; i < size ; i++)
  289.         syntax[i] = dftval;
  290. }
  291.  
  292.  
  293. /*
  294.  * Initialize the syntax table with default values.
  295.  */
  296.  
  297. static void
  298. init()
  299. {
  300.     filltable("CWORD");
  301.     syntax[0] = "CEOF";
  302. #ifdef TARGET_CHAR
  303.     syntax[base + (TARGET_CHAR)CTLESC] = "CCTL";
  304.     syntax[base + (TARGET_CHAR)CTLVAR] = "CCTL";
  305.     syntax[base + (TARGET_CHAR)CTLENDVAR] = "CCTL";
  306.     syntax[base + (TARGET_CHAR)CTLBACKQ] = "CCTL";
  307.     syntax[base + (TARGET_CHAR)CTLBACKQ + (TARGET_CHAR)CTLQUOTE] = "CCTL";
  308.     syntax[base + (TARGET_CHAR)CTLARI] = "CCTL";
  309.     syntax[base + (TARGET_CHAR)CTLENDARI] = "CCTL";
  310.     syntax[base + (TARGET_CHAR)CTLQUOTEMARK] = "CCTL";
  311. #else
  312.     syntax[base + CTLESC] = "CCTL";
  313.     syntax[base + CTLVAR] = "CCTL";
  314.     syntax[base + CTLENDVAR] = "CCTL";
  315.     syntax[base + CTLBACKQ] = "CCTL";
  316.     syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
  317.     syntax[base + CTLARI] = "CCTL";
  318.     syntax[base + CTLENDARI] = "CCTL";
  319.     syntax[base + CTLQUOTEMARK] = "CCTL";
  320. #endif /* TARGET_CHAR */
  321. }
  322.  
  323.  
  324. /*
  325.  * Add entries to the syntax table.
  326.  */
  327.  
  328. static void
  329. add(p, type)
  330.     char *p, *type;
  331. {
  332.     while (*p)
  333.         syntax[*p++ + base] = type;
  334. }
  335.  
  336.  
  337.  
  338. /*
  339.  * Output the syntax table.
  340.  */
  341.  
  342. static void
  343. print(name)
  344.     char *name;
  345. {
  346.     int i;
  347.     int col;
  348.  
  349.     fprintf(hfile, "extern const char %s[];\n", name);
  350.     fprintf(cfile, "const char %s[%d] = {\n", name, size);
  351.     col = 0;
  352.     for (i = 0 ; i < size ; i++) {
  353.         if (i == 0) {
  354.             fputs("      ", cfile);
  355.         } else if ((i & 03) == 0) {
  356.             fputs(",\n      ", cfile);
  357.             col = 0;
  358.         } else {
  359.             putc(',', cfile);
  360.             while (++col < 9 * (i & 03))
  361.                 putc(' ', cfile);
  362.         }
  363.         fputs(syntax[i], cfile);
  364.         col += strlen(syntax[i]);
  365.     }
  366.     fputs("\n};\n", cfile);
  367. }
  368.  
  369.  
  370.  
  371. /*
  372.  * Output character classification macros (e.g. is_digit).  If digits are
  373.  * contiguous, we can test for them quickly.
  374.  */
  375.  
  376. static char *macro[] = {
  377.     "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
  378.     "#define is_alpha(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
  379.     "#define is_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
  380.     "#define is_in_name(c)\t((c) != UPEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
  381.     "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
  382.     NULL
  383. };
  384.  
  385. static void
  386. output_type_macros()
  387. {
  388.     char **pp;
  389.  
  390.     if (digit_contig)
  391.         macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
  392.     for (pp = macro ; *pp ; pp++)
  393.         fprintf(hfile, "%s\n", *pp);
  394.     if (digit_contig)
  395.         fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
  396.     else
  397.         fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
  398. }
  399.  
  400.  
  401.  
  402. /*
  403.  * Output digit conversion table (if digits are not contiguous).
  404.  */
  405.  
  406. static void
  407. digit_convert()
  408. {
  409.     int maxdigit;
  410.     static char digit[] = "0123456789";
  411.     char *p;
  412.     int i;
  413.  
  414.     maxdigit = 0;
  415.     for (p = digit ; *p ; p++)
  416.         if (*p > maxdigit)
  417.             maxdigit = *p;
  418.     fputs("extern const char digit_value[];\n", hfile);
  419.     fputs("\n\nconst char digit_value[] = {\n", cfile);
  420.     for (i = 0 ; i <= maxdigit ; i++) {
  421.         for (p = digit ; *p && *p != i ; p++);
  422.         if (*p == '\0')
  423.             p = digit;
  424.         fprintf(cfile, "      %ld,\n", (long)(p - digit));
  425.     }
  426.     fputs("};\n", cfile);
  427. }
  428.