home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / util / makedepend / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-12  |  9.8 KB  |  451 lines

  1. /*
  2.  * $XConsortium: parse.c,v 1.21 91/05/13 10:23:47 rws Exp $
  3.  */
  4. #include "def.h"
  5.  
  6. extern char    *directives[];
  7. extern struct symtab    deflist[];
  8.  
  9. find_includes(filep, file, file_red, recursion, failOK)
  10.     struct filepointer    *filep;
  11.     struct inclist        *file, *file_red;
  12.     int            recursion;
  13.     boolean            failOK;
  14. {
  15.     register char    *line;
  16.     register int    type;
  17.     boolean recfailOK;
  18.  
  19.     while (line = getline(filep)) {
  20.         switch(type = deftype(line, filep, file_red, file, TRUE)) {
  21.         case IF:
  22.         doif:
  23.             type = find_includes(filep, file,
  24.                 file_red, recursion+1, failOK);
  25.             while ((type == ELIF) || (type == ELIFFALSE) ||
  26.                    (type == ELIFGUESSFALSE))
  27.                 type = gobble(filep, file, file_red);
  28.             if (type == ELSE)
  29.                 gobble(filep, file, file_red);
  30.             break;
  31.         case IFFALSE:
  32.         case IFGUESSFALSE:
  33.             doiffalse:
  34.             if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
  35.                 recfailOK = TRUE;
  36.             else
  37.                 recfailOK = failOK;
  38.             type = gobble(filep, file, file_red);
  39.             if (type == ELSE)
  40.                 find_includes(filep, file,
  41.                       file_red, recursion+1, recfailOK);
  42.             else
  43.             if (type == ELIF)
  44.                 goto doif;
  45.             else
  46.             if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
  47.                 goto doiffalse;
  48.             break;
  49.         case IFDEF:
  50.         case IFNDEF:
  51.             if ((type == IFDEF && isdefined(line, file_red))
  52.              || (type == IFNDEF && !isdefined(line, file_red))) {
  53.                 debug(1,(type == IFNDEF ?
  54.                     "line %d: %s !def'd in %s via %s%s\n" : "",
  55.                     filep->f_line, line,
  56.                     file->i_file, file_red->i_file, ": doit"));
  57.                 type = find_includes(filep, file,
  58.                     file_red, recursion+1, failOK);
  59.                 if (type == ELSE)
  60.                     gobble(filep, file, file_red);
  61.             }
  62.             else {
  63.                 debug(1,(type == IFDEF ?
  64.                     "line %d: %s !def'd in %s via %s%s\n" : "",
  65.                     filep->f_line, line,
  66.                     file->i_file, file_red->i_file, ": gobble"));
  67.                 type = gobble(filep, file, file_red);
  68.                 if (type == ELSE)
  69.                     find_includes(filep, file,
  70.                         file_red, recursion+1, failOK);
  71.             }
  72.             break;
  73.         case ELSE:
  74.         case ELIFFALSE:
  75.         case ELIFGUESSFALSE:
  76.         case ELIF:
  77.             if (!recursion)
  78.                 gobble(filep, file, file_red);
  79.         case ENDIF:
  80.             if (recursion)
  81.                 return(type);
  82.         case DEFINE:
  83.             define(line, file);
  84.             break;
  85.         case UNDEF:
  86.             /*
  87.              * undefine all occurances of line by killing s_name
  88.              */
  89.             if (!*line) {
  90.                 warning("%s, line %d: incomplete undef == \"%s\"\n",
  91.                 file_red->i_file, filep->f_line, line);
  92.                 break;
  93.             }
  94.             {
  95.             struct symtab *val;
  96.             for(val = isdefined(line, file_red);
  97.                 (val && val->s_name);
  98.                 val = isdefined(line, file_red))
  99.  
  100.                 val->s_name = "";
  101.             }
  102.             break;
  103.         case INCLUDE:
  104.             add_include(file, file_red, line, FALSE, failOK);
  105.             break;
  106.         case INCLUDEDOT:
  107.             add_include(file, file_red, line, TRUE, failOK);
  108.             break;
  109.         case PRAGMA:
  110.         case ERROR:
  111.         case IDENT:
  112.         case SCCS:
  113.         case EJECT:
  114.             break;
  115.         case -1:
  116.             warning("%s", file_red->i_file);
  117.             if (file_red != file)
  118.                 warning1(" (reading %s)", file->i_file);
  119.             warning1(", line %d: unknown directive == \"%s\"\n",
  120.                  filep->f_line, line);
  121.             break;
  122.         case -2:
  123.             warning("%s", file_red->i_file);
  124.             if (file_red != file)
  125.                 warning1(" (reading %s)", file->i_file);
  126.             warning1(", line %d: incomplete include == \"%s\"\n",
  127.                  filep->f_line, line);
  128.             break;
  129.         }
  130.     }
  131.     return(-1);
  132. }
  133.  
  134. gobble(filep, file, file_red)
  135.     register struct filepointer *filep;
  136.     struct inclist        *file, *file_red;
  137. {
  138.     register char    *line;
  139.     register int    type;
  140.  
  141.     while (line = getline(filep)) {
  142.         switch(type = deftype(line, filep, file_red, file, FALSE)) {
  143.         case IF:
  144.         case IFFALSE:
  145.         case IFGUESSFALSE:
  146.         case IFDEF:
  147.         case IFNDEF:
  148.             type = gobble(filep, file, file_red);
  149.             while ((type == ELIF) || (type == ELIFFALSE) ||
  150.                    (type == ELIFGUESSFALSE))
  151.                 type = gobble(filep, file, file_red);
  152.             if (type == ELSE)
  153.                     (void)gobble(filep, file, file_red);
  154.             break;
  155.         case ELSE:
  156.         case ENDIF:
  157.             debug(0,("%s, line %d: #%s\n",
  158.                 file->i_file, filep->f_line,
  159.                 directives[type]));
  160.             return(type);
  161.         case DEFINE:
  162.         case UNDEF:
  163.         case INCLUDE:
  164.         case INCLUDEDOT:
  165.         case PRAGMA:
  166.         case ERROR:
  167.         case IDENT:
  168.         case SCCS:
  169.         case EJECT:
  170.             break;
  171.         case ELIF:
  172.         case ELIFFALSE:
  173.         case ELIFGUESSFALSE:
  174.             return(type);
  175.         case -1:
  176.             warning("%s, line %d: unknown directive == \"%s\"\n",
  177.                 file_red->i_file, filep->f_line, line);
  178.             break;
  179.         }
  180.     }
  181.     return(-1);
  182. }
  183.  
  184. /*
  185.  * Decide what type of # directive this line is.
  186.  */
  187. int deftype (line, filep, file_red, file, parse_it)
  188.     register char    *line;
  189.     register struct filepointer *filep;
  190.     register struct inclist *file_red, *file;
  191.     int    parse_it;
  192. {
  193.     register char    *p;
  194.     char    *directive, savechar;
  195.     register int    ret;
  196.  
  197.     /*
  198.      * Parse the directive...
  199.      */
  200.     directive=line+1;
  201.     while (*directive == ' ' || *directive == '\t')
  202.         directive++;
  203.  
  204.     p = directive;
  205.     while (*p >= 'a' && *p <= 'z')
  206.         p++;
  207.     savechar = *p;
  208.     *p = '\0';
  209.     ret = match(directive, directives);
  210.     *p = savechar;
  211.  
  212.     /* If we don't recognize this compiler directive or we happen to just
  213.      * be gobbling up text while waiting for an #endif or #elif or #else
  214.      * in the case of an #elif we must check the zero_value and return an
  215.      * ELIF or an ELIFFALSE.
  216.      */
  217.  
  218.     if (ret == ELIF && !parse_it)
  219.     {
  220.         while (*p == ' ' || *p == '\t')
  221.         p++;
  222.         /*
  223.          * parse an expression.
  224.          */
  225.         debug(0,("%s, line %d: #elif %s ",
  226.            file->i_file, filep->f_line, p));
  227.         ret = zero_value(p, filep, file_red);
  228.         if (ret != IF)
  229.         {
  230.         debug(0,("false...\n"));
  231.         if (ret == IFFALSE)
  232.             return(ELIFFALSE);
  233.         else
  234.             return(ELIFGUESSFALSE);
  235.         }
  236.         else
  237.         {
  238.         debug(0,("true...\n"));
  239.         return(ELIF);
  240.         }
  241.     }
  242.  
  243.     if (ret < 0 || ! parse_it)
  244.         return(ret);
  245.  
  246.     /*
  247.      * now decide how to parse the directive, and do it.
  248.      */
  249.     while (*p == ' ' || *p == '\t')
  250.         p++;
  251.     switch (ret) {
  252.     case IF:
  253.         /*
  254.          * parse an expression.
  255.          */
  256.         debug(0,("%s, line %d: #if %s\n",
  257.             file->i_file, filep->f_line, p));
  258.         ret = zero_value(p, filep, file_red);
  259.         break;
  260.     case IFDEF:
  261.     case IFNDEF:
  262.         debug(0,("%s, line %d: #%s %s\n",
  263.             file->i_file, filep->f_line, directives[ret], p));
  264.     case UNDEF:
  265.         /*
  266.          * separate the name of a single symbol.
  267.          */
  268.         while (isalnum(*p) || *p == '_')
  269.             *line++ = *p++;
  270.         *line = '\0';
  271.         break;
  272.     case INCLUDE:
  273.         debug(2,("%s, line %d: #include %s\n",
  274.             file->i_file, filep->f_line, p));
  275.  
  276.         /* Support ANSI macro substitution */
  277.         {
  278.             struct symtab *sym = isdefined(p, file_red);
  279.             while (sym) {
  280.             p = sym->s_value;
  281.             debug(3,("%s : #includes SYMBOL %s = %s\n",
  282.                    file->i_incstring,
  283.                    sym -> s_name,
  284.                    sym -> s_value));
  285.             /* mark file as having included a 'soft include' */
  286.             file->i_included_sym = TRUE; 
  287.             sym = isdefined(p, file_red);
  288.             }
  289.         }
  290.  
  291.         /*
  292.          * Separate the name of the include file.
  293.          */
  294.         while (*p && *p != '"' && *p != '<')
  295.             p++;
  296.         if (! *p)
  297.             return(-2);
  298.         if (*p++ == '"') {
  299.             ret = INCLUDEDOT;
  300.             while (*p && *p != '"')
  301.                 *line++ = *p++;
  302.         } else
  303.             while (*p && *p != '>')
  304.                 *line++ = *p++;
  305.         *line = '\0';
  306.         break;
  307.     case DEFINE:
  308.         /*
  309.          * copy the definition back to the beginning of the line.
  310.          */
  311.         strcpy (line, p);
  312.         break;
  313.     case ELSE:
  314.     case ENDIF:
  315.     case ELIF:
  316.     case PRAGMA:
  317.     case ERROR:
  318.     case IDENT:
  319.     case SCCS:
  320.     case EJECT:
  321.         debug(0,("%s, line %d: #%s\n",
  322.             file->i_file, filep->f_line, directives[ret]));
  323.         /*
  324.          * nothing to do.
  325.          */
  326.         break;
  327.     }
  328.     return(ret);
  329. }
  330.  
  331. struct symtab *isdefined(symbol, file)
  332.     register char    *symbol;
  333.     struct inclist    *file;
  334. {
  335.     register struct symtab    *val;
  336.  
  337.     if (val = slookup(symbol, deflist)) {
  338.         debug(1,("%s defined on command line\n", symbol));
  339.         return(val);
  340.     }
  341.     if (val = fdefined(symbol, file))
  342.         return(val);
  343.     debug(1,("%s not defined in %s\n", symbol, file->i_file));
  344.     return(NULL);
  345. }
  346.  
  347. struct symtab *fdefined(symbol, file)
  348.     register char    *symbol;
  349.     struct inclist    *file;
  350. {
  351.     register struct inclist    **ip;
  352.     register struct symtab    *val;
  353.     register int    i;
  354.     static int    recurse_lvl = 0;
  355.  
  356.     if (file->i_defchecked)
  357.         return(NULL);
  358.     file->i_defchecked = TRUE;
  359.     if (val = slookup(symbol, file->i_defs))
  360.         debug(1,("%s defined in %s\n", symbol, file->i_file));
  361.     if (val == NULL && file->i_list)
  362.         for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
  363.             if (val = fdefined(symbol, *ip)) {
  364.                 debug(1,("%s defined in %s\n",
  365.                     symbol, (*ip)->i_file));
  366.                 break;
  367.             }
  368.     recurse_lvl--;
  369.     file->i_defchecked = FALSE;
  370.  
  371.     return(val);
  372. }
  373.  
  374. struct symtab *slookup(symbol, stab)
  375.     register char    *symbol;
  376.     register struct symtab    *stab;
  377. {
  378.     if (stab)
  379.         for (; stab->s_name; stab++)
  380.             if (strcmp(symbol, stab->s_name) == 0)
  381.                 return(stab);
  382.     return(NULL);
  383. }
  384.  
  385. /*
  386.  * Return type based on if the #if expression evaluates to 0
  387.  */
  388. zero_value(exp, filep, file_red)
  389.     register char    *exp;
  390.     register struct filepointer *filep;
  391.     register struct inclist *file_red;
  392. {
  393. #ifdef    CPP
  394.     if (cppsetup(exp, filep, file_red))
  395.         return(IFFALSE);
  396.     else
  397.         return(IF);
  398. #else
  399.     return(IFGUESSFALSE);
  400. #endif /* CPP */
  401. }
  402.  
  403. define(def, file)
  404.     register char    *def;
  405.     register struct inclist    *file;
  406. {
  407.     register char    *p;
  408.     struct symtab    *sp = file->i_lastdef++;
  409.     register int    i;
  410.  
  411.     /*
  412.      * If we are out of space, allocate some more.
  413.      */
  414.     if (file->i_defs == NULL
  415.     || file->i_lastdef == file->i_defs + file->i_deflen) {
  416.         if (file->i_defs)
  417.             file->i_defs = (struct symtab *) realloc(file->i_defs,
  418.                 sizeof(struct symtab)*(file->i_deflen+SYMTABINC));
  419.         else
  420.             file->i_defs = (struct symtab *)
  421.                 malloc(sizeof (struct symtab) * SYMTABINC);
  422.         i=file->i_deflen;
  423.         file->i_deflen += SYMTABINC;
  424.         while (i < file->i_deflen)
  425.             file->i_defs[ i++ ].s_name = NULL;
  426.         file->i_lastdef = file->i_defs + file->i_deflen - SYMTABINC;
  427.         if (sp) /* be sure we use last cell in previous group */
  428.             file->i_lastdef--;
  429.         sp = file->i_lastdef++;
  430.     }
  431.     else if (file->i_lastdef > file->i_defs + file->i_deflen)
  432.         fatal("define() botch\n");
  433.  
  434.     /*
  435.      * copy the symbol being defined.
  436.      */
  437.     p = def;
  438.     while (isalnum(*p) || *p == '_')
  439.         p++;
  440.     if (*p)
  441.         *p++ = '\0';
  442.     sp->s_name = copy(def);
  443.  
  444.     /*
  445.      * And copy its value.
  446.      */
  447.     while (*p == ' ' && *p == '\t')
  448.         p++;
  449.     sp->s_value = copy(p);
  450. }
  451.