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