Subversion Repositories HelenOS

Rev

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

  1. /*  $NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 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[] = "@(#)mknodes.c   8.2 (Berkeley) 5/4/95";
  48. #else
  49. static const char rcsid[] =
  50.     "$NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $";
  51. #endif
  52. #endif /* not lint */
  53.  
  54. /*
  55.  * This program reads the nodetypes file and nodes.c.pat file.  It generates
  56.  * the files nodes.h and nodes.c.
  57.  */
  58.  
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #ifdef __STDC__
  63. #include <stdarg.h>
  64. #else
  65. #include <varargs.h>
  66. #endif
  67.  
  68.  
  69. #define MAXTYPES 50     /* max number of node types */
  70. #define MAXFIELDS 20        /* max fields in a structure */
  71. #define BUFLEN 100      /* size of character buffers */
  72.  
  73. /* field types */
  74. #define T_NODE 1        /* union node *field */
  75. #define T_NODELIST 2        /* struct nodelist *field */
  76. #define T_STRING 3
  77. #define T_INT 4         /* int field */
  78. #define T_OTHER 5       /* other */
  79. #define T_TEMP 6        /* don't copy this field */
  80.  
  81.  
  82. struct field {          /* a structure field */
  83.     char *name;     /* name of field */
  84.     int type;           /* type of field */
  85.     char *decl;     /* declaration of field */
  86. };
  87.  
  88.  
  89. struct str {            /* struct representing a node structure */
  90.     char *tag;      /* structure tag */
  91.     int nfields;        /* number of fields in the structure */
  92.     struct field field[MAXFIELDS];  /* the fields of the structure */
  93.     int done;           /* set if fully parsed */
  94. };
  95.  
  96.  
  97. static int ntypes;          /* number of node types */
  98. static char *nodename[MAXTYPES];    /* names of the nodes */
  99. static struct str *nodestr[MAXTYPES];   /* type of structure used by the node */
  100. static int nstr;            /* number of structures */
  101. static struct str str[MAXTYPES];    /* the structures */
  102. static struct str *curstr;      /* current structure */
  103. static FILE *infp;
  104. static char line[1024];
  105. static int linno;
  106. static char *linep;
  107.  
  108. static void parsenode(void);
  109. static void parsefield(void);
  110. static void output(char *);
  111. static void outsizes(FILE *);
  112. static void outfunc(FILE *, int);
  113. static void indent(int, FILE *);
  114. static int nextfield(char *);
  115. static void skipbl(void);
  116. static int readline(void);
  117. static void error(const char *, ...);
  118. static char *savestr(const char *);
  119. int main(int, char **);
  120.  
  121.  
  122. int
  123. main(argc, argv)
  124.     int argc;
  125.     char **argv;
  126. {
  127.  
  128.     /*
  129.      * some versions of linux complain: initializer element is not
  130.      * constant if this is done at compile time.
  131.      */
  132.     infp = stdin;
  133.  
  134.     if (argc != 3)
  135.         error("usage: mknodes file");
  136.     if ((infp = fopen(argv[1], "r")) == NULL)
  137.         error("Can't open %s", argv[1]);
  138.     while (readline()) {
  139.         if (line[0] == ' ' || line[0] == '\t')
  140.             parsefield();
  141.         else if (line[0] != '\0')
  142.             parsenode();
  143.     }
  144.     output(argv[2]);
  145.     exit(0);
  146.     /* NOTREACHED */
  147. }
  148.  
  149.  
  150.  
  151. static void
  152. parsenode()
  153. {
  154.     char name[BUFLEN];
  155.     char tag[BUFLEN];
  156.     struct str *sp;
  157.  
  158.     if (curstr && curstr->nfields > 0)
  159.         curstr->done = 1;
  160.     nextfield(name);
  161.     if (! nextfield(tag))
  162.         error("Tag expected");
  163.     if (*linep != '\0')
  164.         error("Garbage at end of line");
  165.     nodename[ntypes] = savestr(name);
  166.     for (sp = str ; sp < str + nstr ; sp++) {
  167.         if (strcmp(sp->tag, tag) == 0)
  168.             break;
  169.     }
  170.     if (sp >= str + nstr) {
  171.         sp->tag = savestr(tag);
  172.         sp->nfields = 0;
  173.         curstr = sp;
  174.         nstr++;
  175.     }
  176.     nodestr[ntypes] = sp;
  177.     ntypes++;
  178. }
  179.  
  180.  
  181. static void
  182. parsefield()
  183. {
  184.     char name[BUFLEN];
  185.     char type[BUFLEN];
  186.     char decl[2 * BUFLEN];
  187.     struct field *fp;
  188.  
  189.     if (curstr == NULL || curstr->done)
  190.         error("No current structure to add field to");
  191.     if (! nextfield(name))
  192.         error("No field name");
  193.     if (! nextfield(type))
  194.         error("No field type");
  195.     fp = &curstr->field[curstr->nfields];
  196.     fp->name = savestr(name);
  197.     if (strcmp(type, "nodeptr") == 0) {
  198.         fp->type = T_NODE;
  199.         sprintf(decl, "union node *%s", name);
  200.     } else if (strcmp(type, "nodelist") == 0) {
  201.         fp->type = T_NODELIST;
  202.         sprintf(decl, "struct nodelist *%s", name);
  203.     } else if (strcmp(type, "string") == 0) {
  204.         fp->type = T_STRING;
  205.         sprintf(decl, "char *%s", name);
  206.     } else if (strcmp(type, "int") == 0) {
  207.         fp->type = T_INT;
  208.         sprintf(decl, "int %s", name);
  209.     } else if (strcmp(type, "other") == 0) {
  210.         fp->type = T_OTHER;
  211.     } else if (strcmp(type, "temp") == 0) {
  212.         fp->type = T_TEMP;
  213.     } else {
  214.         error("Unknown type %s", type);
  215.     }
  216.     if (fp->type == T_OTHER || fp->type == T_TEMP) {
  217.         skipbl();
  218.         fp->decl = savestr(linep);
  219.     } else {
  220.         if (*linep)
  221.             error("Garbage at end of line");
  222.         fp->decl = savestr(decl);
  223.     }
  224.     curstr->nfields++;
  225. }
  226.  
  227.  
  228. char writer[] = "\
  229. /*\n\
  230. * This file was generated by the mknodes program.\n\
  231. */\n\
  232. \n";
  233.  
  234. static void
  235. output(file)
  236.     char *file;
  237. {
  238.     FILE *hfile;
  239.     FILE *cfile;
  240.     FILE *patfile;
  241.     int i;
  242.     struct str *sp;
  243.     struct field *fp;
  244.     char *p;
  245.  
  246.     if ((patfile = fopen(file, "r")) == NULL)
  247.         error("Can't open %s", file);
  248.     if ((hfile = fopen("nodes.h", "w")) == NULL)
  249.         error("Can't create nodes.h");
  250.     if ((cfile = fopen("nodes.c", "w")) == NULL)
  251.         error("Can't create nodes.c");
  252.     fputs(writer, hfile);
  253.     for (i = 0 ; i < ntypes ; i++)
  254.         fprintf(hfile, "#define %s %d\n", nodename[i], i);
  255.     fputs("\n\n\n", hfile);
  256.     for (sp = str ; sp < &str[nstr] ; sp++) {
  257.         fprintf(hfile, "struct %s {\n", sp->tag);
  258.         for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
  259.             fprintf(hfile, "      %s;\n", fp->decl);
  260.         }
  261.         fputs("};\n\n\n", hfile);
  262.     }
  263.     fputs("union node {\n", hfile);
  264.     fprintf(hfile, "      int type;\n");
  265.     for (sp = str ; sp < &str[nstr] ; sp++) {
  266.         fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
  267.     }
  268.     fputs("};\n\n\n", hfile);
  269.     fputs("struct nodelist {\n", hfile);
  270.     fputs("\tstruct nodelist *next;\n", hfile);
  271.     fputs("\tunion node *n;\n", hfile);
  272.     fputs("};\n\n\n", hfile);
  273.     fputs("#ifdef __STDC__\n", hfile);
  274.     fputs("union node *copyfunc(union node *);\n", hfile);
  275.     fputs("void freefunc(union node *);\n", hfile);
  276.     fputs("#else\n", hfile);
  277.     fputs("union node *copyfunc();\n", hfile);
  278.     fputs("void freefunc();\n", hfile);
  279.     fputs("#endif\n", hfile);
  280.  
  281.     fputs(writer, cfile);
  282.     while (fgets(line, sizeof line, patfile) != NULL) {
  283.         for (p = line ; *p == ' ' || *p == '\t' ; p++);
  284.         if (strcmp(p, "%SIZES\n") == 0)
  285.             outsizes(cfile);
  286.         else if (strcmp(p, "%CALCSIZE\n") == 0)
  287.             outfunc(cfile, 1);
  288.         else if (strcmp(p, "%COPY\n") == 0)
  289.             outfunc(cfile, 0);
  290.         else
  291.             fputs(line, cfile);
  292.     }
  293. }
  294.  
  295.  
  296.  
  297. static void
  298. outsizes(cfile)
  299.     FILE *cfile;
  300. {
  301.     int i;
  302.  
  303.     fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
  304.     for (i = 0 ; i < ntypes ; i++) {
  305.         fprintf(cfile, "      ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
  306.     }
  307.     fprintf(cfile, "};\n");
  308. }
  309.  
  310.  
  311. static void
  312. outfunc(cfile, calcsize)
  313.     FILE *cfile;
  314.     int calcsize;
  315. {
  316.     struct str *sp;
  317.     struct field *fp;
  318.     int i;
  319.  
  320.     fputs("      if (n == NULL)\n", cfile);
  321.     if (calcsize)
  322.         fputs("     return;\n", cfile);
  323.     else
  324.         fputs("     return NULL;\n", cfile);
  325.     if (calcsize)
  326.         fputs("      funcblocksize += nodesize[n->type];\n", cfile);
  327.     else {
  328.         fputs("      new = funcblock;\n", cfile);
  329.         fputs("      funcblock = (char *) funcblock + nodesize[n->type];\n", cfile);
  330.     }
  331.     fputs("      switch (n->type) {\n", cfile);
  332.     for (sp = str ; sp < &str[nstr] ; sp++) {
  333.         for (i = 0 ; i < ntypes ; i++) {
  334.             if (nodestr[i] == sp)
  335.                 fprintf(cfile, "      case %s:\n", nodename[i]);
  336.         }
  337.         for (i = sp->nfields ; --i >= 1 ; ) {
  338.             fp = &sp->field[i];
  339.             switch (fp->type) {
  340.             case T_NODE:
  341.                 if (calcsize) {
  342.                     indent(12, cfile);
  343.                     fprintf(cfile, "calcsize(n->%s.%s);\n",
  344.                         sp->tag, fp->name);
  345.                 } else {
  346.                     indent(12, cfile);
  347.                     fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
  348.                         sp->tag, fp->name, sp->tag, fp->name);
  349.                 }
  350.                 break;
  351.             case T_NODELIST:
  352.                 if (calcsize) {
  353.                     indent(12, cfile);
  354.                     fprintf(cfile, "sizenodelist(n->%s.%s);\n",
  355.                         sp->tag, fp->name);
  356.                 } else {
  357.                     indent(12, cfile);
  358.                     fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
  359.                         sp->tag, fp->name, sp->tag, fp->name);
  360.                 }
  361.                 break;
  362.             case T_STRING:
  363.                 if (calcsize) {
  364.                     indent(12, cfile);
  365.                     fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
  366.                         sp->tag, fp->name);
  367.                 } else {
  368.                     indent(12, cfile);
  369.                     fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
  370.                         sp->tag, fp->name, sp->tag, fp->name);
  371.                 }
  372.                 break;
  373.             case T_INT:
  374.             case T_OTHER:
  375.                 if (! calcsize) {
  376.                     indent(12, cfile);
  377.                     fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
  378.                         sp->tag, fp->name, sp->tag, fp->name);
  379.                 }
  380.                 break;
  381.             }
  382.         }
  383.         indent(12, cfile);
  384.         fputs("break;\n", cfile);
  385.     }
  386.     fputs("      };\n", cfile);
  387.     if (! calcsize)
  388.         fputs("      new->type = n->type;\n", cfile);
  389. }
  390.  
  391.  
  392. static void
  393. indent(amount, fp)
  394.     int amount;
  395.     FILE *fp;
  396. {
  397.     while (amount >= 8) {
  398.         putc('\t', fp);
  399.         amount -= 8;
  400.     }
  401.     while (--amount >= 0) {
  402.         putc(' ', fp);
  403.     }
  404. }
  405.  
  406.  
  407. static int
  408. nextfield(buf)
  409.     char *buf;
  410. {
  411.     char *p, *q;
  412.  
  413.     p = linep;
  414.     while (*p == ' ' || *p == '\t')
  415.         p++;
  416.     q = buf;
  417.     while (*p != ' ' && *p != '\t' && *p != '\0')
  418.         *q++ = *p++;
  419.     *q = '\0';
  420.     linep = p;
  421.     return (q > buf);
  422. }
  423.  
  424.  
  425. static void
  426. skipbl()
  427. {
  428.     while (*linep == ' ' || *linep == '\t')
  429.         linep++;
  430. }
  431.  
  432.  
  433. static int
  434. readline()
  435. {
  436.     char *p;
  437.  
  438.     if (fgets(line, 1024, infp) == NULL)
  439.         return 0;
  440.     for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
  441.     while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
  442.         p--;
  443.     *p = '\0';
  444.     linep = line;
  445.     linno++;
  446.     if (p - line > BUFLEN)
  447.         error("Line too long");
  448.     return 1;
  449. }
  450.  
  451.  
  452.  
  453. static void
  454. #ifdef __STDC__
  455. error(const char *msg, ...)
  456. #else
  457. error(va_alist)
  458.     va_dcl
  459. #endif
  460. {
  461.     va_list va;
  462. #ifdef __STDC__
  463.     va_start(va, msg);
  464. #else
  465.     char *msg;
  466.     va_start(va);
  467.     msg = va_arg(va, char *);
  468. #endif
  469.  
  470.     (void) fprintf(stderr, "line %d: ", linno);
  471.     (void) vfprintf(stderr, msg, va);
  472.     (void) fputc('\n', stderr);
  473.  
  474.     va_end(va);
  475.  
  476.     exit(2);
  477.     /* NOTREACHED */
  478. }
  479.  
  480.  
  481.  
  482. static char *
  483. savestr(s)
  484.     const char *s;
  485. {
  486.     char *p;
  487.  
  488.     if ((p = malloc(strlen(s) + 1)) == NULL)
  489.         error("Out of space");
  490.     (void) strcpy(p, s);
  491.     return p;
  492. }
  493.