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