home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / ice / pisces / mkdepend / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-04  |  9.9 KB  |  464 lines

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