cond.c revision 146154
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 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: head/usr.bin/make/cond.c 146154 2005-05-12 15:41:02Z harti $"); 44 45/* 46 * Functions to handle conditionals in a makefile. 47 * 48 * Interface: 49 * Cond_Eval Evaluate the conditional in the passed line. 50 */ 51 52#include <ctype.h> 53#include <string.h> 54#include <stdlib.h> 55 56#include "buf.h" 57#include "cond.h" 58#include "dir.h" 59#include "globals.h" 60#include "GNode.h" 61#include "make.h" 62#include "parse.h" 63#include "sprite.h" 64#include "str.h" 65#include "targ.h" 66#include "util.h" 67#include "var.h" 68 69/* 70 * The parsing of conditional expressions is based on this grammar: 71 * E -> F || E 72 * E -> F 73 * F -> T && F 74 * F -> T 75 * T -> defined(variable) 76 * T -> make(target) 77 * T -> exists(file) 78 * T -> empty(varspec) 79 * T -> target(name) 80 * T -> symbol 81 * T -> $(varspec) op value 82 * T -> $(varspec) == "string" 83 * T -> $(varspec) != "string" 84 * T -> ( E ) 85 * T -> ! T 86 * op -> == | != | > | < | >= | <= 87 * 88 * 'symbol' is some other symbol to which the default function (condDefProc) 89 * is applied. 90 * 91 * Tokens are scanned from the 'condExpr' string. The scanner (CondToken) 92 * will return And for '&' and '&&', Or for '|' and '||', Not for '!', 93 * LParen for '(', RParen for ')' and will evaluate the other terminal 94 * symbols, using either the default function or the function given in the 95 * terminal, and return the result as either True or False. 96 * 97 * All Non-Terminal functions (CondE, CondF and CondT) return Err on error. 98 */ 99typedef enum { 100 And, 101 Or, 102 Not, 103 True, 104 False, 105 LParen, 106 RParen, 107 EndOfFile, 108 None, 109 Err 110} Token; 111 112typedef Boolean CondProc(int, char *); 113 114/*- 115 * Structures to handle elegantly the different forms of #if's. The 116 * last two fields are stored in condInvert and condDefProc, respectively. 117 */ 118static void CondPushBack(Token); 119static int CondGetArg(char **, char **, const char *, Boolean); 120static CondProc CondDoDefined; 121static CondProc CondDoMake; 122static CondProc CondDoExists; 123static CondProc CondDoTarget; 124static char *CondCvtArg(char *, double *); 125static Token CondToken(Boolean); 126static Token CondT(Boolean); 127static Token CondF(Boolean); 128static Token CondE(Boolean); 129 130static const struct If { 131 Boolean doNot; /* TRUE if default function should be negated */ 132 CondProc *defProc; /* Default function to apply */ 133 Boolean isElse; /* actually el<XXX> */ 134} ifs[] = { 135 [COND_IF] = { FALSE, CondDoDefined, FALSE }, 136 [COND_IFDEF] = { FALSE, CondDoDefined, FALSE }, 137 [COND_IFNDEF] = { TRUE, CondDoDefined, FALSE }, 138 [COND_IFMAKE] = { FALSE, CondDoMake, FALSE }, 139 [COND_IFNMAKE] = { TRUE, CondDoMake, FALSE }, 140 [COND_ELIF] = { FALSE, CondDoDefined, TRUE }, 141 [COND_ELIFDEF] = { FALSE, CondDoDefined, TRUE }, 142 [COND_ELIFNDEF] = { TRUE, CondDoDefined, TRUE }, 143 [COND_ELIFMAKE] = { FALSE, CondDoMake, TRUE }, 144 [COND_ELIFNMAKE] = { TRUE, CondDoMake, TRUE }, 145}; 146 147static Boolean condInvert; /* Invert the default function */ 148static CondProc *condDefProc; /* default function to apply */ 149static char *condExpr; /* The expression to parse */ 150static Token condPushBack = None; /* Single push-back token in parsing */ 151 152#define MAXIF 30 /* greatest depth of #if'ing */ 153 154static Boolean condStack[MAXIF]; /* Stack of conditionals's values */ 155static int condLineno[MAXIF]; /* Line numbers of the opening .if */ 156static int condTop = MAXIF; /* Top-most conditional */ 157static int skipIfLevel = 0; /* Depth of skipped conditionals */ 158static int skipIfLineno[MAXIF]; /* Line numbers of skipped .ifs */ 159Boolean skipLine = FALSE; /* Whether the parse module is skipping 160 * lines */ 161 162/** 163 * CondPushBack 164 * Push back the most recent token read. We only need one level of 165 * this, so the thing is just stored in 'condPushback'. 166 * 167 * Side Effects: 168 * condPushback is overwritten. 169 */ 170static void 171CondPushBack(Token t) 172{ 173 174 condPushBack = t; 175} 176 177/** 178 * CondGetArg 179 * Find the argument of a built-in function. parens is set to TRUE 180 * if the arguments are bounded by parens. 181 * 182 * Results: 183 * The length of the argument and the address of the argument. 184 * 185 * Side Effects: 186 * The pointer is set to point to the closing parenthesis of the 187 * function call. 188 */ 189static int 190CondGetArg(char **linePtr, char **argPtr, const char *func, Boolean parens) 191{ 192 char *cp; 193 size_t argLen; 194 Buffer *buf; 195 196 cp = *linePtr; 197 if (parens) { 198 while (*cp != '(' && *cp != '\0') { 199 cp++; 200 } 201 if (*cp == '(') { 202 cp++; 203 } 204 } 205 206 if (*cp == '\0') { 207 /* 208 * No arguments whatsoever. Because 'make' and 'defined' 209 * aren't really "reserved words", we don't print a message. 210 * I think this is better than hitting the user with a warning 211 * message every time s/he uses the word 'make' or 'defined' 212 * at the beginning of a symbol... 213 */ 214 *argPtr = cp; 215 return (0); 216 } 217 218 while (*cp == ' ' || *cp == '\t') { 219 cp++; 220 } 221 222 /* 223 * Create a buffer for the argument and start it out at 16 characters 224 * long. Why 16? Why not? 225 */ 226 buf = Buf_Init(16); 227 228 while ((strchr(" \t)&|", *cp) == NULL) && (*cp != '\0')) { 229 if (*cp == '$') { 230 /* 231 * Parse the variable spec and install it as part of 232 * the argument if it's valid. We tell Var_Parse to 233 * complain on an undefined variable, so we don't do 234 * it too. Nor do we return an error, though perhaps 235 * we should... 236 */ 237 char *cp2; 238 size_t len = 0; 239 Boolean doFree; 240 241 cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree); 242 243 Buf_Append(buf, cp2); 244 if (doFree) { 245 free(cp2); 246 } 247 cp += len; 248 } else { 249 Buf_AddByte(buf, (Byte)*cp); 250 cp++; 251 } 252 } 253 254 Buf_AddByte(buf, (Byte)'\0'); 255 *argPtr = (char *)Buf_GetAll(buf, &argLen); 256 Buf_Destroy(buf, FALSE); 257 258 while (*cp == ' ' || *cp == '\t') { 259 cp++; 260 } 261 if (parens && *cp != ')') { 262 Parse_Error(PARSE_WARNING, 263 "Missing closing parenthesis for %s()", func); 264 return (0); 265 } else if (parens) { 266 /* 267 * Advance pointer past close parenthesis. 268 */ 269 cp++; 270 } 271 272 *linePtr = cp; 273 return (argLen); 274} 275 276/** 277 * CondDoDefined 278 * Handle the 'defined' function for conditionals. 279 * 280 * Results: 281 * TRUE if the given variable is defined. 282 */ 283static Boolean 284CondDoDefined(int argLen, char *arg) 285{ 286 char savec = arg[argLen]; 287 char *p1; 288 Boolean result; 289 290 arg[argLen] = '\0'; 291 if (Var_Value(arg, VAR_CMD, &p1) != NULL) { 292 result = TRUE; 293 } else { 294 result = FALSE; 295 } 296 free(p1); 297 arg[argLen] = savec; 298 return (result); 299} 300 301/** 302 * CondDoMake 303 * Handle the 'make' function for conditionals. 304 * 305 * Results: 306 * TRUE if the given target is being made. 307 */ 308static Boolean 309CondDoMake(int argLen, char *arg) 310{ 311 char savec = arg[argLen]; 312 Boolean result; 313 const LstNode *ln; 314 315 arg[argLen] = '\0'; 316 result = FALSE; 317 LST_FOREACH(ln, &create) { 318 if (Str_Match(Lst_Datum(ln), arg)) { 319 result = TRUE; 320 break; 321 } 322 } 323 arg[argLen] = savec; 324 return (result); 325} 326 327/** 328 * CondDoExists 329 * See if the given file exists. 330 * 331 * Results: 332 * TRUE if the file exists and FALSE if it does not. 333 */ 334static Boolean 335CondDoExists(int argLen, char *arg) 336{ 337 char savec = arg[argLen]; 338 Boolean result; 339 char *path; 340 341 arg[argLen] = '\0'; 342 path = Path_FindFile(arg, &dirSearchPath); 343 if (path != NULL) { 344 result = TRUE; 345 free(path); 346 } else { 347 result = FALSE; 348 } 349 arg[argLen] = savec; 350 return (result); 351} 352 353/** 354 * CondDoTarget 355 * See if the given node exists and is an actual target. 356 * 357 * Results: 358 * TRUE if the node exists as a target and FALSE if it does not. 359 */ 360static Boolean 361CondDoTarget(int argLen, char *arg) 362{ 363 char savec = arg[argLen]; 364 Boolean result; 365 GNode *gn; 366 367 arg[argLen] = '\0'; 368 gn = Targ_FindNode(arg, TARG_NOCREATE); 369 if ((gn != NULL) && !OP_NOP(gn->type)) { 370 result = TRUE; 371 } else { 372 result = FALSE; 373 } 374 arg[argLen] = savec; 375 return (result); 376} 377 378/** 379 * CondCvtArg 380 * Convert the given number into a double. If the number begins 381 * with 0x, it is interpreted as a hexadecimal integer 382 * and converted to a double from there. All other strings just have 383 * strtod called on them. 384 * 385 * Results: 386 * Sets 'value' to double value of string. 387 * Returns address of the first character after the last valid 388 * character of the converted number. 389 * 390 * Side Effects: 391 * Can change 'value' even if string is not a valid number. 392 */ 393static char * 394CondCvtArg(char *str, double *value) 395{ 396 397 if ((*str == '0') && (str[1] == 'x')) { 398 long i; 399 400 for (str += 2, i = 0; ; str++) { 401 int x; 402 403 if (isdigit((unsigned char)*str)) 404 x = *str - '0'; 405 else if (isxdigit((unsigned char)*str)) 406 x = 10 + *str - 407 isupper((unsigned char)*str) ? 'A' : 'a'; 408 else { 409 *value = (double)i; 410 return (str); 411 } 412 i = (i << 4) + x; 413 } 414 415 } else { 416 char *eptr; 417 418 *value = strtod(str, &eptr); 419 return (eptr); 420 } 421} 422 423/** 424 * CondToken 425 * Return the next token from the input. 426 * 427 * Results: 428 * A Token for the next lexical token in the stream. 429 * 430 * Side Effects: 431 * condPushback will be set back to None if it is used. 432 */ 433static Token 434CondToken(Boolean doEval) 435{ 436 Token t; 437 438 if (condPushBack != None) { 439 t = condPushBack; 440 condPushBack = None; 441 return (t); 442 } 443 444 while (*condExpr == ' ' || *condExpr == '\t') { 445 condExpr++; 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 its 488 * 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 a 534 * known relational operator, pretend we got a 535 * != 0 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 559 default: 560 op = "!="; 561 rhs = zero; 562 break; 563 } 564 if (*rhs == '"') { 565 /* 566 * Doing a string comparison. Only allow == and 567 * != 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 583 buf = Buf_Init(0); 584 qt = *rhs == '"' ? 1 : 0; 585 586 for (cp = &rhs[qt]; 587 ((qt && (*cp != '"')) || 588 (!qt && strchr(" \t)", *cp) == NULL)) && 589 (*cp != '\0'); cp++) { 590 if ((*cp == '\\') && (cp[1] != '\0')) { 591 /* 592 * Backslash escapes things -- 593 * skip over next character, * if it exists. 594 */ 595 cp++; 596 Buf_AddByte(buf, (Byte)*cp); 597 598 } else if (*cp == '$') { 599 size_t len = 0; 600 Boolean freeIt; 601 602 cp2 = Var_Parse(cp, VAR_CMD, 603 doEval, &len, &freeIt); 604 if (cp2 != var_Error) { 605 Buf_Append(buf, cp2); 606 if (freeIt) { 607 free(cp2); 608 } 609 cp += len - 1; 610 } else { 611 Buf_AddByte(buf, 612 (Byte)*cp); 613 } 614 } else { 615 Buf_AddByte(buf, (Byte)*cp); 616 } 617 } 618 619 string = Buf_Peel(buf); 620 621 DEBUGF(COND, ("lhs = \"%s\", rhs = \"%s\", " 622 "op = %.2s\n", lhs, string, op)); 623 /* 624 * Null-terminate rhs and perform the 625 * comparison. t is set to the result. 626 */ 627 if (*op == '=') { 628 t = strcmp(lhs, string) ? False : True; 629 } else { 630 t = strcmp(lhs, string) ? True : False; 631 } 632 free(string); 633 if (rhs == condExpr) { 634 if (!qt && *cp == ')') 635 condExpr = cp; 636 else 637 condExpr = cp + 1; 638 } 639 } else { 640 /* 641 * rhs is either a float or an integer. 642 * Convert both the lhs and the rhs to a 643 * double and compare the two. 644 */ 645 double left, right; 646 char *string; 647 648 if (*CondCvtArg(lhs, &left) != '\0') 649 goto do_string_compare; 650 if (*rhs == '$') { 651 size_t len = 0; 652 Boolean freeIt; 653 654 string = Var_Parse(rhs, VAR_CMD, doEval, 655 &len, &freeIt); 656 if (string == var_Error) { 657 right = 0.0; 658 } else { 659 if (*CondCvtArg(string, 660 &right) != '\0') { 661 if (freeIt) 662 free(string); 663 goto do_string_compare; 664 } 665 if (freeIt) 666 free(string); 667 if (rhs == condExpr) 668 condExpr += len; 669 } 670 } else { 671 char *c = CondCvtArg(rhs, &right); 672 673 if (c == rhs) 674 goto do_string_compare; 675 if (rhs == condExpr) { 676 /* 677 * Skip over the right-hand side 678 */ 679 condExpr = c; 680 } 681 } 682 683 DEBUGF(COND, ("left = %f, right = %f, " 684 "op = %.2s\n", left, right, op)); 685 switch (op[0]) { 686 case '!': 687 if (op[1] != '=') { 688 Parse_Error(PARSE_WARNING, 689 "Unknown operator"); 690 goto error; 691 } 692 t = (left != right ? True : False); 693 break; 694 case '=': 695 if (op[1] != '=') { 696 Parse_Error(PARSE_WARNING, 697 "Unknown operator"); 698 goto error; 699 } 700 t = (left == right ? True : False); 701 break; 702 case '<': 703 if (op[1] == '=') { 704 t = (left <= right?True:False); 705 } else { 706 t = (left < right?True:False); 707 } 708 break; 709 case '>': 710 if (op[1] == '=') { 711 t = (left >= right?True:False); 712 } else { 713 t = (left > right?True:False); 714 } 715 break; 716 default: 717 break; 718 } 719 } 720 error: 721 if (doFree) 722 free(lhs); 723 break; 724 } 725 726 default: { 727 CondProc *evalProc; 728 Boolean invert = FALSE; 729 char *arg; 730 int arglen; 731 732 if (strncmp(condExpr, "defined", 7) == 0) { 733 /* 734 * Use CondDoDefined to evaluate the argument 735 * and CondGetArg to extract the argument from 736 * the 'function call'. 737 */ 738 evalProc = CondDoDefined; 739 condExpr += 7; 740 arglen = CondGetArg(&condExpr, &arg, 741 "defined", TRUE); 742 if (arglen == 0) { 743 condExpr -= 7; 744 goto use_default; 745 } 746 747 } else if (strncmp(condExpr, "make", 4) == 0) { 748 /* 749 * Use CondDoMake to evaluate the argument and 750 * CondGetArg to extract the argument from the 751 * 'function call'. 752 */ 753 evalProc = CondDoMake; 754 condExpr += 4; 755 arglen = CondGetArg(&condExpr, &arg, 756 "make", TRUE); 757 if (arglen == 0) { 758 condExpr -= 4; 759 goto use_default; 760 } 761 762 } else if (strncmp(condExpr, "exists", 6) == 0) { 763 /* 764 * Use CondDoExists to evaluate the argument and 765 * CondGetArg to extract the argument from the 766 * '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 777 } else if (strncmp(condExpr, "empty", 5) == 0) { 778 /* 779 * Use Var_Parse to parse the spec in parens and 780 * return True if the resulting string is 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 it 802 * 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 length 821 * 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 and 834 * CondGetArg to extract the argument from the 835 * '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 846 } else { 847 /* 848 * The symbol is itself the argument to the 849 * default function. We advance condExpr to 850 * the end of the symbol by hand (the next 851 * whitespace, closing paren or binary operator) 852 * and set to invert the evaluation 853 * function if condInvert is TRUE. 854 */ 855 use_default: 856 invert = condInvert; 857 evalProc = condDefProc; 858 arglen = CondGetArg(&condExpr, &arg, "", FALSE); 859 } 860 861 /* 862 * Evaluate the argument using the set function. If 863 * invert is TRUE, we invert the sense of the 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 */ 889static Token 890CondT(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 */ 933static Token 934CondF(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 */ 977static Token 978CondE(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 */ 1016void 1017Cond_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 */ 1120void 1121Cond_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 */ 1161void 1162Cond_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 */ 1203void 1204Cond_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} 1225