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