Merge from vendor branch GDB:
[dragonfly.git] / usr.bin / make / cond.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1988, 1989 by Adam de Boor
5  * Copyright (c) 1989 by Berkeley Softworks
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Adam de Boor.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  * @(#)cond.c   8.2 (Berkeley) 1/2/94
40  * $FreeBSD: src/usr.bin/make/cond.c,v 1.12.2.1 2003/07/22 08:03:13 ru Exp $
41  * $DragonFly: src/usr.bin/make/cond.c,v 1.9 2004/11/12 22:57:04 dillon Exp $
42  */
43
44 /*-
45  * cond.c --
46  *      Functions to handle conditionals in a makefile.
47  *
48  * Interface:
49  *      Cond_Eval       Evaluate the conditional in the passed line.
50  *
51  */
52
53 #include    <ctype.h>
54 #include    <math.h>
55 #include    "make.h"
56 #include    "hash.h"
57 #include    "dir.h"
58 #include    "buf.h"
59
60 /*
61  * The parsing of conditional expressions is based on this grammar:
62  *      E -> F || E
63  *      E -> F
64  *      F -> T && F
65  *      F -> T
66  *      T -> defined(variable)
67  *      T -> make(target)
68  *      T -> exists(file)
69  *      T -> empty(varspec)
70  *      T -> target(name)
71  *      T -> symbol
72  *      T -> $(varspec) op value
73  *      T -> $(varspec) == "string"
74  *      T -> $(varspec) != "string"
75  *      T -> ( E )
76  *      T -> ! T
77  *      op -> == | != | > | < | >= | <=
78  *
79  * 'symbol' is some other symbol to which the default function (condDefProc)
80  * is applied.
81  *
82  * Tokens are scanned from the 'condExpr' string. The scanner (CondToken)
83  * will return And for '&' and '&&', Or for '|' and '||', Not for '!',
84  * LParen for '(', RParen for ')' and will evaluate the other terminal
85  * symbols, using either the default function or the function given in the
86  * terminal, and return the result as either True or False.
87  *
88  * All Non-Terminal functions (CondE, CondF and CondT) return Err on error.
89  */
90 typedef enum {
91     And, Or, Not, True, False, LParen, RParen, EndOfFile, None, Err
92 } Token;
93
94 /*-
95  * Structures to handle elegantly the different forms of #if's. The
96  * last two fields are stored in condInvert and condDefProc, respectively.
97  */
98 static void CondPushBack(Token);
99 static int CondGetArg(char **, char **, char *, Boolean);
100 static Boolean CondDoDefined(int, char *);
101 static int CondStrMatch(void *, void *);
102 static Boolean CondDoMake(int, char *);
103 static Boolean CondDoExists(int, char *);
104 static Boolean CondDoTarget(int, char *);
105 static char * CondCvtArg(char *, double *);
106 static Token CondToken(Boolean);
107 static Token CondT(Boolean);
108 static Token CondF(Boolean);
109 static Token CondE(Boolean);
110
111 static struct If {
112     char        *form;        /* Form of if */
113     int         formlen;      /* Length of form */
114     Boolean     doNot;        /* TRUE if default function should be negated */
115     Boolean     (*defProc)(int, char *); /* Default function to apply */
116 } ifs[] = {
117     { "ifdef",    5,      FALSE,  CondDoDefined },
118     { "ifndef",   6,      TRUE,   CondDoDefined },
119     { "ifmake",   6,      FALSE,  CondDoMake },
120     { "ifnmake",  7,      TRUE,   CondDoMake },
121     { "if",       2,      FALSE,  CondDoDefined },
122     { NULL,       0,      FALSE,  NULL }
123 };
124
125 static Boolean    condInvert;           /* Invert the default function */
126 static Boolean    (*condDefProc)        /* Default function to apply */
127                    (int, char *);
128 static char       *condExpr;            /* The expression to parse */
129 static Token      condPushBack=None;    /* Single push-back token used in
130                                          * parsing */
131
132 #define MAXIF           30        /* greatest depth of #if'ing */
133
134 static Boolean    condStack[MAXIF];     /* Stack of conditionals's values */
135 static int        condTop = MAXIF;      /* Top-most conditional */
136 static int        skipIfLevel=0;        /* Depth of skipped conditionals */
137 static Boolean    skipLine = FALSE;     /* Whether the parse module is skipping
138                                          * lines */
139
140 /*-
141  *-----------------------------------------------------------------------
142  * CondPushBack --
143  *      Push back the most recent token read. We only need one level of
144  *      this, so the thing is just stored in 'condPushback'.
145  *
146  * Results:
147  *      None.
148  *
149  * Side Effects:
150  *      condPushback is overwritten.
151  *
152  *-----------------------------------------------------------------------
153  */
154 static void
155 CondPushBack (Token t)
156 {
157     condPushBack = t;
158 }
159 \f
160 /*-
161  *-----------------------------------------------------------------------
162  * CondGetArg --
163  *      Find the argument of a built-in function.  parens is set to TRUE
164  *      if the arguments are bounded by parens.
165  *
166  * Results:
167  *      The length of the argument and the address of the argument.
168  *
169  * Side Effects:
170  *      The pointer is set to point to the closing parenthesis of the
171  *      function call.
172  *
173  *-----------------------------------------------------------------------
174  */
175 static int
176 CondGetArg (char **linePtr, char **argPtr, char *func, Boolean parens)
177 {
178     char          *cp;
179     int           argLen;
180     Buffer        buf;
181
182     cp = *linePtr;
183     if (parens) {
184         while (*cp != '(' && *cp != '\0') {
185             cp++;
186         }
187         if (*cp == '(') {
188             cp++;
189         }
190     }
191
192     if (*cp == '\0') {
193         /*
194          * No arguments whatsoever. Because 'make' and 'defined' aren't really
195          * "reserved words", we don't print a message. I think this is better
196          * than hitting the user with a warning message every time s/he uses
197          * the word 'make' or 'defined' at the beginning of a symbol...
198          */
199         *argPtr = cp;
200         return (0);
201     }
202
203     while (*cp == ' ' || *cp == '\t') {
204         cp++;
205     }
206
207     /*
208      * Create a buffer for the argument and start it out at 16 characters
209      * long. Why 16? Why not?
210      */
211     buf = Buf_Init(16);
212
213     while ((strchr(" \t)&|", *cp) == (char *)NULL) && (*cp != '\0')) {
214         if (*cp == '$') {
215             /*
216              * Parse the variable spec and install it as part of the argument
217              * if it's valid. We tell Var_Parse to complain on an undefined
218              * variable, so we don't do it too. Nor do we return an error,
219              * though perhaps we should...
220              */
221             char        *cp2;
222             int         len;
223             Boolean     doFree;
224
225             cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree);
226
227             Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
228             if (doFree) {
229                 free(cp2);
230             }
231             cp += len;
232         } else {
233             Buf_AddByte(buf, (Byte)*cp);
234             cp++;
235         }
236     }
237
238     Buf_AddByte(buf, (Byte)'\0');
239     *argPtr = (char *)Buf_GetAll(buf, &argLen);
240     Buf_Destroy(buf, FALSE);
241
242     while (*cp == ' ' || *cp == '\t') {
243         cp++;
244     }
245     if (parens && *cp != ')') {
246         Parse_Error (PARSE_WARNING, "Missing closing parenthesis for %s()",
247                      func);
248         return (0);
249     } else if (parens) {
250         /*
251          * Advance pointer past close parenthesis.
252          */
253         cp++;
254     }
255
256     *linePtr = cp;
257     return (argLen);
258 }
259 \f
260 /*-
261  *-----------------------------------------------------------------------
262  * CondDoDefined --
263  *      Handle the 'defined' function for conditionals.
264  *
265  * Results:
266  *      TRUE if the given variable is defined.
267  *
268  * Side Effects:
269  *      None.
270  *
271  *-----------------------------------------------------------------------
272  */
273 static Boolean
274 CondDoDefined (int argLen, char *arg)
275 {
276     char    savec = arg[argLen];
277     char    *p1;
278     Boolean result;
279
280     arg[argLen] = '\0';
281     if (Var_Value (arg, VAR_CMD, &p1) != (char *)NULL) {
282         result = TRUE;
283     } else {
284         result = FALSE;
285     }
286     free(p1);
287     arg[argLen] = savec;
288     return (result);
289 }
290 \f
291 /*-
292  *-----------------------------------------------------------------------
293  * CondStrMatch --
294  *      Front-end for Str_Match so it returns 0 on match and non-zero
295  *      on mismatch. Callback function for CondDoMake via Lst_Find
296  *
297  * Results:
298  *      0 if string matches pattern
299  *
300  * Side Effects:
301  *      None
302  *
303  *-----------------------------------------------------------------------
304  */
305 static int
306 CondStrMatch(void *string, void *pattern)
307 {
308     return(!Str_Match((char *) string,(char *) pattern));
309 }
310 \f
311 /*-
312  *-----------------------------------------------------------------------
313  * CondDoMake --
314  *      Handle the 'make' function for conditionals.
315  *
316  * Results:
317  *      TRUE if the given target is being made.
318  *
319  * Side Effects:
320  *      None.
321  *
322  *-----------------------------------------------------------------------
323  */
324 static Boolean
325 CondDoMake (int argLen, char *arg)
326 {
327     char    savec = arg[argLen];
328     Boolean result;
329
330     arg[argLen] = '\0';
331     if (Lst_Find (create, (void *)arg, CondStrMatch) == NULL) {
332         result = FALSE;
333     } else {
334         result = TRUE;
335     }
336     arg[argLen] = savec;
337     return (result);
338 }
339 \f
340 /*-
341  *-----------------------------------------------------------------------
342  * CondDoExists --
343  *      See if the given file exists.
344  *
345  * Results:
346  *      TRUE if the file exists and FALSE if it does not.
347  *
348  * Side Effects:
349  *      None.
350  *
351  *-----------------------------------------------------------------------
352  */
353 static Boolean
354 CondDoExists (int argLen, char *arg)
355 {
356     char    savec = arg[argLen];
357     Boolean result;
358     char    *path;
359
360     arg[argLen] = '\0';
361     path = Dir_FindFile(arg, dirSearchPath);
362     if (path != (char *)NULL) {
363         result = TRUE;
364         free(path);
365     } else {
366         result = FALSE;
367     }
368     arg[argLen] = savec;
369     return (result);
370 }
371 \f
372 /*-
373  *-----------------------------------------------------------------------
374  * CondDoTarget --
375  *      See if the given node exists and is an actual target.
376  *
377  * Results:
378  *      TRUE if the node exists as a target and FALSE if it does not.
379  *
380  * Side Effects:
381  *      None.
382  *
383  *-----------------------------------------------------------------------
384  */
385 static Boolean
386 CondDoTarget (int argLen, char *arg)
387 {
388     char    savec = arg[argLen];
389     Boolean result;
390     GNode   *gn;
391
392     arg[argLen] = '\0';
393     gn = Targ_FindNode(arg, TARG_NOCREATE);
394     if ((gn != NULL) && !OP_NOP(gn->type)) {
395         result = TRUE;
396     } else {
397         result = FALSE;
398     }
399     arg[argLen] = savec;
400     return (result);
401 }
402
403 \f
404 /*-
405  *-----------------------------------------------------------------------
406  * CondCvtArg --
407  *      Convert the given number into a double. If the number begins
408  *      with 0x, it is interpreted as a hexadecimal integer
409  *      and converted to a double from there. All other strings just have
410  *      strtod called on them.
411  *
412  * Results:
413  *      Sets 'value' to double value of string.
414  *      Returns address of the first character after the last valid
415  *      character of the converted number.
416  *
417  * Side Effects:
418  *      Can change 'value' even if string is not a valid number.
419  *
420  *
421  *-----------------------------------------------------------------------
422  */
423 static char *
424 CondCvtArg(char *str, double *value)
425 {
426     if ((*str == '0') && (str[1] == 'x')) {
427         long i;
428
429         for (str += 2, i = 0; ; str++) {
430             int x;
431             if (isdigit((unsigned char) *str))
432                 x  = *str - '0';
433             else if (isxdigit((unsigned char) *str))
434                 x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';
435             else {
436                 *value = (double) i;
437                 return str;
438             }
439             i = (i << 4) + x;
440         }
441     }
442     else {
443         char *eptr;
444         *value = strtod(str, &eptr);
445         return eptr;
446     }
447 }
448 \f
449 /*-
450  *-----------------------------------------------------------------------
451  * CondToken --
452  *      Return the next token from the input.
453  *
454  * Results:
455  *      A Token for the next lexical token in the stream.
456  *
457  * Side Effects:
458  *      condPushback will be set back to None if it is used.
459  *
460  *-----------------------------------------------------------------------
461  */
462 static Token
463 CondToken(Boolean doEval)
464 {
465     Token         t;
466
467     if (condPushBack == None) {
468         while (*condExpr == ' ' || *condExpr == '\t') {
469             condExpr++;
470         }
471         switch (*condExpr) {
472             case '(':
473                 t = LParen;
474                 condExpr++;
475                 break;
476             case ')':
477                 t = RParen;
478                 condExpr++;
479                 break;
480             case '|':
481                 if (condExpr[1] == '|') {
482                     condExpr++;
483                 }
484                 condExpr++;
485                 t = Or;
486                 break;
487             case '&':
488                 if (condExpr[1] == '&') {
489                     condExpr++;
490                 }
491                 condExpr++;
492                 t = And;
493                 break;
494             case '!':
495                 t = Not;
496                 condExpr++;
497                 break;
498             case '\n':
499             case '\0':
500                 t = EndOfFile;
501                 break;
502             case '$': {
503                 char    *lhs;
504                 char    *rhs;
505                 char    *op;
506                 int     varSpecLen;
507                 Boolean doFree;
508
509                 /*
510                  * Parse the variable spec and skip over it, saving its
511                  * value in lhs.
512                  */
513                 t = Err;
514                 lhs = Var_Parse(condExpr, VAR_CMD, doEval,&varSpecLen,&doFree);
515                 if (lhs == var_Error) {
516                     /*
517                      * Even if !doEval, we still report syntax errors, which
518                      * is what getting var_Error back with !doEval means.
519                      */
520                     return(Err);
521                 }
522                 condExpr += varSpecLen;
523
524                 if (!isspace((unsigned char) *condExpr) &&
525                     strchr("!=><", *condExpr) == NULL) {
526                     Buffer buf;
527                     char *cp;
528
529                     buf = Buf_Init(0);
530
531                     for (cp = lhs; *cp; cp++)
532                         Buf_AddByte(buf, (Byte)*cp);
533
534                     if (doFree)
535                         free(lhs);
536
537                     for (;*condExpr && !isspace((unsigned char) *condExpr);
538                          condExpr++)
539                         Buf_AddByte(buf, (Byte)*condExpr);
540
541                     Buf_AddByte(buf, (Byte)'\0');
542                     lhs = (char *)Buf_GetAll(buf, &varSpecLen);
543                     Buf_Destroy(buf, FALSE);
544
545                     doFree = TRUE;
546                 }
547
548                 /*
549                  * Skip whitespace to get to the operator
550                  */
551                 while (isspace((unsigned char) *condExpr))
552                     condExpr++;
553
554                 /*
555                  * Make sure the operator is a valid one. If it isn't a
556                  * known relational operator, pretend we got a
557                  * != 0 comparison.
558                  */
559                 op = condExpr;
560                 switch (*condExpr) {
561                     case '!':
562                     case '=':
563                     case '<':
564                     case '>':
565                         if (condExpr[1] == '=') {
566                             condExpr += 2;
567                         } else {
568                             condExpr += 1;
569                         }
570                         break;
571                     default:
572                         op = "!=";
573                         rhs = "0";
574
575                         goto do_compare;
576                 }
577                 while (isspace((unsigned char) *condExpr)) {
578                     condExpr++;
579                 }
580                 if (*condExpr == '\0') {
581                     Parse_Error(PARSE_WARNING,
582                                 "Missing right-hand-side of operator");
583                     goto error;
584                 }
585                 rhs = condExpr;
586 do_compare:
587                 if (*rhs == '"') {
588                     /*
589                      * Doing a string comparison. Only allow == and != for
590                      * operators.
591                      */
592                     char    *string;
593                     char    *cp, *cp2;
594                     int     qt;
595                     Buffer  buf;
596
597 do_string_compare:
598                     if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {
599                         Parse_Error(PARSE_WARNING,
600                 "String comparison operator should be either == or !=");
601                         goto error;
602                     }
603
604                     buf = Buf_Init(0);
605                     qt = *rhs == '"' ? 1 : 0;
606
607                     for (cp = &rhs[qt];
608                          ((qt && (*cp != '"')) ||
609                           (!qt && strchr(" \t)", *cp) == NULL)) &&
610                          (*cp != '\0'); cp++) {
611                         if ((*cp == '\\') && (cp[1] != '\0')) {
612                             /*
613                              * Backslash escapes things -- skip over next
614                              * character, if it exists.
615                              */
616                             cp++;
617                             Buf_AddByte(buf, (Byte)*cp);
618                         } else if (*cp == '$') {
619                             int len;
620                             Boolean freeIt;
621
622                             cp2 = Var_Parse(cp, VAR_CMD, doEval,&len, &freeIt);
623                             if (cp2 != var_Error) {
624                                 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
625                                 if (freeIt) {
626                                     free(cp2);
627                                 }
628                                 cp += len - 1;
629                             } else {
630                                 Buf_AddByte(buf, (Byte)*cp);
631                             }
632                         } else {
633                             Buf_AddByte(buf, (Byte)*cp);
634                         }
635                     }
636
637                     Buf_AddByte(buf, (Byte)0);
638
639                     string = (char *)Buf_GetAll(buf, (int *)0);
640                     Buf_Destroy(buf, FALSE);
641
642                     DEBUGF(COND, ("lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
643                            lhs, string, op));
644                     /*
645                      * Null-terminate rhs and perform the comparison.
646                      * t is set to the result.
647                      */
648                     if (*op == '=') {
649                         t = strcmp(lhs, string) ? False : True;
650                     } else {
651                         t = strcmp(lhs, string) ? True : False;
652                     }
653                     free(string);
654                     if (rhs == condExpr) {
655                         if (!qt && *cp == ')')
656                             condExpr = cp;
657                         else
658                             condExpr = cp + 1;
659                     }
660                 } else {
661                     /*
662                      * rhs is either a float or an integer. Convert both the
663                      * lhs and the rhs to a double and compare the two.
664                      */
665                     double      left, right;
666                     char        *string;
667
668                     if (*CondCvtArg(lhs, &left) != '\0')
669                         goto do_string_compare;
670                     if (*rhs == '$') {
671                         int     len;
672                         Boolean freeIt;
673
674                         string = Var_Parse(rhs, VAR_CMD, doEval,&len,&freeIt);
675                         if (string == var_Error) {
676                             right = 0.0;
677                         } else {
678                             if (*CondCvtArg(string, &right) != '\0') {
679                                 if (freeIt)
680                                     free(string);
681                                 goto do_string_compare;
682                             }
683                             if (freeIt)
684                                 free(string);
685                             if (rhs == condExpr)
686                                 condExpr += len;
687                         }
688                     } else {
689                         char *c = CondCvtArg(rhs, &right);
690                         if (c == rhs)
691                             goto do_string_compare;
692                         if (rhs == condExpr) {
693                             /*
694                              * Skip over the right-hand side
695                              */
696                             condExpr = c;
697                         }
698                     }
699
700                     DEBUGF(COND, ("left = %f, right = %f, op = %.2s\n", left,
701                            right, op));
702                     switch(op[0]) {
703                     case '!':
704                         if (op[1] != '=') {
705                             Parse_Error(PARSE_WARNING,
706                                         "Unknown operator");
707                             goto error;
708                         }
709                         t = (left != right ? True : False);
710                         break;
711                     case '=':
712                         if (op[1] != '=') {
713                             Parse_Error(PARSE_WARNING,
714                                         "Unknown operator");
715                             goto error;
716                         }
717                         t = (left == right ? True : False);
718                         break;
719                     case '<':
720                         if (op[1] == '=') {
721                             t = (left <= right ? True : False);
722                         } else {
723                             t = (left < right ? True : False);
724                         }
725                         break;
726                     case '>':
727                         if (op[1] == '=') {
728                             t = (left >= right ? True : False);
729                         } else {
730                             t = (left > right ? True : False);
731                         }
732                         break;
733                     }
734                 }
735 error:
736                 if (doFree)
737                     free(lhs);
738                 break;
739             }
740             default: {
741                 Boolean (*evalProc)(int, char *);
742                 Boolean invert = FALSE;
743                 char    *arg;
744                 int     arglen;
745
746                 if (strncmp (condExpr, "defined", 7) == 0) {
747                     /*
748                      * Use CondDoDefined to evaluate the argument and
749                      * CondGetArg to extract the argument from the 'function
750                      * call'.
751                      */
752                     evalProc = CondDoDefined;
753                     condExpr += 7;
754                     arglen = CondGetArg (&condExpr, &arg, "defined", TRUE);
755                     if (arglen == 0) {
756                         condExpr -= 7;
757                         goto use_default;
758                     }
759                 } else if (strncmp (condExpr, "make", 4) == 0) {
760                     /*
761                      * Use CondDoMake to evaluate the argument and
762                      * CondGetArg to extract the argument from the 'function
763                      * call'.
764                      */
765                     evalProc = CondDoMake;
766                     condExpr += 4;
767                     arglen = CondGetArg (&condExpr, &arg, "make", TRUE);
768                     if (arglen == 0) {
769                         condExpr -= 4;
770                         goto use_default;
771                     }
772                 } else if (strncmp (condExpr, "exists", 6) == 0) {
773                     /*
774                      * Use CondDoExists to evaluate the argument and
775                      * CondGetArg to extract the argument from the
776                      * 'function call'.
777                      */
778                     evalProc = CondDoExists;
779                     condExpr += 6;
780                     arglen = CondGetArg(&condExpr, &arg, "exists", TRUE);
781                     if (arglen == 0) {
782                         condExpr -= 6;
783                         goto use_default;
784                     }
785                 } else if (strncmp(condExpr, "empty", 5) == 0) {
786                     /*
787                      * Use Var_Parse to parse the spec in parens and return
788                      * True if the resulting string is empty.
789                      */
790                     int     length;
791                     Boolean doFree;
792                     char    *val;
793
794                     condExpr += 5;
795
796                     for (arglen = 0;
797                          condExpr[arglen] != '(' && condExpr[arglen] != '\0';
798                          arglen += 1)
799                         continue;
800
801                     if (condExpr[arglen] != '\0') {
802                         val = Var_Parse(&condExpr[arglen - 1], VAR_CMD,
803                                         doEval, &length, &doFree);
804                         if (val == var_Error) {
805                             t = Err;
806                         } else {
807                             /*
808                              * A variable is empty when it just contains
809                              * spaces... 4/15/92, christos
810                              */
811                             char *p;
812                             for (p = val; *p && isspace((unsigned char)*p); p++)
813                                 continue;
814                             t = (*p == '\0') ? True : False;
815                         }
816                         if (doFree) {
817                             free(val);
818                         }
819                         /*
820                          * Advance condExpr to beyond the closing ). Note that
821                          * we subtract one from arglen + length b/c length
822                          * is calculated from condExpr[arglen - 1].
823                          */
824                         condExpr += arglen + length - 1;
825                     } else {
826                         condExpr -= 5;
827                         goto use_default;
828                     }
829                     break;
830                 } else if (strncmp (condExpr, "target", 6) == 0) {
831                     /*
832                      * Use CondDoTarget to evaluate the argument and
833                      * CondGetArg to extract the argument from the
834                      * 'function call'.
835                      */
836                     evalProc = CondDoTarget;
837                     condExpr += 6;
838                     arglen = CondGetArg(&condExpr, &arg, "target", TRUE);
839                     if (arglen == 0) {
840                         condExpr -= 6;
841                         goto use_default;
842                     }
843                 } else {
844                     /*
845                      * The symbol is itself the argument to the default
846                      * function. We advance condExpr to the end of the symbol
847                      * by hand (the next whitespace, closing paren or
848                      * binary operator) and set to invert the evaluation
849                      * function if condInvert is TRUE.
850                      */
851                 use_default:
852                     invert = condInvert;
853                     evalProc = condDefProc;
854                     arglen = CondGetArg(&condExpr, &arg, "", FALSE);
855                 }
856
857                 /*
858                  * Evaluate the argument using the set function. If invert
859                  * is TRUE, we invert the sense of the function.
860                  */
861                 t = (!doEval || (* evalProc) (arglen, arg) ?
862                      (invert ? False : True) :
863                      (invert ? True : False));
864                 free(arg);
865                 break;
866             }
867         }
868     } else {
869         t = condPushBack;
870         condPushBack = None;
871     }
872     return (t);
873 }
874 \f
875 /*-
876  *-----------------------------------------------------------------------
877  * CondT --
878  *      Parse a single term in the expression. This consists of a terminal
879  *      symbol or Not and a terminal symbol (not including the binary
880  *      operators):
881  *          T -> defined(variable) | make(target) | exists(file) | symbol
882  *          T -> ! T | ( E )
883  *
884  * Results:
885  *      True, False or Err.
886  *
887  * Side Effects:
888  *      Tokens are consumed.
889  *
890  *-----------------------------------------------------------------------
891  */
892 static Token
893 CondT(Boolean doEval)
894 {
895     Token   t;
896
897     t = CondToken(doEval);
898
899     if (t == EndOfFile) {
900         /*
901          * If we reached the end of the expression, the expression
902          * is malformed...
903          */
904         t = Err;
905     } else if (t == LParen) {
906         /*
907          * T -> ( E )
908          */
909         t = CondE(doEval);
910         if (t != Err) {
911             if (CondToken(doEval) != RParen) {
912                 t = Err;
913             }
914         }
915     } else if (t == Not) {
916         t = CondT(doEval);
917         if (t == True) {
918             t = False;
919         } else if (t == False) {
920             t = True;
921         }
922     }
923     return (t);
924 }
925 \f
926 /*-
927  *-----------------------------------------------------------------------
928  * CondF --
929  *      Parse a conjunctive factor (nice name, wot?)
930  *          F -> T && F | T
931  *
932  * Results:
933  *      True, False or Err
934  *
935  * Side Effects:
936  *      Tokens are consumed.
937  *
938  *-----------------------------------------------------------------------
939  */
940 static Token
941 CondF(Boolean doEval)
942 {
943     Token   l, o;
944
945     l = CondT(doEval);
946     if (l != Err) {
947         o = CondToken(doEval);
948
949         if (o == And) {
950             /*
951              * F -> T && F
952              *
953              * If T is False, the whole thing will be False, but we have to
954              * parse the r.h.s. anyway (to throw it away).
955              * If T is True, the result is the r.h.s., be it an Err or no.
956              */
957             if (l == True) {
958                 l = CondF(doEval);
959             } else {
960                 (void) CondF(FALSE);
961             }
962         } else {
963             /*
964              * F -> T
965              */
966             CondPushBack (o);
967         }
968     }
969     return (l);
970 }
971 \f
972 /*-
973  *-----------------------------------------------------------------------
974  * CondE --
975  *      Main expression production.
976  *          E -> F || E | F
977  *
978  * Results:
979  *      True, False or Err.
980  *
981  * Side Effects:
982  *      Tokens are, of course, consumed.
983  *
984  *-----------------------------------------------------------------------
985  */
986 static Token
987 CondE(Boolean doEval)
988 {
989     Token   l, o;
990
991     l = CondF(doEval);
992     if (l != Err) {
993         o = CondToken(doEval);
994
995         if (o == Or) {
996             /*
997              * E -> F || E
998              *
999              * A similar thing occurs for ||, except that here we make sure
1000              * the l.h.s. is False before we bother to evaluate the r.h.s.
1001              * Once again, if l is False, the result is the r.h.s. and once
1002              * again if l is True, we parse the r.h.s. to throw it away.
1003              */
1004             if (l == False) {
1005                 l = CondE(doEval);
1006             } else {
1007                 (void) CondE(FALSE);
1008             }
1009         } else {
1010             /*
1011              * E -> F
1012              */
1013             CondPushBack (o);
1014         }
1015     }
1016     return (l);
1017 }
1018 \f
1019 /*-
1020  *-----------------------------------------------------------------------
1021  * Cond_Eval --
1022  *      Evaluate the conditional in the passed line. The line
1023  *      looks like this:
1024  *          #<cond-type> <expr>
1025  *      where <cond-type> is any of if, ifmake, ifnmake, ifdef,
1026  *      ifndef, elif, elifmake, elifnmake, elifdef, elifndef
1027  *      and <expr> consists of &&, ||, !, make(target), defined(variable)
1028  *      and parenthetical groupings thereof.
1029  *
1030  * Results:
1031  *      COND_PARSE      if should parse lines after the conditional
1032  *      COND_SKIP       if should skip lines after the conditional
1033  *      COND_INVALID    if not a valid conditional.
1034  *
1035  * Side Effects:
1036  *      None.
1037  *
1038  *-----------------------------------------------------------------------
1039  */
1040 int
1041 Cond_Eval (char *line)
1042 {
1043     struct If       *ifp;
1044     Boolean         isElse;
1045     Boolean         value = FALSE;
1046     int             level;      /* Level at which to report errors. */
1047
1048     level = PARSE_FATAL;
1049
1050     for (line++; *line == ' ' || *line == '\t'; line++) {
1051         continue;
1052     }
1053
1054     /*
1055      * Find what type of if we're dealing with. The result is left
1056      * in ifp and isElse is set TRUE if it's an elif line.
1057      */
1058     if (line[0] == 'e' && line[1] == 'l') {
1059         line += 2;
1060         isElse = TRUE;
1061     } else if (strncmp (line, "endif", 5) == 0) {
1062         /*
1063          * End of a conditional section. If skipIfLevel is non-zero, that
1064          * conditional was skipped, so lines following it should also be
1065          * skipped. Hence, we return COND_SKIP. Otherwise, the conditional
1066          * was read so succeeding lines should be parsed (think about it...)
1067          * so we return COND_PARSE, unless this endif isn't paired with
1068          * a decent if.
1069          */
1070         if (skipIfLevel != 0) {
1071             skipIfLevel -= 1;
1072             return (COND_SKIP);
1073         } else {
1074             if (condTop == MAXIF) {
1075                 Parse_Error (level, "if-less endif");
1076                 return (COND_INVALID);
1077             } else {
1078                 skipLine = FALSE;
1079                 condTop += 1;
1080                 return (COND_PARSE);
1081             }
1082         }
1083     } else {
1084         isElse = FALSE;
1085     }
1086
1087     /*
1088      * Figure out what sort of conditional it is -- what its default
1089      * function is, etc. -- by looking in the table of valid "ifs"
1090      */
1091     for (ifp = ifs; ifp->form != (char *)0; ifp++) {
1092         if (strncmp (ifp->form, line, ifp->formlen) == 0) {
1093             break;
1094         }
1095     }
1096
1097     if (ifp->form == (char *) 0) {
1098         /*
1099          * Nothing fit. If the first word on the line is actually
1100          * "else", it's a valid conditional whose value is the inverse
1101          * of the previous if we parsed.
1102          */
1103         if (isElse && (line[0] == 's') && (line[1] == 'e')) {
1104             if (condTop == MAXIF) {
1105                 Parse_Error (level, "if-less else");
1106                 return (COND_INVALID);
1107             } else if (skipIfLevel == 0) {
1108                 value = !condStack[condTop];
1109             } else {
1110                 return (COND_SKIP);
1111             }
1112         } else {
1113             /*
1114              * Not a valid conditional type. No error...
1115              */
1116             return (COND_INVALID);
1117         }
1118     } else {
1119         if (isElse) {
1120             if (condTop == MAXIF) {
1121                 Parse_Error (level, "if-less elif");
1122                 return (COND_INVALID);
1123             } else if (skipIfLevel != 0) {
1124                 /*
1125                  * If skipping this conditional, just ignore the whole thing.
1126                  * If we don't, the user might be employing a variable that's
1127                  * undefined, for which there's an enclosing ifdef that
1128                  * we're skipping...
1129                  */
1130                 return(COND_SKIP);
1131             }
1132         } else if (skipLine) {
1133             /*
1134              * Don't even try to evaluate a conditional that's not an else if
1135              * we're skipping things...
1136              */
1137             skipIfLevel += 1;
1138             return(COND_SKIP);
1139         }
1140
1141         /*
1142          * Initialize file-global variables for parsing
1143          */
1144         condDefProc = ifp->defProc;
1145         condInvert = ifp->doNot;
1146
1147         line += ifp->formlen;
1148
1149         while (*line == ' ' || *line == '\t') {
1150             line++;
1151         }
1152
1153         condExpr = line;
1154         condPushBack = None;
1155
1156         switch (CondE(TRUE)) {
1157             case True:
1158                 if (CondToken(TRUE) == EndOfFile) {
1159                     value = TRUE;
1160                     break;
1161                 }
1162                 goto err;
1163                 /*FALLTHRU*/
1164             case False:
1165                 if (CondToken(TRUE) == EndOfFile) {
1166                     value = FALSE;
1167                     break;
1168                 }
1169                 /*FALLTHRU*/
1170             case Err:
1171             err:
1172                 Parse_Error (level, "Malformed conditional (%s)",
1173                              line);
1174                 return (COND_INVALID);
1175             default:
1176                 break;
1177         }
1178     }
1179     if (!isElse) {
1180         condTop -= 1;
1181     } else if ((skipIfLevel != 0) || condStack[condTop]) {
1182         /*
1183          * If this is an else-type conditional, it should only take effect
1184          * if its corresponding if was evaluated and FALSE. If its if was
1185          * TRUE or skipped, we return COND_SKIP (and start skipping in case
1186          * we weren't already), leaving the stack unmolested so later elif's
1187          * don't screw up...
1188          */
1189         skipLine = TRUE;
1190         return (COND_SKIP);
1191     }
1192
1193     if (condTop < 0) {
1194         /*
1195          * This is the one case where we can definitely proclaim a fatal
1196          * error. If we don't, we're hosed.
1197          */
1198         Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF);
1199         return (COND_INVALID);
1200     } else {
1201         condStack[condTop] = value;
1202         skipLine = !value;
1203         return (value ? COND_PARSE : COND_SKIP);
1204     }
1205 }
1206 \f
1207 /*-
1208  *-----------------------------------------------------------------------
1209  * Cond_End --
1210  *      Make sure everything's clean at the end of a makefile.
1211  *
1212  * Results:
1213  *      None.
1214  *
1215  * Side Effects:
1216  *      Parse_Error will be called if open conditionals are around.
1217  *
1218  *-----------------------------------------------------------------------
1219  */
1220 void
1221 Cond_End(void)
1222 {
1223     if (condTop != MAXIF) {
1224         Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop,
1225                     MAXIF-condTop == 1 ? "" : "s");
1226     }
1227     condTop = MAXIF;
1228 }