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