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