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