home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / a / bin / modules-.2 / modules- / modules-1.2.8 / genksyms / parsesym.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-22  |  28.2 KB  |  1,330 lines

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <limits.h>
  6. #include <ctype.h>
  7. #include "lexsyms.h"
  8.  
  9. /*
  10.  * This is version 0.43 of genksyms.c (BETA)
  11.  *
  12.  * In this source, the crc and findsym functions are:
  13.  *
  14.  * updcrc32 function    from gzip (see also the source: makecrc32.c)
  15.  * findsym function    from insmod
  16.  *            (function written by Jon Tombs and/or Bas Laarhoven)
  17.  * 
  18.  * The rest of this source is copyright (C) 1994, Bjorn Ekwall <bj0rn@blox.se>
  19.  *
  20.  *    This program is free software; you can redistribute it and/or modify
  21.  *    it under the terms of the GNU General Public License as published by
  22.  *    the Free Software Foundation; either version 2, or (at your option)
  23.  *    any later version.
  24.  *
  25.  *    This program is distributed in the hope that it will be useful,
  26.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28.  *    GNU General Public License for more details.
  29.  *
  30.  *    You should have received a copy of the GNU General Public License
  31.  *    along with this program; if not, write to the Free Software
  32.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  33.  *
  34.  *
  35.  */
  36.  
  37. char *copyright = "(C) 1994, 1995 Bjorn Ekwall <bj0rn@blox.se>, version 0.43(BETA)";
  38.  
  39. /*
  40.  * If your flex generates a scanner where yytext is
  41.  *    "char *yytext"
  42.  * instead of
  43.  *    "char yytext[YYLMAX]"
  44.  * then change the "#if 0" below to "#if 1"
  45.  */
  46.  
  47. #if 0
  48. extern char *yytext;
  49. #else
  50. extern char yytext[];
  51. #endif
  52. extern int yylex(void);
  53.  
  54. FILE *logfile;
  55. int line_no;
  56. int debug;
  57. int dump_defs;
  58. int warnings = 0; /* at least for ALPHA versions, use '-q' at your own risk */
  59. char *progname;
  60. char *expand_key;
  61. char *outfile_dir = ".";
  62. int outfile_flag = 0;
  63. FILE *outfile = (FILE *)0;
  64. char outfilename[PATH_MAX];
  65. char infile[PATH_MAX];
  66. char macroname[PATH_MAX];
  67. int use_globals = 0;
  68.  
  69. #define MAXTMP 10000
  70. static char tmpbuffer[MAXTMP];
  71. static char *pbuffer = tmpbuffer;
  72.  
  73. char *header[] = {
  74. "/**** This file is generated by genksyms  DO NOT EDIT! ****/",
  75. "#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__)",
  76. 0
  77. };
  78.  
  79. #define MARK '#' /* kludge to mark unresolved references while parsing */
  80.  
  81. struct symbol {
  82.     char *key;
  83.     char *value;
  84.     struct symbol *child[2];
  85.     struct symbol *trail;
  86. };
  87.  
  88. void show_globals(struct symbol *);
  89.  
  90. struct symbol *trail;
  91. struct symbol *type_root;    /* for typdef */
  92. struct symbol *enum_root;    /* for enum */
  93. struct symbol *s_u_root;    /* for for struct or union */
  94. struct symbol *symbol_root;    /* for symbols */
  95.  
  96. /*
  97.  * Look up an name in the symbol table.  If "add" is not null, add a
  98.  * the entry to the table.  The table is stored as a splay tree.
  99.  * (Bjorn: This is one of my favourites!)
  100.  */
  101. struct symbol *
  102. findsym(struct symbol **root, char *key, struct symbol *add)
  103. {
  104.     struct symbol *left, *right;
  105.     struct symbol **leftp, **rightp;
  106.     struct symbol *sp1, *sp2, *sp3;
  107.     int cmp;
  108.     int path1, path2;
  109.  
  110.     if (add) {
  111.         add->key = key;
  112.     }
  113.     sp1 = *root;
  114.     if (sp1 == NULL)
  115.         return add? *root = add : NULL;
  116.     leftp = &left, rightp = &right;
  117.     for (;;) {
  118.         cmp = strcmp( sp1->key, key);
  119.         if (cmp == 0)
  120.             break;
  121.         if (cmp > 0) {
  122.             sp2 = sp1->child[0];
  123.             path1 = 0;
  124.         } else {
  125.             sp2 = sp1->child[1];
  126.             path1 = 1;
  127.         }
  128.         if (sp2 == NULL) {
  129.             if (! add)
  130.                 break;
  131.             sp2 = add;
  132.         }
  133.         cmp = strcmp(sp2->key, key);
  134.         if (cmp == 0) {
  135. one_level_only:
  136.             if (path1 == 0) {    /* sp2 is left child of sp1 */
  137.                 *rightp = sp1;
  138.                 rightp = &sp1->child[0];
  139.             } else {
  140.                 *leftp = sp1;
  141.                 leftp = &sp1->child[1];
  142.             }
  143.             sp1 = sp2;
  144.             break;
  145.         }
  146.         if (cmp > 0) {
  147.             sp3 = sp2->child[0];
  148.             path2 = 0;
  149.         } else {
  150.             sp3 = sp2->child[1];
  151.             path2 = 1;
  152.         }
  153.         if (sp3 == NULL) {
  154.             if (! add)
  155.                 goto one_level_only;
  156.             sp3 = add;
  157.         }
  158.         if (path1 == 0) {
  159.             if (path2 == 0) {
  160.                 sp1->child[0] = sp2->child[1];
  161.                 sp2->child[1] = sp1;
  162.                 *rightp = sp2;
  163.                 rightp = &sp2->child[0];
  164.             } else {
  165.                 *rightp = sp1;
  166.                 rightp = &sp1->child[0];
  167.                 *leftp = sp2;
  168.                 leftp = &sp2->child[1];
  169.             }
  170.         } else {
  171.             if (path2 == 0) {
  172.                 *leftp = sp1;
  173.                 leftp = &sp1->child[1];
  174.                 *rightp = sp2;
  175.                 rightp = &sp2->child[0];
  176.             } else {
  177.                 sp1->child[1] = sp2->child[0];
  178.                 sp2->child[0] = sp1;
  179.                 *leftp = sp2;
  180.                 leftp = &sp2->child[1];
  181.             }
  182.         }
  183.         sp1 = sp3;
  184.     }
  185.     /*
  186.      * Now sp1 points to the result of the search.  If cmp is zero,
  187.      * we had a match; otherwise not.
  188.      */
  189.     *leftp = sp1->child[0];
  190.     *rightp = sp1->child[1];
  191.     sp1->child[0] = left;
  192.     sp1->child[1] = right;
  193.     *root = sp1;
  194.     return cmp == 0? sp1 : NULL;
  195. }
  196.  
  197. /* crc function  slightly modified from gzip */
  198. /*
  199.  * Run a null-terminated string through the crc shift register.
  200.  * If s is a NULL pointer, then initialize the crc shift register
  201.  * contents instead.
  202.  * Return the current crc in either case.
  203.  */
  204.  
  205. static unsigned long crctab32[] = {
  206. #include "crc32.tab"
  207. };
  208.  
  209. unsigned long
  210. updcrc32(register unsigned char *s)
  211. {
  212.     static unsigned long crcreg;
  213.     register unsigned long c, *t;
  214.  
  215.     if (s == 0)
  216.         c = 0xffffffffU;
  217.     else {
  218.         c = crcreg;
  219.         t = crctab32;
  220.         while (*s)
  221.             c = t[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
  222.     }
  223.     crcreg = c;
  224.     return c ^ 0xffffffffU;
  225. }
  226.  
  227. void
  228. drop_table(struct symbol *symtab)
  229. {
  230.     if (symtab) {
  231.         if (symtab->child[0])
  232.             drop_table(symtab->child[0]);
  233.  
  234.         if (symtab->child[1])
  235.             drop_table(symtab->child[1]);
  236.  
  237.         if (symtab->key)
  238.             free(symtab->key);
  239.  
  240.         if (symtab->value)
  241.             free(symtab->value);
  242.  
  243.         free(symtab);
  244.     }
  245. }
  246.  
  247. void
  248. restart_file(char *id)
  249. {
  250.     char *p;
  251.     char *s;
  252.  
  253.     if (debug) fprintf(logfile, "RESTART %s\n", id);
  254.  
  255.     if ((use_globals > 0) && symbol_root)
  256.         show_globals(symbol_root);
  257.  
  258.     if (use_globals < 0)
  259.         use_globals = 1;
  260.  
  261.     line_no = 0;
  262.  
  263.     if (outfile && (outfile != stdout)) {
  264.         if (!dump_defs) {
  265.             fprintf(outfile, "#endif /* %s */\n", macroname);
  266.             fprintf(outfile, "#endif /* CONFIG_MODVERSIONS !__GENKSYMS__ */\n");
  267.         }
  268.  
  269.         fclose(outfile);
  270.         outfile = (FILE *)0;
  271.     }
  272.  
  273.     strcpy(infile, strchr(id, '\"'));
  274.  
  275.     if ((p = strrchr(id, '.')))
  276.         *p = '\0';
  277.     if ((p = strrchr(id, '/')))
  278.         ++p;
  279.     else if ((p = strchr(id, '\"')))
  280.         ++p;
  281.     else {
  282.         fprintf(stderr, "Illegal filename: %s\n", id);
  283.         p = "_unknown";
  284.     }
  285.  
  286.     sprintf(outfilename, "%s/%s.ver", outfile_dir, p);
  287.  
  288.     s = macroname;
  289.     *s++ = '_';
  290.     while (*p) {
  291.         if (*p == '.')
  292.             *s = '_';
  293.         else
  294.             *s = toupper(*p);
  295.         ++s; ++p;
  296.     }
  297.     strcpy(s, "_VER_");
  298.  
  299.     if (outfile == stdout) {
  300.         char **txt = header;
  301.  
  302.         /* Print the header */
  303.         while (!dump_defs && *txt)
  304.             fprintf(outfile, "%s\n", *txt++);
  305.         fprintf(outfile, "#ifndef %s\n", macroname);
  306.         fprintf(outfile, "#define %s\n", macroname);
  307.     }
  308.  
  309.     /* Clean the old tables */
  310.  
  311.     if (type_root) {
  312.         drop_table(type_root);
  313.         type_root = (struct symbol *)0;
  314.     }
  315.  
  316.     if (enum_root) {
  317.         drop_table(enum_root);
  318.         enum_root = (struct symbol *)0;
  319.     }
  320.  
  321.     if (s_u_root) {
  322.         drop_table(s_u_root);
  323.         s_u_root = (struct symbol *)0;
  324.     }
  325.  
  326.     if (symbol_root) {
  327.         drop_table(symbol_root);
  328.         symbol_root = (struct symbol *)0;
  329.     }
  330. }
  331.  
  332. /*
  333.  * Save string in a safe place for later reference
  334.  */
  335. char *
  336. savestr(char *str, int len)
  337. {
  338.     char *p;
  339.  
  340.     p = (char *)malloc(len + 1);
  341.     strcpy(p, str);
  342.  
  343.     return p;
  344. }
  345.  
  346. /*
  347.  * Centralized error reporting
  348.  */
  349. void
  350. put_err(char *s)
  351. {
  352.     if (warnings)
  353.         fprintf(logfile, "%s %s: input line %d: Note: %s\n",
  354.             progname, infile, line_no, s);
  355. }
  356.  
  357. /*
  358.  * Centralized error reporting with an extra parameter
  359.  */
  360. void
  361. put_err2(char *s1, char *s2)
  362. {
  363.     if (warnings) {
  364.         fprintf(logfile, "%s %s: input line %d: Note: ",
  365.             progname, infile, line_no);
  366.         fprintf(logfile, s1, s2);
  367.         fprintf(logfile, "\n");
  368.     }
  369. }
  370.  
  371. /*
  372.  * stuff a string to the end of the work buffer while parsing
  373.  */
  374. void
  375. put(char *s)
  376. {
  377.     strcat(pbuffer, s);
  378.     pbuffer += strlen(s);
  379.  
  380.     strcat(pbuffer, " ");
  381.     ++pbuffer;
  382.     if ((pbuffer - tmpbuffer) >= MAXTMP) {
  383.         fprintf(stderr, "PANIC: buffer overflow! Quitting!\n");
  384.         exit(1);
  385.     }
  386. }
  387.  
  388. /*
  389.  * Save all symbols (identifiers) found while parsing,
  390.  * so that the symbol table later can be updated with the full definition.
  391.  * We don't know the full definition when we find the symbol while scanning!
  392.  */
  393. char **id_stack;
  394. int id_stack_size;
  395. int id_next;
  396.  
  397. void
  398. push_id(char *s) /* yytext */
  399. {
  400.     char *key;
  401.  
  402.     if (debug) fprintf(logfile, "found def <%s>\n", s);
  403.     key = savestr(s, strlen(s));
  404.  
  405.     if (id_stack) {
  406.         if (id_next >= id_stack_size) {
  407.             id_stack = (char **)realloc(id_stack,
  408.                 (id_stack_size + 1) * sizeof(char *));
  409.             id_stack_size += 1;
  410.         }
  411.     }
  412.     else {
  413.         id_stack = (char **)malloc(sizeof(char *));
  414.         id_stack_size = 1;
  415.     }
  416.  
  417.     id_stack[id_next++] = key;
  418. }
  419.  
  420. /*
  421.  * Flush the work buffer since we have completed the scan of this
  422.  * definition/declaration.
  423.  * If we have found any identifiers (i.e. this was not just a type declaration)
  424.  * we create entries in the symbol table for these identifiers,
  425.  * with references to this definition.
  426.  */
  427. void
  428. reset_buf(int saveit)
  429. {
  430.     struct symbol *p;
  431.     int i;
  432.     char *value;
  433.  
  434.     if (debug) fprintf(logfile, "BUFFER: <%s>\n", tmpbuffer);
  435.  
  436.     if (saveit && id_next) {
  437.  
  438.         for (i = 0; i < id_next; ++i) {
  439.             if (debug) fprintf(logfile, "DEF <%s>\n", id_stack[i]);
  440.             value = savestr(tmpbuffer, pbuffer - tmpbuffer);
  441.             p = (struct symbol *)calloc(1, sizeof(struct symbol));
  442.             p->value = value;
  443.             findsym(&symbol_root, id_stack[i], p);
  444.         }
  445.     }
  446.     else {
  447.         while (id_next > 0)
  448.             free(id_stack[--id_next]);
  449.     }
  450.  
  451.     id_next = 0; /* empty stack */
  452.     pbuffer = tmpbuffer;
  453.     *pbuffer = '\0';
  454. }
  455.  
  456. /*
  457.  * Save a struct/union/enum declaration to its respective symbol table.
  458.  * (Different namespaces for enum vs struct/union)
  459.  * This entry will be used later when expanding a declaration/definition
  460.  * for a "X(symbol)" in the input stream.
  461.  */
  462. struct symbol *
  463. save_tag(int sym, char *tag, char *defstart)
  464. {
  465.     struct symbol *p;
  466.     struct symbol **root;
  467.  
  468.     if (sym == ENUM)
  469.         root = &enum_root;
  470.     else
  471.         root = &s_u_root;
  472.  
  473.     p = (struct symbol *)calloc(1, sizeof(struct symbol));
  474.     p->value = savestr(defstart, pbuffer - defstart);
  475.     findsym(root, tag, p);
  476.  
  477.     if (debug) fprintf(logfile, "S/U/E def <%s> <%s>\n", tag, defstart);
  478.  
  479.     return p;
  480. }
  481.  
  482. /*
  483.  * Check the relevant symbol tables for any previous declaration of a
  484.  * struct/union or enum.
  485.  * If we find it, we return 1 else 0.
  486.  * If found: add the definition to the current workbuffer,
  487.  * so that the fully expanded definition of the current symbol will
  488.  * be available when we finally are going looking for it (for the crc)
  489.  *
  490.  * (NOT USED. I left it here for debugging purposes...)
  491.  */
  492. int
  493. expand_tag(int sym, char *tag)
  494. {
  495.     struct symbol *p;
  496.     struct symbol **root;
  497.  
  498.     if (sym == ENUM)
  499.         root = &enum_root;
  500.     else
  501.         root = &s_u_root;
  502.  
  503.  
  504.     if ((p = findsym(root, tag, 0))) {
  505.         put(p->value);
  506.         if (debug) fprintf(logfile, "S/U/E expand <%s>\n", tag);
  507.         return 1;
  508.     }
  509.     else
  510.         return 0;
  511. }
  512.  
  513. /*
  514.  * Save a typedef definition to its own symbol table.
  515.  * (Different namespaces for typedefs vs enum or struct/union)
  516.  * This entry will be used later when expanding a declaration/definition
  517.  * during the parsing of the input stream.
  518.  */
  519. void
  520. save_type(char *type_tag)
  521. {
  522.     struct symbol *p;
  523.     struct symbol **root = &type_root;
  524.  
  525.     p = (struct symbol *)calloc(1, sizeof(struct symbol));
  526.     /* subtract 1 to remove trailing space */
  527.     /* it will be added back when expanding */
  528.     --pbuffer;
  529.     *pbuffer = '\0';
  530.     p->value = savestr(tmpbuffer, strlen(tmpbuffer));
  531.     findsym(root, type_tag, p);
  532.  
  533.     if (debug) fprintf(logfile, "TYPEDEF def <%s> <%s>\n", type_tag, p->value);
  534. }
  535.  
  536. /*
  537.  * Check the relevant symbol tables for any previous declaration of a
  538.  * typedef with this tag.
  539.  * IF we find it, we immediately add the full definition ('typedef' and all)
  540.  * to the current workbuffer, so that the fully expanded definition of the
  541.  * current symbol will be easily available when we later are going looking
  542.  * for it (for the crc).
  543.  */
  544. int
  545. expand_type(char *type_tag)
  546. {
  547.     struct symbol *p;
  548.     struct symbol **root = &type_root;
  549.  
  550.     if ((p = findsym(root, type_tag, 0))) {
  551.         put(p->value);
  552.         if (debug) fprintf(logfile, "TYPEDEF expand <%s>\n", type_tag);
  553.         return 1;
  554.     }
  555.     else
  556.         return 0;
  557. }
  558.  
  559. /*
  560.  * Silly little wrapper for the crc computation.
  561.  * This also prints the (partial) definition if the '-D' option was used
  562.  */
  563. unsigned long
  564. dump_str(char *s)
  565. {
  566.     if (dump_defs)
  567.         printf("%s", s);
  568.  
  569.     return updcrc32((unsigned char *)s);
  570. }
  571.  
  572. /*
  573.  * Potentially recursive fucntion for expanding the text of a definition.
  574.  * IF there is a MARK in the string, it signifies that a reference to
  575.  * a struct/union/enum is going on.
  576.  * The tag (and type) of the reference will be grep-ed for and looked
  577.  * up in the relevant symbol table.
  578.  *
  579.  * This will find all the basic types for every declaration/definition
  580.  * in the input stream (you can see the expansion with the '-D' option)...
  581.  *
  582.  * The fully expanded string is put through a 32bit crc computation,
  583.  * so that any changes in any part of the kernel that might "interfere"
  584.  * with the compatibility of the current symbol, will give a different crc!
  585.  */
  586. unsigned long
  587. expand_def(char *value)
  588. {
  589.     struct symbol **root;
  590.     struct symbol *p;
  591.     unsigned long crc = 0;
  592.     char *start = value;
  593.     char *stop;
  594.     char *marked;
  595.     char saved = '\0';
  596.  
  597.     while ((stop = strchr(start, MARK))) {
  598.         *stop = '\0'; /* null-terminate the partial string */
  599.         crc = dump_str(start); /* the string up to the mark */
  600.         *stop = MARK; /* restore the string */
  601.         start = ++stop;
  602.         /* find type and tag, differ between struct/union vs enum */
  603.         if (strncmp(start, "num", 3) == 0) { /* Yikes, an enum! */
  604.             root = &enum_root;
  605.             marked = "enum";
  606.         }
  607.         else {
  608.             root = &s_u_root;
  609.             if (*start == 't') /* struct */
  610.                 marked = "struct";
  611.             else
  612.                 marked = "union";
  613.         }
  614.  
  615.         /* skip over tag after we have gotten hold of it */
  616.         /* skip #truct #nion #num */
  617.         if ((start = strchr(start, ' ')) == (char *)0) {
  618.             put_err("Ouch, lost sync in symbol expansion (1)");
  619.             break;
  620.         }
  621.         /* find start of tag string */
  622.         if (*++start <= ' ') { /* safe guy.. */
  623.             put_err("Ouch, lost sync in symbol expansion (2)");
  624.             break;
  625.         }
  626.         /* find end of tag string */
  627.         if ((stop = strchr(start, ' ')) != (char *)0) {
  628.             saved = *stop;
  629.             *stop = '\0';
  630.         }
  631.  
  632.         /* start _should_ point to the null-terminated tag */
  633.         /* stop points to the end of the null-terminated tag */
  634.         /* OR stop is NULL for "pre-nulled" string */
  635.  
  636.         if ((p = findsym(root, start, 0)) == (struct symbol *)0) {
  637.             struct symbol *nodup;
  638.             char *here = pbuffer;
  639.             char *savstart = savestr(start, strlen(start));
  640.  
  641.             if (warnings)
  642.                 fprintf(logfile, "%s %s: warning: symbol [%s]: "
  643.                     "unknown '%s %s'\n",
  644.                     progname, infile, expand_key, marked, start);
  645.             /* sound action: */
  646.             /* save the offender: no duplicate warnings */
  647.             put(marked);
  648.             put(start);
  649.             put("{ UNKNOWN }");
  650.             if (strcmp(start, "enum") == 0)
  651.                 nodup = save_tag(ENUM, savstart, here);
  652.             else
  653.                 nodup = save_tag(STRUCT, savstart, here);
  654.             nodup->trail = trail; /* mark it, no loops! */
  655.             trail = nodup;
  656.             crc = dump_str(here); /* the new definition */
  657.             pbuffer = here;
  658.             *pbuffer = '\0';
  659.         }
  660.         else { /* found it */
  661.             if (p->trail) { /* been here before in this expansion */
  662.                 dump_str(marked); /* the type */
  663.                 dump_str(" ");
  664.                 dump_str(start); /* the tag */
  665.                 crc = dump_str(" ");
  666.             }
  667.             else { /* Not here before, expand it */
  668.                 /* The value contains the type and tag */
  669.                 p->trail = trail; /* mark it, no loops! */
  670.                 trail = p;
  671.                 if (stop)
  672.                     *stop = saved; /* restore the string */
  673.                 crc = expand_def(p->value);
  674.             }
  675.         }
  676.  
  677.         /* let us continue with the rest of the string */
  678.         if (stop) {
  679.             *stop = saved; /* restore the string */
  680.             start = ++stop;
  681.         }
  682.         else {
  683.             start = (char *)0; /* flag end of input, for below */
  684.             break;
  685.         }
  686.     }
  687.     /* no more marks have been found (if any!) */
  688.  
  689.     /*
  690.      * take care of the proper tail of the input string
  691.      * (might be the whole string...)
  692.      */
  693.     if (start && *start)
  694.         crc = dump_str(start);
  695.  
  696.     return crc;
  697. }
  698.  
  699. /*
  700.  * Basic main loop for expanding the name of a symbol to its FULL
  701.  * declaration, down to the basic level (like char, int and stuff)...
  702.  */
  703. void
  704. show_def(char *key, char *value)
  705. {
  706.     unsigned long last_crc;
  707.     struct symbol *p;
  708.     struct symbol tail;
  709.  
  710.     if (debug) fprintf(logfile, "FOUND <%s> = ", key);
  711.  
  712.     /* reset CRC */
  713.     updcrc32(0);
  714.  
  715.     if (dump_defs)
  716.         printf("FOUND <%s> = <", key);
  717.  
  718.     expand_key = key;
  719.     trail = &tail; /* just a marker */
  720.     last_crc = expand_def(value);
  721.     while (trail != &tail) { /* clean up */
  722.         p = trail;
  723.         trail = p->trail;
  724.         p->trail = (struct symbol *)0;
  725.     }
  726.  
  727.     if (outfile_flag && !outfile) {
  728.         char **txt = header;
  729.  
  730.         if ((outfile = fopen(outfilename, "w")) == (FILE *)0) {
  731.             perror(outfilename);
  732.             exit(1);
  733.         }
  734.  
  735.         while (!dump_defs && *txt)
  736.             fprintf(outfile, "%s\n", *txt++);
  737.         fprintf(outfile, "#ifndef %s\n", macroname);
  738.         fprintf(outfile, "#define %s\n", macroname);
  739.     }
  740.  
  741.     if (!dump_defs)
  742.         fprintf(outfile, "#define %s\t_set_ver(%s, %08lx)\n",
  743.             key, key, last_crc);
  744.  
  745.     if (dump_defs)
  746.         printf(">\n");
  747. }
  748.  
  749. /*
  750.  * This function will create a version header based on globals
  751.  * instead of symbols mentioned in an explicit symbol table: X(symbol)
  752.  * It is called at end-of-file IF no symbol table has been found,
  753.  * i.e. from restart_file() or from main() after a finished run.
  754.  */
  755. void
  756. show_globals(struct symbol *symtab)
  757. {
  758.     if (symtab) {
  759.         if (symtab->child[0])
  760.             show_globals(symtab->child[0]);
  761.  
  762.         if (symtab->child[1])
  763.             show_globals(symtab->child[1]);
  764.  
  765.         if (symtab->value) {
  766.             if (strncmp(symtab->value, "static ", 7) != 0)
  767.                 /* found one! */
  768.                 show_def(symtab->key, symtab->value);
  769.         }
  770.     }
  771. }
  772.  
  773. /*
  774.  * This is the "black hole" for strings and character constants
  775.  */
  776. void
  777. skip_string()
  778. {
  779.     int sym;
  780.     char match;
  781.  
  782.     match = yytext[0];
  783.  
  784.     if (debug) fprintf(logfile, "skipping %c string at line %d\n", match, line_no);
  785.  
  786.     while ((sym = yylex())) {
  787.         switch (sym) {
  788.         case STRING:
  789.             if (yytext[0] == match) {
  790.                 if (debug) fprintf(logfile, "done skipping string\n");
  791.                 return;
  792.             }
  793.  
  794.         default:
  795.             if (yytext[0] == '\\')
  796.                 yylex(); /* skip escaped */
  797.             if (debug) fprintf(logfile, "line %d: skip sym %d = <%s>\n", line_no, sym, yytext);
  798.             break;
  799.         }
  800.     }
  801.  
  802.     if (debug) fprintf(logfile, "done skipping string\n");
  803.     return;
  804. }
  805.  
  806. /*
  807.  * This (recursive) loop will take care of all '{' '}' nested blocks
  808.  * in the input stream that are _not_ enum/struct/union declarations.
  809.  * So, initializers (e.g. for arrays and structs) and function bodies
  810.  * will disappear down into this black hole...
  811.  *
  812.  * Only _special_ identifiers that conform to:  "X(identifier)"
  813.  * will result in any output.
  814.  *
  815.  * This type of strings should only found in sources using them to
  816.  * denote the kernel symbols in a symbol table that is going to be exported.
  817.  *
  818.  * The action will be to generate the "magic" definitions in module
  819.  * include files, e.g.  <linux/module_version.h>
  820.  */
  821. int
  822. skip_block()
  823. {
  824.     struct symbol *p;
  825.     int sym;
  826.     int maybe = 0;
  827.  
  828.     if (debug) fprintf(logfile, "ENTER SKIP BLOCK\n");
  829.  
  830.     while ((sym = yylex())) {
  831.         switch (sym) {
  832.         case FILENAME: /* This is an error! */
  833.             put_err("Illegal file start block");
  834.             return 0;
  835.  
  836.         case RBRACE:
  837.             if (debug) fprintf(logfile, "LEAVE SKIP BLOCK\n");
  838.             return 1;
  839.  
  840.         case LBRACE:
  841.             maybe = 0;
  842.             if (skip_block() == 0) {
  843.                 if (debug) fprintf(logfile, "LEAVE SKIP BLOCK\n");
  844.                 return 0;
  845.             }
  846.             break;
  847.  
  848.         case STRING:
  849.             skip_string();
  850.             break;
  851.  
  852.         case IDENT:
  853.             if (maybe == 2) {
  854.                 /* might be defined even... */
  855.                 if ((p = findsym(&symbol_root, yytext, 0))) {
  856.                     /* found one! */
  857.                     show_def(yytext, p->value);
  858.                     /*
  859.                      * If there is a symbol table, we
  860.                      * shouldn't create a header based
  861.                      * on any globals in the source...
  862.                      */
  863.                     if (use_globals > 0)
  864.                         use_globals = -1;
  865.                 }
  866.                 else {
  867.                     put_err2("Unkown symbol '%s'", yytext);
  868.                 }
  869.                 maybe = 0;
  870.             }
  871.             else if ((maybe == 0) && (strcmp(yytext, "X") == 0))
  872.                 maybe = 1; /* MAYBE an exported symbol... */
  873.             else
  874.                 maybe = 0;
  875.             break;
  876.  
  877.         case LPAREN:
  878.             if (maybe == 1)
  879.                 maybe = 2;
  880.             else
  881.                 maybe = 0;
  882.             break;
  883.  
  884.         default:
  885.             maybe = 0;
  886.             break;
  887.         }
  888.     }
  889.  
  890.     if (debug) fprintf(logfile, "LEAVE SKIP BLOCK\n");
  891.     return 0;
  892. }
  893.  
  894. /*
  895.  * Parse (maybe recursively) a struct/union/enum definition block.
  896.  * Append it to the work buffer.
  897.  *
  898.  *    This code is in many respects similar to the code in parse(),
  899.  *    but I felt it was easier to maintain one function for the top
  900.  *    level, where all the global definitions are, and another
  901.  *    function that just had to decode a struct/union/enum definition...
  902.  */
  903. void
  904. build_block(void)
  905. {
  906.     int sym;
  907.     int sym1;
  908.     char *tag = (char *)0;
  909.     char *marker;
  910.     char *here;
  911.  
  912.  
  913.     while ((sym = yylex())) {
  914.     again:
  915.         switch (sym) {
  916.         case FILENAME: /* This is an error! */
  917.             put_err("Illegal file start build");
  918.             return;
  919.  
  920.         case TYPEDEF:
  921.             put_err("No typedef allowed here");
  922.             break;
  923.  
  924.         case STRING:
  925.             skip_string();
  926.             break;
  927.  
  928.         case RBRACE:
  929.             put("}");
  930.             return;
  931.  
  932.         case LBRACE:
  933.             put("{");
  934.             build_block();
  935.             break;
  936.  
  937.         case ENUM:
  938.         case UNION:
  939.         case STRUCT:
  940.             marker = pbuffer; /* current "put" pointer */
  941.             put(yytext);
  942.  
  943.             if ((sym1 = yylex()) == IDENT) { /* need a tag */
  944.                 tag = savestr(yytext, strlen(yytext));
  945.                 put(yytext);
  946.                 sym1 = yylex();
  947.             }
  948.             else
  949.                 tag = (char *)0;
  950.  
  951.             if (sym1 != LBRACE) { /* then it is a reference */
  952.                 if (tag) { /* refer */
  953.                     /*
  954.                      * mark for easy retrieval later
  955.                      *
  956.                      * struct -> #truct
  957.                      * union  -> #nion
  958.                      * enum   -> #num
  959.                      */
  960.                     *marker = MARK; /* kludge! */
  961.                 }
  962.                 else
  963.                     put_err("Not a legal definition");
  964.                 sym = sym1;
  965.                 goto again;
  966.             }
  967.             /* else  sym == LBRACE  i.e. a definition! */
  968.  
  969.             here = pbuffer;
  970.  
  971.             put("{");
  972.             build_block();
  973.             if (tag) { /* i.e. not anonymous */
  974.                 save_tag(sym, tag, marker);
  975.  
  976.                 /* The definition is saved separately,
  977.                  * so the workbuffer will only have to
  978.                  * show an expandable definition
  979.                  */
  980.                 pbuffer = here;
  981.                 *pbuffer = '\0';
  982.                 *marker = MARK;
  983.             }
  984.  
  985.             break;
  986.  
  987.         case IDENT:
  988.             if (!expand_type(yytext))
  989.                 put(yytext); /* it was not a typedef */
  990.             break;
  991.  
  992.         case OTHER:
  993.             put(yytext);
  994.             break;
  995.  
  996.         default:
  997.             put(yytext);
  998.             break;
  999.         }
  1000.     }
  1001.     
  1002.     return;
  1003. }
  1004.  
  1005. /*
  1006.  * Main loop for parsing top level definitions/declarations in the
  1007.  * input stream. It has only a rudimentary knowledge of ANSI C,
  1008.  * but it _should_ do the right thing...
  1009.  *
  1010.  * The right thing is hereby defined to be:
  1011.  *
  1012.  * - Save all typedefs, and look for identifiers that are previously
  1013.  * defined as typedefs. Expand these by replacing the identifier
  1014.  * with the _full_ typedef definition, and append this to the work buffer.
  1015.  *
  1016.  * - Save all tagged definitions of struct/union/enum for use in possible
  1017.  * expansions at a later time (i.e. when we find the construct: 'X(symbol)'
  1018.  * in the input stream). This definition is saved as a separate entity,
  1019.  * but is also appended to the current work buffer.
  1020.  *
  1021.  * - Mark all references to tagged struct/union/enum so that they can
  1022.  * easily identified when we later (recursively) expand the definition
  1023.  * of a symbol in the input stream (i.e. the 'X(symbol)' as above).
  1024.  * The marked reference (marked by changing the first character of
  1025.  * the type into '#') is appended to the current work buffer.
  1026.  *
  1027.  * - Keep track of all global identifiers in the input stream.
  1028.  * When a complete definition is parsed, entries will be made in the
  1029.  * symbol table, with references to the parsed definition.
  1030.  * This definition is created in the work buffer at the time of parsing,
  1031.  * and is saved away (malloc) when the full definition has been parsed.
  1032.  *
  1033.  * - For all other tokens in the input stream: append to the work buffer.
  1034.  * Actually only a few tokens are recognized by the lexical analysis,
  1035.  * so the OTHER will be handled a charater at a time.
  1036.  *
  1037.  * NOTE: The work buffer (and thus the internal version of a definition)
  1038.  * consist of the tokens, each one followed by a SPACE.
  1039.  * The final semicolon in a struct/union/enum definition is not included.
  1040.  */
  1041. void
  1042. parse(void)
  1043. {
  1044.     int sym;
  1045.     int sym1;
  1046.     int started = 0; /* have we started a definition/declaration? */
  1047.     int type_def = 0; /* is this part of a typedef? */
  1048.     int parlev = 0; /* number of unmatched LPARENs, see comment at IDENT! */
  1049.     char *marker;
  1050.     char *tag;
  1051.     char *type_tag = (char *)0;
  1052.     char *here;
  1053.  
  1054.     while ((sym = yylex())) {
  1055.         /* top level */
  1056.     top_level:
  1057.         switch (sym) {
  1058.         case FILENAME: /* This is the start of a new source! */
  1059.             restart_file(yytext);
  1060.             break;
  1061.  
  1062.         case 0:
  1063.             return;
  1064.  
  1065.         case STRING:
  1066.             skip_string();
  1067.             break;
  1068.  
  1069.         case TYPEDEF:
  1070.             if (started || type_def) {
  1071.                 put_err("No typedef allowed here");
  1072.             }
  1073.             started = 1;
  1074.             type_def = 1;
  1075.             type_tag = (char *)0;
  1076.             put(yytext);
  1077.             break;
  1078.  
  1079.         case ENUM:
  1080.         case UNION:
  1081.         case STRUCT:
  1082.             if (started && !type_def && (parlev == 0)) {
  1083.                 put_err2("'%s' is not allowed here", yytext);
  1084.             }
  1085.             started = 1;
  1086.  
  1087.             marker = pbuffer; /* current "put" pointer */
  1088.             put(yytext);
  1089.  
  1090.             if ((sym1 = yylex()) == IDENT) { /* tag */
  1091.                 tag = savestr(yytext, strlen(yytext));
  1092.                 put(yytext);
  1093.                 sym1 = yylex();
  1094.             }
  1095.             else
  1096.                 tag = (char *)0;
  1097.  
  1098.  
  1099.             if (sym1 == LBRACE) { /* define */
  1100.                 here = pbuffer;
  1101.  
  1102.                 put("{");
  1103.                 build_block();
  1104.                 if (tag) {
  1105.                     save_tag(sym, tag, marker);
  1106.                     pbuffer = here;
  1107.                     *pbuffer = '\0';
  1108.                     *marker = MARK;
  1109.                 }
  1110.  
  1111.                 if ((sym = yylex()) == SEMI) {
  1112.                     parlev = 0;
  1113.                     started = 0;
  1114.                     if (type_def)
  1115.                         put_err("Illegal typedef");
  1116.                     type_def = 0;
  1117.                     if (type_tag)
  1118.                         free(type_tag);
  1119.                     /* begin anew in buffer! */
  1120.                     reset_buf(0);
  1121.                 }
  1122.                 else {
  1123.                     goto top_level;
  1124.                 }
  1125.             }
  1126.             else { /* refer */
  1127.                 if (tag) {
  1128.                     /*
  1129.                      * make a mark for easy
  1130.                      * retrieval later...
  1131.                      *
  1132.                      * struct -> #truct
  1133.                      * union  -> #nion
  1134.                      * enum   -> #num
  1135.                      */
  1136.                     *marker = MARK; /* kludge! */
  1137.                 }
  1138.                 else {
  1139.                     put_err("Not a legal definition");
  1140.                 }
  1141.                 sym = sym1;
  1142.                 goto top_level;
  1143.             }
  1144.             break;
  1145.  
  1146.         case IDENT: /* must be a TYPE or a typedef at start! */
  1147.             if (!expand_type(yytext)) {
  1148.                 if (!started && !type_def) {
  1149.                     /* OK, OK... it is an int in disguise */
  1150.                     /*
  1151.                     put_err2("type for identifier '%s' is missing", yytext);
  1152.                     */
  1153.                 }
  1154.                 if (type_def && !type_tag) {
  1155.                     type_tag = savestr(yytext, strlen(yytext));
  1156.                 }
  1157.                 else {
  1158.                     /* The following, and only real, use
  1159.                      * of parlev is here to stop IDENTs in
  1160.                      * function parameters from
  1161.                      * cluttering up the symbol table.
  1162.                      * I take the risk that there aren't
  1163.                      * that many "raw" globally defined
  1164.                      * pointers to functions, but that
  1165.                      * they instead are typedef'ed
  1166.                      *
  1167.                      * IF this will ever be a problem,
  1168.                      * just change the "#if" 1 to "#if 0"...
  1169.                      */
  1170. #if 0
  1171.                     if (parlev == 0)
  1172. #endif
  1173.                         push_id(yytext);
  1174.                 }
  1175.                 put(yytext);
  1176.             }
  1177.             started = 1;
  1178.             break;
  1179.  
  1180.         case LBRACE:
  1181.             if (!started) {
  1182.                 put_err("No '{' allowed here");
  1183.             }
  1184.             if (skip_block() == 0)
  1185.                 return;
  1186.             /* FALLTHRU */
  1187.         case SEMI:
  1188.             started = 0;
  1189.             if (type_def) {
  1190.                 type_def = 0;
  1191.                 if (type_tag)
  1192.                     save_type(type_tag);
  1193.                 type_tag = (char *)0;
  1194.                 reset_buf(0);
  1195.             }
  1196.             else {
  1197.                 reset_buf(1); /* save it if it is a def */
  1198.             }
  1199.             parlev = 0;
  1200.             break;
  1201.  
  1202.         case LPAREN:
  1203.             put("(");
  1204.             ++parlev;
  1205.             break;
  1206.  
  1207.         case RPAREN:
  1208.             put(")");
  1209.             --parlev;
  1210.             break;
  1211.  
  1212.         case TYPE: /* data types: int ... */
  1213.             started = 1;
  1214.             /* FALLTHRU */
  1215.         case S_TYPE: /* storage types: extern ... */
  1216.             put(yytext);
  1217.             break;
  1218.  
  1219.         default:
  1220.         case OTHER:
  1221.             if (!started) {
  1222.                 put_err2("No '%s' allowed here", yytext);
  1223.             }
  1224.             put(yytext);
  1225.             break;
  1226.         }
  1227.     }
  1228. }
  1229.  
  1230. int
  1231. yywrap()
  1232. {
  1233.     return 1;
  1234. }
  1235.  
  1236. int
  1237. main(int argc, char **argv)
  1238. {
  1239.     extern int mkdir(char *, int); /* I'm lazy */
  1240.     char *p;
  1241.  
  1242.     logfile = stderr;
  1243.  
  1244.     if ((p = strrchr(argv[0], '/')))
  1245.         progname = p + 1;
  1246.     else
  1247.         progname = argv[0];
  1248.  
  1249.     while ((argc > 1) && (*(p = argv[1]) == '-')) {
  1250.         while (*++p) {
  1251.             switch (*p) {
  1252.             case 'd':
  1253.                 debug += 1;
  1254.                 if (debug > 1)
  1255.                     logfile = stdout;
  1256.                 break;
  1257.  
  1258.             case 'g':
  1259.                 use_globals = 1;
  1260.                 break;
  1261.  
  1262.             case 'w':
  1263.                 warnings = 1;
  1264.                 break;
  1265.  
  1266.             case 'q':
  1267.                 warnings = 0;
  1268.                 break;
  1269.  
  1270.             case 'V':
  1271.                 printf("%s\n", copyright);
  1272.                 break;
  1273.  
  1274.             case 'D':
  1275.                 dump_defs = 1;
  1276.                 break;
  1277.  
  1278.             default:
  1279.                 fprintf(stderr, "usage: %s [-gwqdD] directory\n", progname);
  1280.                 exit (1);
  1281.                 break;
  1282.             }
  1283.         }
  1284.         ++argv;
  1285.         --argc;
  1286.  
  1287.     }
  1288.  
  1289.     if ((argc > 1) && (argv[1][0])) {
  1290.         outfile_dir = argv[1];
  1291.         outfile_flag = 1;
  1292.         outfile = (FILE *)0;
  1293.         ++argv;
  1294.         --argc;
  1295.  
  1296.         for (p = outfile_dir + 1; (p = strchr(p, '/')); p = p+1) {
  1297.             *p = '\0';
  1298.             if (access(outfile_dir, F_OK) < 0) {
  1299.                 if (mkdir(outfile_dir, 0755) < 0) {
  1300.                     perror(outfile_dir);
  1301.                     exit(1);
  1302.                 }
  1303.             }
  1304.             *p = '/';
  1305.         }
  1306.         if (access(outfile_dir, R_OK | W_OK | F_OK) < 0) {
  1307.             if (mkdir(outfile_dir, 0755) < 0) {
  1308.                 perror(outfile_dir);
  1309.                 exit(1);
  1310.             }
  1311.         }
  1312.     }
  1313.     else
  1314.         outfile = stdout;
  1315.  
  1316.     parse();
  1317.  
  1318.     if ((use_globals > 0) && symbol_root)
  1319.         show_globals(symbol_root);
  1320.  
  1321.     if (!dump_defs && outfile) {
  1322.         fprintf(outfile, "#endif /* %s */\n", macroname);
  1323.         fprintf(outfile, "#endif /* CONFIG_MODVERSIONS !__GENKSYMS__ */\n");
  1324.     }
  1325.     if (outfile != stdout)
  1326.         fclose(outfile);
  1327.  
  1328.     return 0;
  1329. }
  1330.