Subversion Repositories HelenOS

Rev

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

  1. /*  $NetBSD: mkinit.c,v 1.20 2000/07/18 19:13:20 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.  
  40. #ifndef lint
  41. static const char copyright[] =
  42.     "@(#) Copyright (c) 1991, 1993\n\
  43.     The Regents of the University of California.  All rights reserved.\n";
  44. #endif /* not lint */
  45.  
  46. #ifndef lint
  47. #if 0
  48. static char sccsid[] = "@(#)mkinit.c    8.2 (Berkeley) 5/4/95";
  49. #else
  50. static const char rcsid[] =
  51.     "$NetBSD: mkinit.c,v 1.20 2000/07/18 19:13:20 cgd Exp $";
  52. #endif
  53. #endif /* not lint */
  54.  
  55. /*
  56.  * This program scans all the source files for code to handle various
  57.  * special events and combines this code into one file.  This (allegedly)
  58.  * improves the structure of the program since there is no need for
  59.  * anyone outside of a module to know that that module performs special
  60.  * operations on particular events.
  61.  *
  62.  * Usage:  mkinit sourcefile...
  63.  */
  64.  
  65. #include <sys/types.h>
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <fcntl.h>
  70. #include <unistd.h>
  71.  
  72.  
  73. /*
  74.  * OUTFILE is the name of the output file.  Output is initially written
  75.  * to the file OUTTEMP, which is then moved to OUTFILE.
  76.  */
  77.  
  78. #define OUTFILE "init.c"
  79. #define OUTTEMP "init.c.new"
  80.  
  81.  
  82. /*
  83.  * A text structure is basicly just a string that grows as more characters
  84.  * are added onto the end of it.  It is implemented as a linked list of
  85.  * blocks of characters.  The routines addstr and addchar append a string
  86.  * or a single character, respectively, to a text structure.  Writetext
  87.  * writes the contents of a text structure to a file.
  88.  */
  89.  
  90. #define BLOCKSIZE 512
  91.  
  92. struct text {
  93.     char *nextc;
  94.     int nleft;
  95.     struct block *start;
  96.     struct block *last;
  97. };
  98.  
  99. struct block {
  100.     struct block *next;
  101.     char text[BLOCKSIZE];
  102. };
  103.  
  104.  
  105. /*
  106.  * There is one event structure for each event that mkinit handles.
  107.  */
  108.  
  109. struct event {
  110.     char *name;     /* name of event (e.g. INIT) */
  111.     char *routine;      /* name of routine called on event */
  112.     char *comment;      /* comment describing routine */
  113.     struct text code;   /* code for handling event */
  114. };
  115.  
  116.  
  117. char writer[] = "\
  118. /*\n\
  119. * This file was generated by the mkinit program.\n\
  120. */\n\
  121. \n";
  122.  
  123. char init[] = "\
  124. /*\n\
  125. * Initialization code.\n\
  126. */\n";
  127.  
  128. char reset[] = "\
  129. /*\n\
  130. * This routine is called when an error or an interrupt occurs in an\n\
  131. * interactive shell and control is returned to the main command loop.\n\
  132. */\n";
  133.  
  134. char shellproc[] = "\
  135. /*\n\
  136. * This routine is called to initialize the shell to run a shell procedure.\n\
  137. */\n";
  138.  
  139.  
  140. struct event event[] = {
  141.     {"INIT", "init", init},
  142.     {"RESET", "reset", reset},
  143.     {"SHELLPROC", "initshellproc", shellproc},
  144.     {NULL, NULL}
  145. };
  146.  
  147.  
  148. char *curfile;              /* current file */
  149. int linno;              /* current line */
  150. char *header_files[200];        /* list of header files */
  151. struct text defines;            /* #define statements */
  152. struct text decls;          /* declarations */
  153. int amiddecls;              /* for formatting */
  154.  
  155.  
  156. void readfile(char *);
  157. int match(char *, char *);
  158. int gooddefine(char *);
  159. void doevent(struct event *, FILE *, char *);
  160. void doinclude(char *);
  161. void dodecl(char *, FILE *);
  162. void output(void);
  163. void addstr(char *, struct text *);
  164. void addchar(int, struct text *);
  165. void writetext(struct text *, FILE *);
  166. FILE *ckfopen(char *, char *);
  167. void *ckmalloc(int);
  168. char *savestr(char *);
  169. void error(char *);
  170. int main(int, char **);
  171.  
  172. #define equal(s1, s2)   (strcmp(s1, s2) == 0)
  173.  
  174. int
  175. main(argc, argv)
  176.     int argc;
  177.     char **argv;
  178. {
  179.     char **ap;
  180.  
  181.     header_files[0] = "\"shell.h\"";
  182.     header_files[1] = "\"mystring.h\"";
  183.     header_files[2] = "\"init.h\"";
  184.     for (ap = argv + 1 ; *ap ; ap++)
  185.         readfile(*ap);
  186.     output();
  187.     rename(OUTTEMP, OUTFILE);
  188.     exit(0);
  189.     /* NOTREACHED */
  190. }
  191.  
  192.  
  193. /*
  194.  * Parse an input file.
  195.  */
  196.  
  197. void
  198. readfile(fname)
  199.     char *fname;
  200.     {
  201.     FILE *fp;
  202.     char line[1024];
  203.     struct event *ep;
  204.  
  205.     fp = ckfopen(fname, "r");
  206.     curfile = fname;
  207.     linno = 0;
  208.     amiddecls = 0;
  209.     while (fgets(line, sizeof line, fp) != NULL) {
  210.         linno++;
  211.         for (ep = event ; ep->name ; ep++) {
  212.             if (line[0] == ep->name[0] && match(ep->name, line)) {
  213.                 doevent(ep, fp, fname);
  214.                 break;
  215.             }
  216.         }
  217.         if (line[0] == 'I' && match("INCLUDE", line))
  218.             doinclude(line);
  219.         if (line[0] == 'M' && match("MKINIT", line))
  220.             dodecl(line, fp);
  221.         if (line[0] == '#' && gooddefine(line))
  222.             addstr(line, &defines);
  223.         if (line[0] == '#' && gooddefine(line)) {
  224.                 char *cp;
  225.             char line2[1024];
  226.             static const char undef[] = "#undef ";
  227.  
  228.             strcpy(line2, line);
  229.             memcpy(line2, undef, sizeof(undef) - 1);
  230.             cp = line2 + sizeof(undef) - 1;
  231.             while(*cp && (*cp == ' ' || *cp == '\t'))
  232.                     cp++;
  233.             while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
  234.                     cp++;
  235.             *cp++ = '\n'; *cp = '\0';
  236.             addstr(line2, &defines);
  237.             addstr(line, &defines);
  238.         }
  239.     }
  240.     fclose(fp);
  241. }
  242.  
  243.  
  244. int
  245. match(name, line)
  246.     char *name;
  247.     char *line;
  248. {
  249.     char *p, *q;
  250.  
  251.     p = name, q = line;
  252.     while (*p) {
  253.         if (*p++ != *q++)
  254.             return 0;
  255.     }
  256.     if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
  257.         return 0;
  258.     return 1;
  259. }
  260.  
  261.  
  262. int
  263. gooddefine(line)
  264.     char *line;
  265. {
  266.     char *p;
  267.  
  268.     if (! match("#define", line))
  269.         return 0;           /* not a define */
  270.     p = line + 7;
  271.     while (*p == ' ' || *p == '\t')
  272.         p++;
  273.     while (*p != ' ' && *p != '\t') {
  274.         if (*p == '(')
  275.             return 0;       /* macro definition */
  276.         p++;
  277.     }
  278.     while (*p != '\n' && *p != '\0')
  279.         p++;
  280.     if (p[-1] == '\\')
  281.         return 0;           /* multi-line definition */
  282.     return 1;
  283. }
  284.  
  285.  
  286. void
  287. doevent(ep, fp, fname)
  288.     struct event *ep;
  289.     FILE *fp;
  290.     char *fname;
  291.     {
  292.     char line[1024];
  293.     int indent;
  294.     char *p;
  295.  
  296.     sprintf(line, "\n      /* from %s: */\n", fname);
  297.     addstr(line, &ep->code);
  298.     addstr("      {\n", &ep->code);
  299.     for (;;) {
  300.         linno++;
  301.         if (fgets(line, sizeof line, fp) == NULL)
  302.             error("Unexpected EOF");
  303.         if (equal(line, "}\n"))
  304.             break;
  305.         indent = 6;
  306.         for (p = line ; *p == '\t' ; p++)
  307.             indent += 8;
  308.         for ( ; *p == ' ' ; p++)
  309.             indent++;
  310.         if (*p == '\n' || *p == '#')
  311.             indent = 0;
  312.         while (indent >= 8) {
  313.             addchar('\t', &ep->code);
  314.             indent -= 8;
  315.         }
  316.         while (indent > 0) {
  317.             addchar(' ', &ep->code);
  318.             indent--;
  319.         }
  320.         addstr(p, &ep->code);
  321.     }
  322.     addstr("      }\n", &ep->code);
  323. }
  324.  
  325.  
  326. void
  327. doinclude(line)
  328.     char *line;
  329.     {
  330.     char *p;
  331.     char *name;
  332.     char **pp;
  333.  
  334.     for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
  335.     if (*p == '\0')
  336.         error("Expecting '\"' or '<'");
  337.     name = p;
  338.     while (*p != ' ' && *p != '\t' && *p != '\n')
  339.         p++;
  340.     if (p[-1] != '"' && p[-1] != '>')
  341.         error("Missing terminator");
  342.     *p = '\0';
  343.  
  344.     /* name now contains the name of the include file */
  345.     for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
  346.     if (*pp == NULL)
  347.         *pp = savestr(name);
  348. }
  349.  
  350.  
  351. void
  352. dodecl(line1, fp)
  353.     char *line1;
  354.     FILE *fp;
  355.     {
  356.     char line[1024];
  357.     char *p, *q;
  358.  
  359.     if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
  360.         addchar('\n', &decls);
  361.         do {
  362.             linno++;
  363.             if (fgets(line, sizeof line, fp) == NULL)
  364.                 error("Unterminated structure declaration");
  365.             addstr(line, &decls);
  366.         } while (line[0] != '}');
  367.         amiddecls = 0;
  368.     } else {
  369.         if (! amiddecls)
  370.             addchar('\n', &decls);
  371.         q = NULL;
  372.         for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
  373.             continue;
  374.         if (*p == '=') {        /* eliminate initialization */
  375.             for (q = p ; *q && *q != ';' ; q++);
  376.             if (*q == '\0')
  377.                 q = NULL;
  378.             else {
  379.                 while (p[-1] == ' ')
  380.                     p--;
  381.                 *p = '\0';
  382.             }
  383.         }
  384.         addstr("extern", &decls);
  385.         addstr(line1 + 6, &decls);
  386.         if (q != NULL)
  387.             addstr(q, &decls);
  388.         amiddecls = 1;
  389.     }
  390. }
  391.  
  392.  
  393.  
  394. /*
  395.  * Write the output to the file OUTTEMP.
  396.  */
  397.  
  398. void
  399. output() {
  400.     FILE *fp;
  401.     char **pp;
  402.     struct event *ep;
  403.  
  404.     fp = ckfopen(OUTTEMP, "w");
  405.     fputs(writer, fp);
  406.     for (pp = header_files ; *pp ; pp++)
  407.         fprintf(fp, "#include %s\n", *pp);
  408.     fputs("\n\n\n", fp);
  409.     writetext(&defines, fp);
  410.     fputs("\n\n", fp);
  411.     writetext(&decls, fp);
  412.     for (ep = event ; ep->name ; ep++) {
  413.         fputs("\n\n\n", fp);
  414.         fputs(ep->comment, fp);
  415.         fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
  416.         writetext(&ep->code, fp);
  417.         fprintf(fp, "}\n");
  418.     }
  419.     fclose(fp);
  420. }
  421.  
  422.  
  423. /*
  424.  * A text structure is simply a block of text that is kept in memory.
  425.  * Addstr appends a string to the text struct, and addchar appends a single
  426.  * character.
  427.  */
  428.  
  429. void
  430. addstr(s, text)
  431.     char *s;
  432.     struct text *text;
  433.     {
  434.     while (*s) {
  435.         if (--text->nleft < 0)
  436.             addchar(*s++, text);
  437.         else
  438.             *text->nextc++ = *s++;
  439.     }
  440. }
  441.  
  442.  
  443. void
  444. addchar(c, text)
  445.     int c;
  446.     struct text *text;
  447. {
  448.     struct block *bp;
  449.  
  450.     if (--text->nleft < 0) {
  451.         bp = ckmalloc(sizeof *bp);
  452.         if (text->start == NULL)
  453.             text->start = bp;
  454.         else
  455.             text->last->next = bp;
  456.         text->last = bp;
  457.         text->nextc = bp->text;
  458.         text->nleft = BLOCKSIZE - 1;
  459.     }
  460.     *text->nextc++ = c;
  461. }
  462.  
  463. /*
  464.  * Write the contents of a text structure to a file.
  465.  */
  466. void
  467. writetext(text, fp)
  468.     struct text *text;
  469.     FILE *fp;
  470.     {
  471.     struct block *bp;
  472.  
  473.     if (text->start != NULL) {
  474.         for (bp = text->start ; bp != text->last ; bp = bp->next)
  475.             fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
  476.         fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
  477.     }
  478. }
  479.  
  480. FILE *
  481. ckfopen(file, mode)
  482.     char *file;
  483.     char *mode;
  484.     {
  485.     FILE *fp;
  486.  
  487.     if ((fp = fopen(file, mode)) == NULL) {
  488.         fprintf(stderr, "Can't open %s\n", file);
  489.         exit(2);
  490.     }
  491.     return fp;
  492. }
  493.  
  494. void *
  495. ckmalloc(nbytes)
  496.     int nbytes;
  497. {
  498.     char *p;
  499.  
  500.     if ((p = malloc(nbytes)) == NULL)
  501.         error("Out of space");
  502.     return p;
  503. }
  504.  
  505. char *
  506. savestr(s)
  507.     char *s;
  508.     {
  509.     char *p;
  510.  
  511.     p = ckmalloc(strlen(s) + 1);
  512.     strcpy(p, s);
  513.     return p;
  514. }
  515.  
  516. void
  517. error(msg)
  518.     char *msg;
  519.     {
  520.     if (curfile != NULL)
  521.         fprintf(stderr, "%s:%d: ", curfile, linno);
  522.     fprintf(stderr, "%s\n", msg);
  523.     exit(2);
  524.     /* NOTREACHED */
  525. }
  526.