cond.c revision 146177
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 146177 2005-05-13 08:53:00Z 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 "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 */ 98typedef enum { 99 And, 100 Or, 101 Not, 102 True, 103 False, 104 LParen, 105 RParen, 106 EndOfFile, 107 None, 108 Err 109} Token; 110 111typedef 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 */ 117static void CondPushBack(Token); 118static int CondGetArg(char **, char **, const char *, Boolean); 119static CondProc CondDoDefined; 120static CondProc CondDoMake; 121static CondProc CondDoExists; 122static CondProc CondDoTarget; 123static char *CondCvtArg(char *, double *); 124static Token CondToken(Boolean); 125static Token CondT(Boolean); 126static Token CondF(Boolean); 127static Token CondE(Boolean); 128 129static 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 146static Boolean condInvert; /* Invert the default function */ 147static CondProc *condDefProc; /* default function to apply */ 148static char *condExpr; /* The expression to parse */ 149static Token condPushBack = None; /* Single push-back token in parsing */ 150 151#define MAXIF 30 /* greatest depth of #if'ing */ 152 153static Boolean condStack[MAXIF]; /* Stack of conditionals's values */ 154static int condLineno[MAXIF]; /* Line numbers of the opening .if */ 155static int condTop = MAXIF; /* Top-most conditional */ 156static int skipIfLevel = 0; /* Depth of skipped conditionals */ 157static int skipIfLineno[MAXIF]; /* Line numbers of skipped .ifs */ 158Boolean 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 */ 169static void 170CondPushBack(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 */ 188static int 189CondGetArg(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 */ 282static Boolean 283CondDoDefined(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 */ 307static Boolean 308CondDoMake(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 */ 333static Boolean 334CondDoExists(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 */ 359static Boolean 360CondDoTarget(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 */ 392static char * 393CondCvtArg(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 */ 432static Token 433CondToken(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 switch (*condExpr) { 447 case '(': 448 t = LParen; 449 condExpr++; 450 break; 451 case ')': 452 t = RParen; 453 condExpr++; 454 break; 455 case '|': 456 if (condExpr[1] == '|') { 457 condExpr++; 458 } 459 condExpr++; 460 t = Or; 461 break; 462 case '&': 463 if (condExpr[1] == '&') { 464 condExpr++; 465 } 466 condExpr++; 467 t = And; 468 break; 469 case '!': 470 t = Not; 471 condExpr++; 472 break; 473 case '\n': 474 case '\0': 475 t = EndOfFile; 476 break; 477 case '$': { 478 char *lhs; 479 const char *op; 480 char *rhs; 481 char zero[] = "0"; 482 size_t varSpecLen = 0; 483 Boolean doFree; 484 485 /* 486 * Parse the variable spec and skip over it, saving its 487 * value in lhs. 488 */ 489 t = Err; 490 lhs = Var_Parse(condExpr, VAR_CMD, doEval, 491 &varSpecLen, &doFree); 492 if (lhs == var_Error) { 493 /* 494 * Even if !doEval, we still report syntax 495 * errors, which is what getting var_Error 496 * back with !doEval means. 497 */ 498 return (Err); 499 } 500 condExpr += varSpecLen; 501 502 if (!isspace((unsigned char)*condExpr) && 503 strchr("!=><", *condExpr) == NULL) { 504 Buffer *buf; 505 506 buf = Buf_Init(0); 507 508 Buf_Append(buf, lhs); 509 510 if (doFree) 511 free(lhs); 512 513 for (;*condExpr && 514 !isspace((unsigned char)*condExpr); 515 condExpr++) 516 Buf_AddByte(buf, (Byte)*condExpr); 517 518 Buf_AddByte(buf, (Byte)'\0'); 519 lhs = (char *)Buf_GetAll(buf, &varSpecLen); 520 Buf_Destroy(buf, FALSE); 521 522 doFree = TRUE; 523 } 524 525 /* 526 * Skip whitespace to get to the operator 527 */ 528 while (isspace((unsigned char)*condExpr)) 529 condExpr++; 530 531 /* 532 * Make sure the operator is a valid one. If it isn't a 533 * known relational operator, pretend we got a 534 * != 0 comparison. 535 */ 536 op = condExpr; 537 switch (*condExpr) { 538 case '!': 539 case '=': 540 case '<': 541 case '>': 542 if (condExpr[1] == '=') { 543 condExpr += 2; 544 } else { 545 condExpr += 1; 546 } 547 while (isspace((unsigned char)*condExpr)) { 548 condExpr++; 549 } 550 if (*condExpr == '\0') { 551 Parse_Error(PARSE_WARNING, 552 "Missing right-hand-side of operator"); 553 goto error; 554 } 555 rhs = condExpr; 556 break; 557 558 default: 559 op = "!="; 560 rhs = zero; 561 break; 562 } 563 if (*rhs == '"') { 564 /* 565 * Doing a string comparison. Only allow == and 566 * != for * operators. 567 */ 568 char *string; 569 char *cp, *cp2; 570 int qt; 571 Buffer *buf; 572 573 do_string_compare: 574 if (((*op != '!') && (*op != '=')) || 575 (op[1] != '=')) { 576 Parse_Error(PARSE_WARNING, 577 "String comparison operator should " 578 "be either == or !="); 579 goto error; 580 } 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 character, * if it exists. 593 */ 594 cp++; 595 Buf_AddByte(buf, (Byte)*cp); 596 597 } else if (*cp == '$') { 598 size_t len = 0; 599 Boolean freeIt; 600 601 cp2 = Var_Parse(cp, VAR_CMD, 602 doEval, &len, &freeIt); 603 if (cp2 != var_Error) { 604 Buf_Append(buf, cp2); 605 if (freeIt) { 606 free(cp2); 607 } 608 cp += len - 1; 609 } else { 610 Buf_AddByte(buf, 611 (Byte)*cp); 612 } 613 } else { 614 Buf_AddByte(buf, (Byte)*cp); 615 } 616 } 617 618 string = Buf_Peel(buf); 619 620 DEBUGF(COND, ("lhs = \"%s\", rhs = \"%s\", " 621 "op = %.2s\n", lhs, string, op)); 622 /* 623 * Null-terminate rhs and perform the 624 * comparison. t is set to the result. 625 */ 626 if (*op == '=') { 627 t = strcmp(lhs, string) ? False : True; 628 } else { 629 t = strcmp(lhs, string) ? True : False; 630 } 631 free(string); 632 if (rhs == condExpr) { 633 if (!qt && *cp == ')') 634 condExpr = cp; 635 else 636 condExpr = cp + 1; 637 } 638 } else { 639 /* 640 * rhs is either a float or an integer. 641 * Convert both the lhs and the rhs to a 642 * double and compare the two. 643 */ 644 double left, right; 645 char *string; 646 647 if (*CondCvtArg(lhs, &left) != '\0') 648 goto do_string_compare; 649 if (*rhs == '$') { 650 size_t len = 0; 651 Boolean freeIt; 652 653 string = Var_Parse(rhs, VAR_CMD, doEval, 654 &len, &freeIt); 655 if (string == var_Error) { 656 right = 0.0; 657 } else { 658 if (*CondCvtArg(string, 659 &right) != '\0') { 660 if (freeIt) 661 free(string); 662 goto do_string_compare; 663 } 664 if (freeIt) 665 free(string); 666 if (rhs == condExpr) 667 condExpr += len; 668 } 669 } else { 670 char *c = CondCvtArg(rhs, &right); 671 672 if (c == rhs) 673 goto do_string_compare; 674 if (rhs == condExpr) { 675 /* 676 * Skip over the right-hand 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 from 735 * 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 746 } else if (strncmp(condExpr, "make", 4) == 0) { 747 /* 748 * Use CondDoMake to evaluate the argument and 749 * CondGetArg to extract the argument from the 750 * 'function call'. 751 */ 752 evalProc = CondDoMake; 753 condExpr += 4; 754 arglen = CondGetArg(&condExpr, &arg, 755 "make", TRUE); 756 if (arglen == 0) { 757 condExpr -= 4; 758 goto use_default; 759 } 760 761 } else if (strncmp(condExpr, "exists", 6) == 0) { 762 /* 763 * Use CondDoExists to evaluate the argument and 764 * CondGetArg to extract the argument from the 765 * 'function call'. 766 */ 767 evalProc = CondDoExists; 768 condExpr += 6; 769 arglen = CondGetArg(&condExpr, &arg, 770 "exists", TRUE); 771 if (arglen == 0) { 772 condExpr -= 6; 773 goto use_default; 774 } 775 776 } else if (strncmp(condExpr, "empty", 5) == 0) { 777 /* 778 * Use Var_Parse to parse the spec in parens and 779 * return True if the resulting string is empty. 780 */ 781 size_t length; 782 Boolean doFree; 783 char *val; 784 785 condExpr += 5; 786 787 for (arglen = 0; 788 condExpr[arglen] != '(' && 789 condExpr[arglen] != '\0'; arglen += 1) 790 continue; 791 792 if (condExpr[arglen] != '\0') { 793 length = 0; 794 val = Var_Parse(&condExpr[arglen - 1], 795 VAR_CMD, FALSE, &length, &doFree); 796 if (val == var_Error) { 797 t = Err; 798 } else { 799 /* 800 * A variable is empty when it 801 * just contains spaces... 802 * 4/15/92, christos 803 */ 804 char *p; 805 806 for (p = val; 807 *p && 808 isspace((unsigned char)*p); 809 p++) 810 continue; 811 t = (*p == '\0') ? True : False; 812 } 813 if (doFree) { 814 free(val); 815 } 816 /* 817 * Advance condExpr to beyond the 818 * closing ). Note that we subtract 819 * one from arglen + length b/c length 820 * is calculated from 821 * condExpr[arglen - 1]. 822 */ 823 condExpr += arglen + length - 1; 824 } else { 825 condExpr -= 5; 826 goto use_default; 827 } 828 break; 829 830 } else if (strncmp(condExpr, "target", 6) == 0) { 831 /* 832 * Use CondDoTarget to evaluate the argument and 833 * CondGetArg to extract the argument from the 834 * 'function call'. 835 */ 836 evalProc = CondDoTarget; 837 condExpr += 6; 838 arglen = CondGetArg(&condExpr, &arg, 839 "target", TRUE); 840 if (arglen == 0) { 841 condExpr -= 6; 842 goto use_default; 843 } 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 operator) 851 * 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 function. 863 */ 864 t = (!doEval || (* evalProc) (arglen, arg) ? 865 (invert ? False : True) : 866 (invert ? True : False)); 867 free(arg); 868 break; 869 } 870 } 871 return (t); 872} 873 874/** 875 * CondT 876 * Parse a single term in the expression. This consists of a terminal 877 * symbol or Not and a terminal symbol (not including the binary 878 * operators): 879 * T -> defined(variable) | make(target) | exists(file) | symbol 880 * T -> ! T | ( E ) 881 * 882 * Results: 883 * True, False or Err. 884 * 885 * Side Effects: 886 * Tokens are consumed. 887 */ 888static Token 889CondT(Boolean doEval) 890{ 891 Token t; 892 893 t = CondToken(doEval); 894 if (t == EndOfFile) { 895 /* 896 * If we reached the end of the expression, the expression 897 * is malformed... 898 */ 899 t = Err; 900 } else if (t == LParen) { 901 /* 902 * T -> ( E ) 903 */ 904 t = CondE(doEval); 905 if (t != Err) { 906 if (CondToken(doEval) != RParen) { 907 t = Err; 908 } 909 } 910 } else if (t == Not) { 911 t = CondT(doEval); 912 if (t == True) { 913 t = False; 914 } else if (t == False) { 915 t = True; 916 } 917 } 918 return (t); 919} 920 921/** 922 * CondF -- 923 * Parse a conjunctive factor (nice name, wot?) 924 * F -> T && F | T 925 * 926 * Results: 927 * True, False or Err 928 * 929 * Side Effects: 930 * Tokens are consumed. 931 */ 932static Token 933CondF(Boolean doEval) 934{ 935 Token l, o; 936 937 l = CondT(doEval); 938 if (l != Err) { 939 o = CondToken(doEval); 940 941 if (o == And) { 942 /* 943 * F -> T && F 944 * 945 * If T is False, the whole thing will be False, but 946 * we have to parse the r.h.s. anyway (to throw it 947 * away). If T is True, the result is the r.h.s., 948 * be it an Err or no. 949 */ 950 if (l == True) { 951 l = CondF(doEval); 952 } else { 953 CondF(FALSE); 954 } 955 } else { 956 /* 957 * F -> T 958 */ 959 CondPushBack(o); 960 } 961 } 962 return (l); 963} 964 965/** 966 * CondE -- 967 * Main expression production. 968 * E -> F || E | F 969 * 970 * Results: 971 * True, False or Err. 972 * 973 * Side Effects: 974 * Tokens are, of course, consumed. 975 */ 976static Token 977CondE(Boolean doEval) 978{ 979 Token l, o; 980 981 l = CondF(doEval); 982 if (l != Err) { 983 o = CondToken(doEval); 984 985 if (o == Or) { 986 /* 987 * E -> F || E 988 * 989 * A similar thing occurs for ||, except that here we 990 * make sure the l.h.s. is False before we bother to 991 * evaluate the r.h.s. Once again, if l is False, the 992 * result is the r.h.s. and once again if l is True, 993 * we parse the r.h.s. to throw it away. 994 */ 995 if (l == False) { 996 l = CondE(doEval); 997 } else { 998 CondE(FALSE); 999 } 1000 } else { 1001 /* 1002 * E -> F 1003 */ 1004 CondPushBack(o); 1005 } 1006 } 1007 return (l); 1008} 1009 1010/** 1011 * Cond_If 1012 * Handle .if<X> and .elif<X> directives. 1013 * This function is called even when we're skipping. 1014 */ 1015void 1016Cond_If(char *line, int code, int lineno) 1017{ 1018 const struct If *ifp; 1019 Boolean value; 1020 1021 ifp = &ifs[code]; 1022 1023 if (ifp->isElse) { 1024 if (condTop == MAXIF) { 1025 Parse_Error(PARSE_FATAL, "if-less elif"); 1026 return; 1027 } 1028 if (skipIfLevel != 0) { 1029 /* 1030 * If skipping this conditional, just ignore 1031 * the whole thing. If we don't, the user 1032 * might be employing a variable that's 1033 * undefined, for which there's an enclosing 1034 * ifdef that we're skipping... 1035 */ 1036 skipIfLineno[skipIfLevel - 1] = lineno; 1037 return; 1038 } 1039 1040 } else if (skipLine) { 1041 /* 1042 * Don't even try to evaluate a conditional that's 1043 * not an else if we're skipping things... 1044 */ 1045 skipIfLineno[skipIfLevel] = lineno; 1046 skipIfLevel += 1; 1047 return; 1048 } 1049 1050 /* 1051 * Initialize file-global variables for parsing 1052 */ 1053 condDefProc = ifp->defProc; 1054 condInvert = ifp->doNot; 1055 1056 while (*line == ' ' || *line == '\t') { 1057 line++; 1058 } 1059 1060 condExpr = line; 1061 condPushBack = None; 1062 1063 switch (CondE(TRUE)) { 1064 case True: 1065 if (CondToken(TRUE) != EndOfFile) 1066 goto err; 1067 value = TRUE; 1068 break; 1069 1070 case False: 1071 if (CondToken(TRUE) != EndOfFile) 1072 goto err; 1073 value = FALSE; 1074 break; 1075 1076 case Err: 1077 err: Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line); 1078 return; 1079 1080 default: 1081 abort(); 1082 } 1083 1084 if (!ifp->isElse) { 1085 /* push this value */ 1086 condTop -= 1; 1087 1088 } else if (skipIfLevel != 0 || condStack[condTop]) { 1089 /* 1090 * If this is an else-type conditional, it should only take 1091 * effect if its corresponding if was evaluated and FALSE. 1092 * If its if was TRUE or skipped, we return COND_SKIP (and 1093 * start skipping in case we weren't already), leaving the 1094 * stack unmolested so later elif's don't screw up... 1095 */ 1096 skipLine = TRUE; 1097 return; 1098 } 1099 1100 if (condTop < 0) { 1101 /* 1102 * This is the one case where we can definitely proclaim a fatal 1103 * error. If we don't, we're hosed. 1104 */ 1105 Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.",MAXIF); 1106 return; 1107 } 1108 1109 /* push */ 1110 condStack[condTop] = value; 1111 condLineno[condTop] = lineno; 1112 skipLine = !value; 1113} 1114 1115/** 1116 * Cond_Else 1117 * Handle .else statement. 1118 */ 1119void 1120Cond_Else(char *line __unused, int code __unused, int lineno __unused) 1121{ 1122 1123 while (isspace((u_char)*line)) 1124 line++; 1125 1126 if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) { 1127 Parse_Error(PARSE_WARNING, "junk after .else ignored '%s'", 1128 line); 1129 } 1130 1131 if (condTop == MAXIF) { 1132 Parse_Error(PARSE_FATAL, "if-less else"); 1133 return; 1134 } 1135 if (skipIfLevel != 0) 1136 return; 1137 1138 if (skipIfLevel != 0 || condStack[condTop]) { 1139 /* 1140 * An else should only take effect if its corresponding if was 1141 * evaluated and FALSE. 1142 * If its if was TRUE or skipped, we return COND_SKIP (and 1143 * start skipping in case we weren't already), leaving the 1144 * stack unmolested so later elif's don't screw up... 1145 * XXX How does this work with two .else's? 1146 */ 1147 skipLine = TRUE; 1148 return; 1149 } 1150 1151 /* inverse value */ 1152 condStack[condTop] = !condStack[condTop]; 1153 skipLine = !condStack[condTop]; 1154} 1155 1156/** 1157 * Cond_Endif 1158 * Handle .endif statement. 1159 */ 1160void 1161Cond_Endif(char *line __unused, int code __unused, int lineno __unused) 1162{ 1163 1164 while (isspace((u_char)*line)) 1165 line++; 1166 1167 if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) { 1168 Parse_Error(PARSE_WARNING, "junk after .endif ignored '%s'", 1169 line); 1170 } 1171 1172 /* 1173 * End of a conditional section. If skipIfLevel is non-zero, 1174 * that conditional was skipped, so lines following it should 1175 * also be skipped. Hence, we return COND_SKIP. Otherwise, 1176 * the conditional was read so succeeding lines should be 1177 * parsed (think about it...) so we return COND_PARSE, unless 1178 * this endif isn't paired with a decent if. 1179 */ 1180 if (skipIfLevel != 0) { 1181 skipIfLevel -= 1; 1182 return; 1183 } 1184 1185 if (condTop == MAXIF) { 1186 Parse_Error(PARSE_FATAL, "if-less endif"); 1187 return; 1188 } 1189 1190 /* pop */ 1191 skipLine = FALSE; 1192 condTop += 1; 1193} 1194 1195/** 1196 * Cond_End 1197 * Make sure everything's clean at the end of a makefile. 1198 * 1199 * Side Effects: 1200 * Parse_Error will be called if open conditionals are around. 1201 */ 1202void 1203Cond_End(void) 1204{ 1205 int level; 1206 1207 if (condTop != MAXIF) { 1208 Parse_Error(PARSE_FATAL, "%d open conditional%s:", 1209 MAXIF - condTop + skipIfLevel, 1210 MAXIF - condTop + skipIfLevel== 1 ? "" : "s"); 1211 1212 for (level = skipIfLevel; level > 0; level--) 1213 Parse_Error(PARSE_FATAL, "\t%*sat line %d (skipped)", 1214 MAXIF - condTop + level + 1, "", 1215 skipIfLineno[level - 1]); 1216 for (level = condTop; level < MAXIF; level++) 1217 Parse_Error(PARSE_FATAL, "\t%*sat line %d " 1218 "(evaluated to %s)", MAXIF - level + skipIfLevel, 1219 "", condLineno[level], 1220 condStack[level] ? "true" : "false"); 1221 } 1222 condTop = MAXIF; 1223} 1224