/[make]/make/read.c
ViewVC logotype

Diff of /make/read.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.144 by psmith, Tue May 3 13:57:20 2005 UTC revision 1.145 by psmith, Fri May 13 12:45:30 2005 UTC
# Line 78  struct conditionals Line 78  struct conditionals
78    {    {
79      unsigned int if_cmds;       /* Depth of conditional nesting.  */      unsigned int if_cmds;       /* Depth of conditional nesting.  */
80      unsigned int allocated;     /* Elts allocated in following arrays.  */      unsigned int allocated;     /* Elts allocated in following arrays.  */
81      char *ignoring;             /* Are we ignoring or interepreting?  */      char *ignoring;             /* Are we ignoring or interpreting?
82                                       0=interpreting, 1=not yet interpreted,
83                                       2=already interpreted */
84      char *seen_else;            /* Have we already seen an `else'?  */      char *seen_else;            /* Have we already seen an `else'?  */
85    };    };
86    
# Line 130  static long readline PARAMS ((struct ebu Line 132  static long readline PARAMS ((struct ebu
132  static void do_define PARAMS ((char *name, unsigned int namelen,  static void do_define PARAMS ((char *name, unsigned int namelen,
133                                 enum variable_origin origin,                                 enum variable_origin origin,
134                                 struct ebuffer *ebuf));                                 struct ebuffer *ebuf));
135  static int conditional_line PARAMS ((char *line, const struct floc *flocp));  static int conditional_line PARAMS ((char *line, int len, const struct floc *flocp));
136  static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,  static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent,
137                          struct dep *deps, unsigned int cmds_started, char *commands,                          struct dep *deps, unsigned int cmds_started, char *commands,
138                          unsigned int commands_idx, int two_colon,                          unsigned int commands_idx, int two_colon,
# Line 613  eval (struct ebuffer *ebuf, int set_defa Line 615  eval (struct ebuffer *ebuf, int set_defa
615           ignoring anything, since they control what we will do with           ignoring anything, since they control what we will do with
616           following lines.  */           following lines.  */
617    
618        if (!in_ignored_define        if (!in_ignored_define)
           && (word1eq ("ifdef") || word1eq ("ifndef")  
               || word1eq ("ifeq") || word1eq ("ifneq")  
               || word1eq ("else") || word1eq ("endif")))  
619          {          {
620            int i = conditional_line (p, fstart);            int i = conditional_line (p, len, fstart);
621            if (i < 0)            if (i != -2)
622              fatal (fstart, _("invalid syntax in conditional"));              {
623                  if (i == -1)
624                    fatal (fstart, _("invalid syntax in conditional"));
625    
626            ignoring = i;                ignoring = i;
627            continue;                continue;
628                }
629          }          }
630    
631        if (word1eq ("endef"))        if (word1eq ("endef"))
# Line 1420  do_define (char *name, unsigned int name Line 1422  do_define (char *name, unsigned int name
1422     FILENAME and LINENO are the filename and line number in the     FILENAME and LINENO are the filename and line number in the
1423     current makefile.  They are used for error messages.     current makefile.  They are used for error messages.
1424    
1425     Value is -1 if the line is invalid,     Value is -2 if the line is not a conditional at all,
1426       -1 if the line is an invalid conditional,
1427     0 if following text should be interpreted,     0 if following text should be interpreted,
1428     1 if following text should be ignored.  */     1 if following text should be ignored.  */
1429    
1430  static int  static int
1431  conditional_line (char *line, const struct floc *flocp)  conditional_line (char *line, int len, const struct floc *flocp)
1432  {  {
   int notdef;  
1433    char *cmdname;    char *cmdname;
1434    register unsigned int i;    enum { c_ifdef, c_ifndef, c_ifeq, c_ifneq, c_else, c_endif } cmdtype;
1435      unsigned int i;
1436    if (*line == 'i')    unsigned int o;
1437      {  
1438        /* It's an "if..." command.  */    /* Compare a word, both length and contents. */
1439        notdef = line[2] == 'n';  #define word1eq(s)      (len == sizeof(s)-1 && strneq (s, line, sizeof(s)-1))
1440        if (notdef)  #define chkword(s, t)   if (word1eq (s)) { cmdtype = (t); cmdname = (s); }
1441          {  
1442            cmdname = line[3] == 'd' ? "ifndef" : "ifneq";    /* Make sure this line is a conditional.  */
1443            line += cmdname[3] == 'd' ? 7 : 6;    chkword ("ifdef", c_ifdef)
1444          }    else chkword ("ifndef", c_ifndef)
1445        else    else chkword ("ifeq", c_ifeq)
1446          {    else chkword ("ifneq", c_ifneq)
1447            cmdname = line[2] == 'd' ? "ifdef" : "ifeq";    else chkword ("else", c_else)
1448            line += cmdname[2] == 'd' ? 6 : 5;    else chkword ("endif", c_endif)
         }  
     }  
1449    else    else
1450      {      return -2;
1451        /* It's an "else" or "endif" command.  */  
1452        notdef = line[1] == 'n';    /* Found one: skip past it and any whitespace after it.  */
1453        cmdname = notdef ? "endif" : "else";    line = next_token (line + len);
       line += notdef ? 5 : 4;  
     }  
1454    
1455    line = next_token (line);  #define EXTRANEOUS() error (flocp, _("Extraneous text after `%s' directive"), cmdname)
1456    
1457    if (*cmdname == 'e')    /* An 'endif' cannot contain extra text, and reduces the if-depth by 1  */
1458      if (cmdtype == c_endif)
1459      {      {
1460        if (*line != '\0')        if (*line != '\0')
1461          error (flocp, _("Extraneous text after `%s' directive"), cmdname);          EXTRANEOUS ();
1462        /* "Else" or "endif".  */  
1463        if (conditionals->if_cmds == 0)        if (!conditionals->if_cmds)
1464          fatal (flocp, _("extraneous `%s'"), cmdname);          fatal (flocp, _("extraneous `%s'"), cmdname);
1465        /* NOTDEF indicates an `endif' command.  */  
1466        if (notdef)        --conditionals->if_cmds;
1467          --conditionals->if_cmds;  
1468        else if (conditionals->seen_else[conditionals->if_cmds - 1])        goto DONE;
1469          fatal (flocp, _("only one `else' per conditional"));      }
1470    
1471      /* An 'else' statement can either be simple, or it can have another
1472         conditional after it.  */
1473      if (cmdtype == c_else)
1474        {
1475          const char *p;
1476    
1477          if (!conditionals->if_cmds)
1478            fatal (flocp, _("extraneous `%s'"), cmdname);
1479    
1480          o = conditionals->if_cmds - 1;
1481    
1482          if (conditionals->seen_else[o])
1483            fatal (flocp, _("only one `else' per conditional"));
1484    
1485          /* Change the state of ignorance.  */
1486          switch (conditionals->ignoring[o])
1487            {
1488              case 0:
1489                /* We've just been interpreting.  Never do it again.  */
1490                conditionals->ignoring[o] = 2;
1491                break;
1492              case 1:
1493                /* We've never interpreted yet.  Maybe this time!  */
1494                conditionals->ignoring[o] = 0;
1495                break;
1496            }
1497    
1498          /* It's a simple 'else'.  */
1499          if (*line == '\0')
1500            {
1501              conditionals->seen_else[o] = 1;
1502              goto DONE;
1503            }
1504    
1505          /* The 'else' has extra text.  That text must be another conditional
1506             and cannot be an 'else' or 'endif'.  */
1507    
1508          /* Find the length of the next word.  */
1509          for (p = line+1; *p != '\0' && !isspace ((unsigned char)*p); ++p)
1510            ;
1511          len = p - line;
1512    
1513          /* If it's 'else' or 'endif' or an illegal conditional, fail.  */
1514          if (word1eq("else") || word1eq("endif")
1515              || conditional_line (line, len, flocp) < 0)
1516            EXTRANEOUS ();
1517        else        else
1518          {          {
1519            /* Toggle the state of ignorance.  */            /* conditional_line() created a new level of conditional.
1520            conditionals->ignoring[conditionals->if_cmds - 1]               Raise it back to this level.  */
1521              = !conditionals->ignoring[conditionals->if_cmds - 1];            if (conditionals->ignoring[o] < 2)
1522            /* Record that we have seen an `else' in this conditional.              conditionals->ignoring[o] = conditionals->ignoring[o+1];
1523               A second `else' will be erroneous.  */            --conditionals->if_cmds;
1524            conditionals->seen_else[conditionals->if_cmds - 1] = 1;          }
1525          }  
1526        for (i = 0; i < conditionals->if_cmds; ++i)        goto DONE;
         if (conditionals->ignoring[i])  
           return 1;  
       return 0;  
1527      }      }
1528    
1529    if (conditionals->allocated == 0)    if (conditionals->allocated == 0)
# Line 1490  conditional_line (char *line, const stru Line 1533  conditional_line (char *line, const stru
1533        conditionals->seen_else = (char *) xmalloc (conditionals->allocated);        conditionals->seen_else = (char *) xmalloc (conditionals->allocated);
1534      }      }
1535    
1536    ++conditionals->if_cmds;    o = conditionals->if_cmds++;
1537    if (conditionals->if_cmds > conditionals->allocated)    if (conditionals->if_cmds > conditionals->allocated)
1538      {      {
1539        conditionals->allocated += 5;        conditionals->allocated += 5;
# Line 1501  conditional_line (char *line, const stru Line 1544  conditional_line (char *line, const stru
1544      }      }
1545    
1546    /* Record that we have seen an `if...' but no `else' so far.  */    /* Record that we have seen an `if...' but no `else' so far.  */
1547    conditionals->seen_else[conditionals->if_cmds - 1] = 0;    conditionals->seen_else[o] = 0;
1548    
1549    /* Search through the stack to see if we're already ignoring.  */    /* Search through the stack to see if we're already ignoring.  */
1550    for (i = 0; i < conditionals->if_cmds - 1; ++i)    for (i = 0; i < o; ++i)
1551      if (conditionals->ignoring[i])      if (conditionals->ignoring[i])
1552        {        {
1553          /* We are already ignoring, so just push a level          /* We are already ignoring, so just push a level to match the next
1554             to match the next "else" or "endif", and keep ignoring.             "else" or "endif", and keep ignoring.  We don't want to expand
1555             We don't want to expand variables in the condition.  */             variables in the condition.  */
1556          conditionals->ignoring[conditionals->if_cmds - 1] = 1;          conditionals->ignoring[o] = 1;
1557          return 1;          return 1;
1558        }        }
1559    
1560    if (cmdname[notdef ? 3 : 2] == 'd')    if (cmdtype == c_ifdef || cmdtype == c_ifndef)
1561      {      {
       /* "Ifdef" or "ifndef".  */  
1562        char *var;        char *var;
1563        struct variable *v;        struct variable *v;
1564        register char *p;        char *p;
1565    
1566        /* Expand the thing we're looking up, so we can use indirect and        /* Expand the thing we're looking up, so we can use indirect and
1567           constructed variable names.  */           constructed variable names.  */
# Line 1533  conditional_line (char *line, const stru Line 1575  conditional_line (char *line, const stru
1575          return -1;          return -1;
1576    
1577        var[i] = '\0';        var[i] = '\0';
1578        v = lookup_variable (var, strlen (var));        v = lookup_variable (var, i);
1579        conditionals->ignoring[conditionals->if_cmds - 1]  
1580          = (v != 0 && *v->value != '\0') == notdef;        conditionals->ignoring[o] =
1581            ((v != 0 && *v->value != '\0') == (cmdtype == c_ifndef));
1582    
1583        free (var);        free (var);
1584      }      }
# Line 1553  conditional_line (char *line, const stru Line 1596  conditional_line (char *line, const stru
1596        /* Find the end of the first string.  */        /* Find the end of the first string.  */
1597        if (termin == ',')        if (termin == ',')
1598          {          {
1599            register int count = 0;            int count = 0;
1600            for (; *line != '\0'; ++line)            for (; *line != '\0'; ++line)
1601              if (*line == '(')              if (*line == '(')
1602                ++count;                ++count;
# Line 1627  conditional_line (char *line, const stru Line 1670  conditional_line (char *line, const stru
1670        *line = '\0';        *line = '\0';
1671        line = next_token (++line);        line = next_token (++line);
1672        if (*line != '\0')        if (*line != '\0')
1673          error (flocp, _("Extraneous text after `%s' directive"), cmdname);          EXTRANEOUS ();
1674    
1675        s2 = variable_expand (s2);        s2 = variable_expand (s2);
1676        conditionals->ignoring[conditionals->if_cmds - 1]        conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));
         = streq (s1, s2) == notdef;  
1677      }      }
1678    
1679     DONE:
1680    /* Search through the stack to see if we're ignoring.  */    /* Search through the stack to see if we're ignoring.  */
1681    for (i = 0; i < conditionals->if_cmds; ++i)    for (i = 0; i < conditionals->if_cmds; ++i)
1682      if (conditionals->ignoring[i])      if (conditionals->ignoring[i])

Legend:
Removed from v.1.144  
changed lines
  Added in v.1.145

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26