1/* 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 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. --- 25 unchanged lines hidden (view full) --- 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 * @(#)parse.c 8.3 (Berkeley) 3/19/94 39 */ 40 41#include <sys/cdefs.h> |
42__FBSDID("$FreeBSD: head/usr.bin/make/parse.c 138232 2004-11-30 17:46:29Z harti $"); |
43 44/*- 45 * parse.c -- 46 * Functions to parse a makefile. 47 * 48 * One function, Parse_Init, must be called before any functions 49 * in this module are used. After that, the function Parse_File is the 50 * main entry point and controls most of the other functions in this --- 189 unchanged lines hidden (view full) --- 240 * Results: 241 * The index of the keyword, or -1 if it isn't there. 242 * 243 * Side Effects: 244 * None 245 *---------------------------------------------------------------------- 246 */ 247static int |
248ParseFindKeyword(char *str) |
249{ 250 int start, 251 end, 252 cur; 253 int diff; 254 255 start = 0; |
256 end = (sizeof(parseKeywords) / sizeof(parseKeywords[0])) - 1; |
257 258 do { 259 cur = start + ((end - start) / 2); |
260 diff = strcmp(str, parseKeywords[cur].name); |
261 262 if (diff == 0) { 263 return (cur); 264 } else if (diff < 0) { 265 end = cur - 1; 266 } else { 267 start = cur + 1; 268 } --- 15 unchanged lines hidden (view full) --- 284 */ 285/* VARARGS */ 286void 287Parse_Error(int type, const char *fmt, ...) 288{ 289 va_list ap; 290 291 va_start(ap, fmt); |
292 fprintf(stderr, "\"%s\", line %d: ", |
293 curFile.fname, curFile.lineno); 294 if (type == PARSE_WARNING) |
295 fprintf(stderr, "warning: "); 296 vfprintf(stderr, fmt, ap); |
297 va_end(ap); |
298 fprintf(stderr, "\n"); 299 fflush(stderr); |
300 if (type == PARSE_FATAL) 301 fatals += 1; 302} 303 304/*- 305 *--------------------------------------------------------------------- 306 * ParseLinkSrc -- 307 * Link the parent node to its new child. Used in a Lst_ForEach by --- 5 unchanged lines hidden (view full) --- 313 * 314 * Side Effects: 315 * New elements are added to the parents list of cgn and the 316 * children list of cgn. the unmade field of pgn is updated 317 * to reflect the additional child. 318 *--------------------------------------------------------------------- 319 */ 320static int |
321ParseLinkSrc(void *pgnp, void *cgnp) |
322{ |
323 GNode *pgn = (GNode *)pgnp; 324 GNode *cgn = (GNode *)cgnp; 325 326 if (Lst_Member(pgn->children, (void *)cgn) == NULL) { 327 Lst_AtEnd (pgn->children, (void *)cgn); |
328 if (specType == Not) { |
329 Lst_AtEnd (cgn->parents, (void *)pgn); |
330 } 331 pgn->unmade += 1; 332 } 333 return (0); 334} 335 336/*- 337 *--------------------------------------------------------------------- --- 7 unchanged lines hidden (view full) --- 345 * Always 0 346 * 347 * Side Effects: 348 * The type field of the node is altered to reflect any new bits in 349 * the op. 350 *--------------------------------------------------------------------- 351 */ 352static int |
353ParseDoOp(void *gnp, void *opp) |
354{ |
355 GNode *gn = (GNode *)gnp; 356 int op = *(int *)opp; 357 |
358 /* 359 * If the dependency mask of the operator and the node don't match and 360 * the node has actually had an operator applied to it before, and 361 * the operator actually has some dependency information in it, complain. 362 */ 363 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 364 !OP_NOP(gn->type) && !OP_NOP(op)) 365 { |
366 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); |
367 return (1); 368 } 369 370 if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 371 /* 372 * If the node was the object of a :: operator, we need to create a 373 * new instance of it for the children and commands on this dependency 374 * line. The new instance is placed on the 'cohorts' list of the --- 11 unchanged lines hidden (view full) --- 386 * 387 * Make the cohort invisible as well to avoid duplicating it into 388 * other variables. True, parents of this target won't tend to do 389 * anything with their local variables, but better safe than 390 * sorry. 391 */ 392 Lst_ForEach(gn->parents, ParseLinkSrc, (void *)cohort); 393 cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; |
394 Lst_AtEnd(gn->cohorts, (void *)cohort); |
395 396 /* 397 * Replace the node in the targets list with the new copy 398 */ 399 ln = Lst_Member(targets, (void *)gn); 400 Lst_Replace(ln, (void *)cohort); 401 gn = cohort; 402 } --- 20 unchanged lines hidden (view full) --- 423 * Side Effects: 424 * A dependency can be added between the two nodes. 425 * 426 *--------------------------------------------------------------------- 427 */ 428static int 429ParseAddDep(void *pp, void *sp) 430{ |
431 GNode *p = (GNode *)pp; 432 GNode *s = (GNode *)sp; |
433 434 if (p->order < s->order) { 435 /* 436 * XXX: This can cause loops, and loops can cause unmade targets, 437 * but checking is tedious, and the debugging output can show the 438 * problem 439 */ |
440 Lst_AtEnd(p->successors, (void *)s); 441 Lst_AtEnd(s->preds, (void *)p); 442 return (0); |
443 } 444 else |
445 return (1); |
446} 447 448 449/*- 450 *--------------------------------------------------------------------- 451 * ParseDoSrc -- 452 * Given the name of a source, figure out if it is an attribute 453 * and apply it to the targets if it is. Else decide if there is --- 5 unchanged lines hidden (view full) --- 459 * None 460 * 461 * Side Effects: 462 * Operator bits may be added to the list of targets or to the source. 463 * The targets may have a new source added to their lists of children. 464 *--------------------------------------------------------------------- 465 */ 466static void |
467ParseDoSrc(int tOp, char *src, Lst allsrc) |
468{ 469 GNode *gn = NULL; 470 471 if (*src == '.' && isupper ((unsigned char) src[1])) { 472 int keywd = ParseFindKeyword(src); 473 if (keywd != -1) { 474 int op = parseKeywords[keywd].op; 475 if (op != 0) { --- 12 unchanged lines hidden (view full) --- 488 /* 489 * If we have noted the existence of a .MAIN, it means we need 490 * to add the sources of said target to the list of things 491 * to create. The string 'src' is likely to be free, so we 492 * must make a new copy of it. Note that this will only be 493 * invoked if the user didn't specify a target on the command 494 * line. This is to allow #ifmake's to succeed, or something... 495 */ |
496 Lst_AtEnd (create, (void *)estrdup(src)); |
497 /* 498 * Add the name to the .TARGETS variable as well, so the user cna 499 * employ that, if desired. 500 */ 501 Var_Append(".TARGETS", src, VAR_GLOBAL); 502 return; 503 504 case Order: 505 /* 506 * Create proper predecessor/successor links between the previous 507 * source and the current one. 508 */ 509 gn = Targ_FindNode(src, TARG_CREATE); 510 if (predecessor != NULL) { |
511 Lst_AtEnd(predecessor->successors, (void *)gn); 512 Lst_AtEnd(gn->preds, (void *)predecessor); |
513 } 514 /* 515 * The current source now becomes the predecessor for the next one. 516 */ 517 predecessor = gn; 518 break; 519 520 default: 521 /* 522 * If the source is not an attribute, we need to find/create 523 * a node for it. After that we can apply any operator to it 524 * from a special target or link it to its parents, as 525 * appropriate. 526 * 527 * In the case of a source that was the object of a :: operator, 528 * the attribute is applied to all of its instances (as kept in 529 * the 'cohorts' list of the node) or all the cohorts are linked 530 * to all the targets. 531 */ |
532 gn = Targ_FindNode(src, TARG_CREATE); |
533 if (tOp) { 534 gn->type |= tOp; 535 } else { 536 Lst_ForEach (targets, ParseLinkSrc, (void *)gn); 537 } 538 if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 539 GNode *cohort; 540 LstNode ln; --- 6 unchanged lines hidden (view full) --- 547 Lst_ForEach(targets, ParseLinkSrc, (void *)cohort); 548 } 549 } 550 } 551 break; 552 } 553 554 gn->order = waiting; |
555 Lst_AtEnd(allsrc, (void *)gn); |
556 if (waiting) { 557 Lst_ForEach(allsrc, ParseAddDep, (void *)gn); 558 } 559} 560 561/*- 562 *----------------------------------------------------------------------- 563 * ParseFindMain -- --- 8 unchanged lines hidden (view full) --- 572 * mainNode is changed and Targ_SetMain is called. 573 * 574 *----------------------------------------------------------------------- 575 */ 576static int 577ParseFindMain(void *gnp, void *dummy __unused) 578{ 579 GNode *gn = (GNode *) gnp; |
580 if ((gn->type & (OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM)) == 0) { |
581 mainNode = gn; 582 Targ_SetMain(gn); 583 return (1); 584 } else { 585 return (0); 586 } 587} 588 --- 8 unchanged lines hidden (view full) --- 597 * Side Effects: 598 * See Dir_AddDir. 599 * 600 *----------------------------------------------------------------------- 601 */ 602static int 603ParseAddDir(void *path, void *name) 604{ |
605 606 Dir_AddDir((Lst)path, (char *)name); |
607 return(0); 608} 609 610/*- 611 *----------------------------------------------------------------------- 612 * ParseClearPath -- 613 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going 614 * 615 * Results: 616 * === 0 617 * 618 * Side Effects: 619 * See Dir_ClearPath 620 * 621 *----------------------------------------------------------------------- 622 */ 623static int 624ParseClearPath(void *path, void *dummy __unused) 625{ |
626 627 Dir_ClearPath((Lst)path); |
628 return (0); 629} 630 631/*- 632 *--------------------------------------------------------------------- 633 * ParseDoDependency -- 634 * Parse the dependency line in line. 635 * --- 48 unchanged lines hidden (view full) --- 684 waiting = 0; 685 paths = (Lst)NULL; 686 687 curTargs = Lst_Init(FALSE); 688 curSrcs = Lst_Init(FALSE); 689 690 do { 691 for (cp = line; |
692 *cp && !isspace ((unsigned char)*cp) && *cp != '('; |
693 cp++) 694 { 695 if (*cp == '$') { 696 /* 697 * Must be a dynamic source (would have been expanded 698 * otherwise), so call the Var module to parse the puppy 699 * so we can safely advance beyond it...There should be 700 * no errors in this, as they would have been discovered 701 * in the initial Var_Subst and we wouldn't be here. 702 */ 703 int length; 704 Boolean freeIt; 705 char *result; 706 |
707 result = Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt); |
708 709 if (freeIt) { 710 free(result); 711 } |
712 cp += length - 1; |
713 } else if (*cp == '!' || *cp == ':') { 714 /* 715 * We don't want to end a word on ':' or '!' if there is a 716 * better match later on in the string (greedy matching). 717 * This allows the user to have targets like: 718 * fie::fi:fo: fum 719 * foo::bar: 720 * where "fie::fi:fo" and "foo::bar" are the targets. In --- 25 unchanged lines hidden (view full) --- 746 * flag is set in their 'type' field, for one thing, and because 747 * things like "archive(file1.o file2.o file3.o)" are permissible. 748 * Arch_ParseArchive will set 'line' to be the first non-blank 749 * after the archive-spec. It creates/finds nodes for the members 750 * and places them on the given list, returning SUCCESS if all 751 * went well and FAILURE if there was an error in the 752 * specification. On error, line should remain untouched. 753 */ |
754 if (Arch_ParseArchive(&line, targets, VAR_CMD) != SUCCESS) { 755 Parse_Error(PARSE_FATAL, |
756 "Error in archive specification: \"%s\"", line); 757 return; 758 } else { 759 continue; 760 } 761 } 762 savec = *cp; 763 764 if (!*cp) { 765 /* 766 * Ending a dependency line without an operator is a Bozo 767 * no-no. As a heuristic, this is also often triggered by 768 * undetected conflicts from cvs/rcs merges. 769 */ 770 if ((strncmp(line, "<<<<<<", 6) == 0) || 771 (strncmp(line, "======", 6) == 0) || 772 (strncmp(line, ">>>>>>", 6) == 0)) |
773 Parse_Error(PARSE_FATAL, |
774 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); 775 else |
776 Parse_Error(PARSE_FATAL, "Need an operator"); |
777 return; 778 } 779 *cp = '\0'; 780 /* 781 * Have a word in line. See if it's a special target and set 782 * specType to match it. 783 */ |
784 if (*line == '.' && isupper ((unsigned char)line[1])) { |
785 /* 786 * See if the target is a special target that must have it 787 * or its sources handled specially. 788 */ 789 int keywd = ParseFindKeyword(line); 790 if (keywd != -1) { 791 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 792 Parse_Error(PARSE_FATAL, "Mismatched special targets"); --- 31 unchanged lines hidden (view full) --- 824 * .SINGLESHELL Create a shell for each command. 825 * .ORDER Must set initial predecessor to NULL 826 */ 827 switch (specType) { 828 case ExPath: 829 if (paths == NULL) { 830 paths = Lst_Init(FALSE); 831 } |
832 Lst_AtEnd(paths, (void *)dirSearchPath); |
833 break; 834 case Main: 835 if (!Lst_IsEmpty(create)) { 836 specType = Not; 837 } 838 break; 839 case Begin: 840 case End: 841 case Interrupt: 842 gn = Targ_FindNode(line, TARG_CREATE); 843 gn->type |= OP_NOTMAIN; |
844 Lst_AtEnd(targets, (void *)gn); |
845 break; 846 case Default: 847 gn = Targ_NewGN(".DEFAULT"); 848 gn->type |= (OP_NOTMAIN|OP_TRANSFORM); |
849 Lst_AtEnd(targets, (void *)gn); |
850 DEFAULT = gn; 851 break; 852 case NotParallel: 853 { 854 maxJobs = 1; 855 break; 856 } 857 case SingleShell: 858 compatMake = 1; 859 break; 860 case Order: 861 predecessor = NULL; 862 break; 863 default: 864 break; 865 } |
866 } else if (strncmp(line, ".PATH", 5) == 0) { |
867 /* 868 * .PATH<suffix> has to be handled specially. 869 * Call on the suffix module to give us a path to 870 * modify. 871 */ 872 Lst path; 873 874 specType = ExPath; |
875 path = Suff_GetPath(&line[5]); |
876 if (path == NULL) { |
877 Parse_Error(PARSE_FATAL, |
878 "Suffix '%s' not defined (yet)", 879 &line[5]); 880 return; 881 } else { 882 if (paths == (Lst)NULL) { 883 paths = Lst_Init(FALSE); 884 } |
885 Lst_AtEnd(paths, (void *)path); |
886 } 887 } 888 } 889 890 /* 891 * Have word in line. Get or create its node and stick it at 892 * the end of the targets list 893 */ --- 10 unchanged lines hidden (view full) --- 904 Dir_Expand(line, emptyPath, curTargs); 905 906 Lst_Destroy(emptyPath, Dir_Destroy); 907 } else { 908 /* 909 * No wildcards, but we want to avoid code duplication, 910 * so create a list with the word on it. 911 */ |
912 Lst_AtEnd(curTargs, (void *)line); |
913 } 914 915 while(!Lst_IsEmpty(curTargs)) { 916 char *targName = (char *)Lst_DeQueue(curTargs); 917 918 if (!Suff_IsTransform (targName)) { |
919 gn = Targ_FindNode(targName, TARG_CREATE); |
920 } else { |
921 gn = Suff_AddTransform(targName); |
922 } 923 |
924 Lst_AtEnd(targets, (void *)gn); |
925 } 926 } else if (specType == ExPath && *line != '.' && *line != '\0') { 927 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 928 } 929 930 *cp = savec; 931 /* 932 * If it is a special type and not .PATH, it's the only target we --- 54 unchanged lines hidden (view full) --- 987 } else if (*cp == ':') { 988 if (cp[1] == ':') { 989 op = OP_DOUBLEDEP; 990 cp++; 991 } else { 992 op = OP_DEPENDS; 993 } 994 } else { |
995 Parse_Error(PARSE_FATAL, "Missing dependency operator"); |
996 return; 997 } 998 999 cp++; /* Advance beyond operator */ 1000 |
1001 Lst_ForEach(targets, ParseDoOp, (void *)&op); |
1002 1003 /* 1004 * Get to the first source 1005 */ |
1006 while (*cp && isspace ((unsigned char)*cp)) { |
1007 cp++; 1008 } 1009 line = cp; 1010 1011 /* 1012 * Several special targets take different actions if present with no 1013 * sources: 1014 * a .SUFFIXES line with no sources clears out all old suffixes 1015 * a .PRECIOUS line makes all targets precious 1016 * a .IGNORE line ignores errors for all targets 1017 * a .SILENT line creates silence when making all targets 1018 * a .PATH removes all directories from the search path(s). 1019 */ 1020 if (!*line) { 1021 switch (specType) { 1022 case Suffixes: |
1023 Suff_ClearSuffixes(); |
1024 break; 1025 case Precious: 1026 allPrecious = TRUE; 1027 break; 1028 case Ignore: 1029 ignoreErrors = TRUE; 1030 break; 1031 case Silent: --- 9 unchanged lines hidden (view full) --- 1041 break; 1042 } 1043 } else if (specType == MFlags) { 1044 /* 1045 * Call on functions in main.c to deal with these arguments and 1046 * set the initial character to a null-character so the loop to 1047 * get sources won't get anything 1048 */ |
1049 Main_ParseArgLine(line); |
1050 *line = '\0'; 1051 } else if (specType == ExShell) { |
1052 if (Job_ParseShell(line) != SUCCESS) { 1053 Parse_Error(PARSE_FATAL, "improper shell specification"); |
1054 return; 1055 } 1056 *line = '\0'; 1057 } else if ((specType == NotParallel) || (specType == SingleShell)) { 1058 *line = '\0'; 1059 } 1060 1061 /* --- 24 unchanged lines hidden (view full) --- 1086 * If it was .LIBS, the source is taken to be the suffix of 1087 * files which are considered libraries and whose search path 1088 * should be present in the .LIBS variable. 1089 * 1090 * If it was .NULL, the source is the suffix to use when a file 1091 * has no valid suffix. 1092 */ 1093 char savech; |
1094 while (*cp && !isspace ((unsigned char)*cp)) { |
1095 cp++; 1096 } 1097 savech = *cp; 1098 *cp = '\0'; 1099 switch (specType) { 1100 case Suffixes: |
1101 Suff_AddSuffix(line); |
1102 break; 1103 case ExPath: 1104 Lst_ForEach(paths, ParseAddDir, (void *)line); 1105 break; 1106 case Includes: |
1107 Suff_AddInclude(line); |
1108 break; 1109 case Libs: |
1110 Suff_AddLib(line); |
1111 break; 1112 case Null: |
1113 Suff_SetNull(line); |
1114 break; 1115 default: 1116 break; 1117 } 1118 *cp = savech; 1119 if (savech != '\0') { 1120 cp++; 1121 } |
1122 while (*cp && isspace ((unsigned char)*cp)) { |
1123 cp++; 1124 } 1125 line = cp; 1126 } 1127 if (paths) { 1128 Lst_Destroy(paths, NOFREE); 1129 } 1130 } else { 1131 while (*line) { 1132 /* 1133 * The targets take real sources, so we must beware of archive 1134 * specifications (i.e. things with left parentheses in them) 1135 * and handle them accordingly. 1136 */ |
1137 while (*cp && !isspace ((unsigned char)*cp)) { |
1138 if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) { 1139 /* 1140 * Only stop for a left parenthesis if it isn't at the 1141 * start of a word (that'll be for variable changes 1142 * later) and isn't preceded by a dollar sign (a dynamic 1143 * source). 1144 */ 1145 break; 1146 } else { 1147 cp++; 1148 } 1149 } 1150 1151 if (*cp == '(') { 1152 GNode *gnp; 1153 |
1154 sources = Lst_Init(FALSE); 1155 if (Arch_ParseArchive(&line, sources, VAR_CMD) != SUCCESS) { 1156 Parse_Error(PARSE_FATAL, |
1157 "Error in source archive spec \"%s\"", line); 1158 return; 1159 } 1160 1161 while (!Lst_IsEmpty (sources)) { |
1162 gnp = (GNode *)Lst_DeQueue(sources); 1163 ParseDoSrc(tOp, gnp->name, curSrcs); |
1164 } |
1165 Lst_Destroy(sources, NOFREE); |
1166 cp = line; 1167 } else { 1168 if (*cp) { 1169 *cp = '\0'; 1170 cp += 1; 1171 } 1172 |
1173 ParseDoSrc(tOp, line, curSrcs); |
1174 } |
1175 while (*cp && isspace ((unsigned char)*cp)) { |
1176 cp++; 1177 } 1178 line = cp; 1179 } 1180 } 1181 1182 if (mainNode == NULL) { 1183 /* 1184 * If we have yet to decide on a main target to make, in the 1185 * absence of any user input, we want the first target on 1186 * the first dependency line that is actually a real target 1187 * (i.e. isn't a .USE or .EXEC rule) to be made. 1188 */ |
1189 Lst_ForEach(targets, ParseFindMain, (void *)0); |
1190 } 1191 1192 /* 1193 * Finally, destroy the list of sources 1194 */ 1195 Lst_Destroy(curSrcs, NOFREE); 1196} 1197 --- 9 unchanged lines hidden (view full) --- 1207 * Results: 1208 * TRUE if it is. FALSE if it ain't 1209 * 1210 * Side Effects: 1211 * none 1212 *--------------------------------------------------------------------- 1213 */ 1214Boolean |
1215Parse_IsVar(char *line) |
1216{ 1217 Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1218 Boolean haveName = FALSE; /* Set TRUE if have a variable name */ |
1219 |
1220 int level = 0; 1221#define ISEQOPERATOR(c) \ 1222 (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) 1223 1224 /* 1225 * Skip to variable name 1226 */ |
1227 for (; (*line == ' ') || (*line == '\t'); line++) |
1228 continue; 1229 1230 for (; *line != '=' || level != 0; line++) 1231 switch (*line) { 1232 case '\0': 1233 /* 1234 * end-of-line -- can't be a variable assignment. 1235 */ |
1236 return (FALSE); |
1237 1238 case ' ': 1239 case '\t': 1240 /* 1241 * there can be as much white space as desired so long as there is 1242 * only one word before the operator 1243 */ 1244 wasSpace = TRUE; --- 11 unchanged lines hidden (view full) --- 1256 1257 default: 1258 if (wasSpace && haveName) { 1259 if (ISEQOPERATOR(*line)) { 1260 /* 1261 * We must have a finished word 1262 */ 1263 if (level != 0) |
1264 return (FALSE); |
1265 1266 /* 1267 * When an = operator [+?!:] is found, the next 1268 * character must be an = or it ain't a valid 1269 * assignment. 1270 */ 1271 if (line[1] == '=') |
1272 return (haveName); |
1273#ifdef SUNSHCMD 1274 /* 1275 * This is a shell command 1276 */ 1277 if (strncmp(line, ":sh", 3) == 0) |
1278 return (haveName); |
1279#endif 1280 } 1281 /* 1282 * This is the start of another word, so not assignment. 1283 */ |
1284 return (FALSE); |
1285 } 1286 else { 1287 haveName = TRUE; 1288 wasSpace = FALSE; 1289 } 1290 break; 1291 } 1292 |
1293 return (haveName); |
1294} 1295 1296/*- 1297 *--------------------------------------------------------------------- 1298 * Parse_DoVar -- 1299 * Take the variable assignment in the passed line and do it in the 1300 * global context. 1301 * --- 7 unchanged lines hidden (view full) --- 1309 * none 1310 * 1311 * Side Effects: 1312 * the variable structure of the given variable name is altered in the 1313 * global context. 1314 *--------------------------------------------------------------------- 1315 */ 1316void |
1317Parse_DoVar(char *line, GNode *ctxt) |
1318{ 1319 char *cp; /* pointer into line */ 1320 enum { 1321 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL 1322 } type; /* Type of assignment */ 1323 char *opc; /* ptr to operator character to 1324 * null-terminate the variable name */ 1325 /* 1326 * Avoid clobbered variable warnings by forcing the compiler 1327 * to ``unregister'' variables 1328 */ 1329#if __GNUC__ |
1330 (void)&cp; 1331 (void)&line; |
1332#endif 1333 1334 /* 1335 * Skip to variable name 1336 */ 1337 while ((*line == ' ') || (*line == '\t')) { 1338 line++; 1339 } 1340 1341 /* 1342 * Skip to operator character, nulling out whitespace as we go 1343 */ 1344 for (cp = line + 1; *cp != '='; cp++) { |
1345 if (isspace ((unsigned char)*cp)) { |
1346 *cp = '\0'; 1347 } 1348 } |
1349 opc = cp - 1; /* operator is the previous character */ |
1350 *cp++ = '\0'; /* nuke the = */ 1351 1352 /* 1353 * Check operator type 1354 */ 1355 switch (*opc) { 1356 case '+': 1357 type = VAR_APPEND; --- 35 unchanged lines hidden (view full) --- 1393 *opc = '\0'; 1394 break; 1395 } 1396#endif 1397 type = VAR_NORMAL; 1398 break; 1399 } 1400 |
1401 while (isspace ((unsigned char)*cp)) { |
1402 cp++; 1403 } 1404 1405 if (type == VAR_APPEND) { |
1406 Var_Append(line, cp, ctxt); |
1407 } else if (type == VAR_SUBST) { 1408 /* 1409 * Allow variables in the old value to be undefined, but leave their 1410 * invocation alone -- this is done by forcing oldVars to be false. 1411 * XXX: This can cause recursive variables, but that's not hard to do, 1412 * and this allows someone to do something like 1413 * 1414 * CFLAGS = $(.INCLUDES) --- 59 unchanged lines hidden (view full) --- 1474 * 1475 * Side Effects: 1476 * A new element is added to the commands list of the node. 1477 */ 1478static int 1479ParseAddCmd(void *gnp, void *cmd) 1480{ 1481 GNode *gn = (GNode *) gnp; |
1482 |
1483 /* if target already supplied, ignore commands */ 1484 if (!(gn->type & OP_HAS_COMMANDS)) |
1485 Lst_AtEnd(gn->commands, cmd); |
1486 else 1487 Parse_Error(PARSE_WARNING, 1488 "duplicate script for target \"%s\" ignored", 1489 gn->name); |
1490 return (0); |
1491} 1492 1493/*- 1494 *----------------------------------------------------------------------- 1495 * ParseHasCommands -- 1496 * Callback procedure for Parse_File when destroying the list of 1497 * targets on the last dependency line. Marks a target as already 1498 * having commands if it does, to keep from having shell commands --- 5 unchanged lines hidden (view full) --- 1504 * Side Effects: 1505 * OP_HAS_COMMANDS may be set for the target. 1506 * 1507 *----------------------------------------------------------------------- 1508 */ 1509static void 1510ParseHasCommands(void *gnp) 1511{ |
1512 |
1513 GNode *gn = (GNode *) gnp; |
1514 |
1515 if (!Lst_IsEmpty(gn->commands)) { 1516 gn->type |= OP_HAS_COMMANDS; 1517 } 1518} 1519 1520/*- 1521 *----------------------------------------------------------------------- 1522 * Parse_AddIncludeDir -- --- 4 unchanged lines hidden (view full) --- 1527 * None. 1528 * 1529 * Side Effects: 1530 * The directory is appended to the list. 1531 * 1532 *----------------------------------------------------------------------- 1533 */ 1534void |
1535Parse_AddIncludeDir(char *dir) |
1536{ |
1537 1538 Dir_AddDir(parseIncPath, dir); |
1539} 1540 1541/*--------------------------------------------------------------------- 1542 * ParseDoError -- 1543 * Handle error directive 1544 * 1545 * The input is the line minus the ".error". We substitute variables, 1546 * print the message and exit(1) or just print a warning if the ".error" 1547 * directive is malformed. 1548 * 1549 *--------------------------------------------------------------------- 1550 */ 1551static void 1552ParseDoError(char *errmsg) 1553{ |
1554 1555 if (!isspace((unsigned char)*errmsg)) { |
1556 Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg); 1557 return; 1558 } |
1559 1560 while (isspace((unsigned char)*errmsg)) |
1561 errmsg++; |
1562 |
1563 errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE); 1564 1565 Parse_Error(PARSE_FATAL, "%s", errmsg); 1566 /* Terminate immediately. */ 1567 exit(1); 1568} 1569 1570/*--------------------------------------------------------------------- --- 4 unchanged lines hidden (view full) --- 1575 * and print the message or just print a warning if the ".warning" 1576 * directive is malformed. 1577 * 1578 *--------------------------------------------------------------------- 1579 */ 1580static void 1581ParseDoWarning(char *warnmsg) 1582{ |
1583 1584 if (!isspace((unsigned char)*warnmsg)) { |
1585 Parse_Error(PARSE_WARNING, "invalid syntax: .warning%s", 1586 warnmsg); 1587 return; 1588 } |
1589 1590 while (isspace((unsigned char)*warnmsg)) |
1591 warnmsg++; |
1592 |
1593 warnmsg = Var_Subst(NULL, warnmsg, VAR_GLOBAL, FALSE); 1594 1595 Parse_Error(PARSE_WARNING, "%s", warnmsg); 1596} 1597 1598/*- 1599 *--------------------------------------------------------------------- 1600 * ParseDoInclude -- --- 24 unchanged lines hidden (view full) --- 1625 /* 1626 * Skip to delimiter character so we know where to look 1627 */ 1628 while ((*file == ' ') || (*file == '\t')) { 1629 file++; 1630 } 1631 1632 if ((*file != '"') && (*file != '<')) { |
1633 Parse_Error(PARSE_FATAL, |
1634 ".include filename must be delimited by '\"' or '<'"); 1635 return; 1636 } 1637 1638 /* 1639 * Set the search path on which to find the include file based on the 1640 * characters which bracket its name. Angle-brackets imply it's 1641 * a system Makefile while double-quotes imply it's a user makefile --- 9 unchanged lines hidden (view full) --- 1651 /* 1652 * Skip to matching delimiter 1653 */ 1654 for (cp = ++file; *cp && *cp != endc; cp++) { 1655 continue; 1656 } 1657 1658 if (*cp != endc) { |
1659 Parse_Error(PARSE_FATAL, |
1660 "Unclosed %cinclude filename. '%c' expected", 1661 '.', endc); 1662 return; 1663 } 1664 *cp = '\0'; 1665 1666 /* 1667 * Substitute for any variables in the file name before trying to 1668 * find the thing. 1669 */ |
1670 file = Var_Subst(NULL, file, VAR_CMD, FALSE); |
1671 1672 /* 1673 * Now we know the file's name and its search path, we attempt to 1674 * find the durn thing. A return of NULL indicates the file don't 1675 * exist. 1676 */ 1677 if (!isSystem) { 1678 /* 1679 * Include files contained in double-quotes are first searched for 1680 * relative to the including file's location. We don't want to 1681 * cd there, of course, so we just tack on the old file's 1682 * leading path components and call Dir_FindFile to see if 1683 * we can locate the beast. 1684 */ 1685 char *prefEnd, *Fname; 1686 1687 /* Make a temporary copy of this, to be safe. */ 1688 Fname = estrdup(curFile.fname); 1689 |
1690 prefEnd = strrchr(Fname, '/'); |
1691 if (prefEnd != (char *)NULL) { 1692 char *newName; 1693 1694 *prefEnd = '\0'; 1695 if (file[0] == '/') 1696 newName = estrdup(file); 1697 else |
1698 newName = str_concat(Fname, file, STR_ADDSLASH); 1699 fullname = Dir_FindFile(newName, parseIncPath); |
1700 if (fullname == (char *)NULL) { 1701 fullname = Dir_FindFile(newName, dirSearchPath); 1702 } |
1703 free(newName); |
1704 *prefEnd = '/'; 1705 } else { 1706 fullname = (char *)NULL; 1707 } |
1708 free(Fname); |
1709 } else { 1710 fullname = (char *)NULL; 1711 } 1712 1713 if (fullname == (char *)NULL) { 1714 /* 1715 * System makefile or makefile wasn't found in same directory as 1716 * included makefile. Search for it first on the -I search path, 1717 * then on the .PATH search path, if not found in a -I directory. 1718 * XXX: Suffix specific? 1719 */ |
1720 fullname = Dir_FindFile(file, parseIncPath); |
1721 if (fullname == (char *)NULL) { 1722 fullname = Dir_FindFile(file, dirSearchPath); 1723 } 1724 } 1725 1726 if (fullname == (char *)NULL) { 1727 /* 1728 * Still haven't found the makefile. Look for it on the system 1729 * path as a last resort. 1730 */ 1731 fullname = Dir_FindFile(file, sysIncPath); 1732 } 1733 1734 if (fullname == (char *) NULL) { 1735 *cp = endc; |
1736 Parse_Error(PARSE_FATAL, "Could not find %s", file); |
1737 return; 1738 } 1739 1740 free(file); 1741 1742 /* 1743 * Once we find the absolute path to the file, we get to save all the 1744 * state from the current file before we can start reading this 1745 * include file. The state is stored in an IFile structure which 1746 * is placed on a list with other IFile structures. The list makes 1747 * a very nice stack to track how we got here... 1748 */ |
1749 oldFile = (IFile *) emalloc(sizeof (IFile)); |
1750 memcpy(oldFile, &curFile, sizeof (IFile)); 1751 |
1752 Lst_AtFront(includes, (void *)oldFile); |
1753 1754 /* 1755 * Once the previous state has been saved, we can get down to reading 1756 * the new file. We set up the name of the file to be the absolute 1757 * name of the include file so error messages refer to the right 1758 * place. Naturally enough, we start reading at line number 0. 1759 */ 1760 curFile.fname = fullname; 1761 curFile.lineno = 0; 1762 |
1763 curFile.F = fopen(fullname, "r"); |
1764 curFile.p = NULL; 1765 if (curFile.F == (FILE * ) NULL) { |
1766 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); |
1767 /* 1768 * Pop to previous file 1769 */ |
1770 ParseEOF(0); |
1771 } else { 1772 Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 1773 } 1774} 1775 |
1776/*- 1777 *--------------------------------------------------------------------- 1778 * Parse_FromString -- 1779 * Start Parsing from the given string 1780 * 1781 * Results: 1782 * None 1783 * --- 4 unchanged lines hidden (view full) --- 1788 */ 1789void 1790Parse_FromString(char *str, int lineno) 1791{ 1792 IFile *oldFile; /* state associated with this file */ 1793 1794 DEBUGF(FOR, ("%s\n---- at line %d\n", str, lineno)); 1795 |
1796 oldFile = (IFile *)emalloc(sizeof(IFile)); 1797 memcpy(oldFile, &curFile, sizeof(IFile)); |
1798 |
1799 Lst_AtFront (includes, (void *)oldFile); |
1800 1801 curFile.F = NULL; |
1802 curFile.p = (PTR *)emalloc(sizeof (PTR)); |
1803 curFile.p->str = curFile.p->ptr = str; 1804 curFile.lineno = lineno; 1805 curFile.fname = estrdup(curFile.fname); 1806} 1807 |
1808#ifdef SYSVINCLUDE 1809/*- 1810 *--------------------------------------------------------------------- 1811 * ParseTraditionalInclude -- 1812 * Push to another file. 1813 * 1814 * The input is the line minus the "include". The file name is 1815 * the string following the "include". --- 16 unchanged lines hidden (view full) --- 1832 /* 1833 * Skip over whitespace 1834 */ 1835 while ((*file == ' ') || (*file == '\t')) { 1836 file++; 1837 } 1838 1839 if (*file == '\0') { |
1840 Parse_Error(PARSE_FATAL, |
1841 "Filename missing from \"include\""); 1842 return; 1843 } 1844 1845 /* 1846 * Skip to end of line or next whitespace 1847 */ 1848 for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { 1849 continue; 1850 } 1851 1852 *cp = '\0'; 1853 1854 /* 1855 * Substitute for any variables in the file name before trying to 1856 * find the thing. 1857 */ |
1858 file = Var_Subst(NULL, file, VAR_CMD, FALSE); |
1859 1860 /* 1861 * Now we know the file's name, we attempt to find the durn thing. 1862 * Search for it first on the -I search path, then on the .PATH 1863 * search path, if not found in a -I directory. 1864 */ |
1865 fullname = Dir_FindFile(file, parseIncPath); |
1866 if (fullname == (char *)NULL) { 1867 fullname = Dir_FindFile(file, dirSearchPath); 1868 } 1869 1870 if (fullname == (char *)NULL) { 1871 /* 1872 * Still haven't found the makefile. Look for it on the system 1873 * path as a last resort. 1874 */ 1875 fullname = Dir_FindFile(file, sysIncPath); 1876 } 1877 1878 if (fullname == (char *) NULL) { |
1879 Parse_Error(PARSE_FATAL, "Could not find %s", file); |
1880 return; 1881 } 1882 1883 /* 1884 * Once we find the absolute path to the file, we get to save all the 1885 * state from the current file before we can start reading this 1886 * include file. The state is stored in an IFile structure which 1887 * is placed on a list with other IFile structures. The list makes 1888 * a very nice stack to track how we got here... 1889 */ |
1890 oldFile = (IFile *)emalloc(sizeof(IFile)); 1891 memcpy(oldFile, &curFile, sizeof(IFile)); |
1892 |
1893 Lst_AtFront(includes, (void *)oldFile); |
1894 1895 /* 1896 * Once the previous state has been saved, we can get down to reading 1897 * the new file. We set up the name of the file to be the absolute 1898 * name of the include file so error messages refer to the right 1899 * place. Naturally enough, we start reading at line number 0. 1900 */ 1901 curFile.fname = fullname; 1902 curFile.lineno = 0; 1903 |
1904 curFile.F = fopen(fullname, "r"); |
1905 curFile.p = NULL; |
1906 if (curFile.F == (FILE * )NULL) { 1907 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); |
1908 /* 1909 * Pop to previous file 1910 */ |
1911 ParseEOF(1); |
1912 } else { 1913 Var_Append(".MAKEFILE_LIST", fullname, VAR_GLOBAL); 1914 } 1915} 1916#endif 1917 1918/*- 1919 *--------------------------------------------------------------------- --- 7 unchanged lines hidden (view full) --- 1927 * 1928 * Side Effects: 1929 * The old curFile.F is closed. The includes list is shortened. 1930 * curFile.lineno, curFile.F, and curFile.fname are changed if 1931 * CONTINUE is returned. 1932 *--------------------------------------------------------------------- 1933 */ 1934static int |
1935ParseEOF(int opened) |
1936{ 1937 IFile *ifile; /* the state on the top of the includes stack */ 1938 1939 if (Lst_IsEmpty (includes)) { 1940 Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 1941 return (DONE); 1942 } 1943 |
1944 ifile = (IFile *)Lst_DeQueue(includes); 1945 free(curFile.fname); |
1946 if (opened && curFile.F) { |
1947 fclose(curFile.F); |
1948 Var_Append(".MAKEFILE_LIST", "..", VAR_GLOBAL); 1949 } 1950 if (curFile.p) { 1951 free(curFile.p->str); 1952 free(curFile.p); 1953 } |
1954 memcpy(&curFile, ifile, sizeof(IFile)); 1955 free(ifile); |
1956 return (CONTINUE); 1957} 1958 1959/*- 1960 *--------------------------------------------------------------------- 1961 * ParseReadc -- 1962 * Read a character from the current file 1963 * 1964 * Results: 1965 * The character that was read 1966 * 1967 * Side Effects: 1968 *--------------------------------------------------------------------- 1969 */ 1970static int 1971ParseReadc(void) 1972{ |
1973 |
1974 if (curFile.F) |
1975 return (fgetc(curFile.F)); |
1976 1977 if (curFile.p && *curFile.p->ptr) |
1978 return (*curFile.p->ptr++); 1979 return (EOF); |
1980} 1981 1982 1983/*- 1984 *--------------------------------------------------------------------- 1985 * ParseUnreadc -- 1986 * Put back a character to the current file 1987 * 1988 * Results: 1989 * None. 1990 * 1991 * Side Effects: 1992 *--------------------------------------------------------------------- 1993 */ 1994static void 1995ParseUnreadc(int c) 1996{ |
1997 |
1998 if (curFile.F) { 1999 ungetc(c, curFile.F); 2000 return; 2001 } 2002 if (curFile.p) { 2003 *--(curFile.p->ptr) = c; 2004 return; 2005 } --- 42 unchanged lines hidden (view full) --- 2048 2049 Buf_AddByte(buf, (Byte)c); 2050 lastc = c; 2051 } 2052 2053 if (c == EOF) { 2054 Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop"); 2055 Buf_Destroy(buf, TRUE); |
2056 return ((char *)NULL); |
2057 } 2058 2059 curFile.lineno++; 2060 Buf_AddByte(buf, (Byte)'\0'); 2061 line = (char *)Buf_GetAll(buf, &lineLength); 2062 } while (skip == 1 && line[0] != '.'); 2063 2064 Buf_Destroy(buf, FALSE); |
2065 return (line); |
2066} 2067 2068 2069/*- 2070 *--------------------------------------------------------------------- 2071 * ParseReadLine -- 2072 * Read an entire line from the input file. Called only by Parse_File. 2073 * To facilitate escaped newlines and what have you, a character is --- 5 unchanged lines hidden (view full) --- 2079 * Results: 2080 * A line w/o its newline 2081 * 2082 * Side Effects: 2083 * Only those associated with reading a character 2084 *--------------------------------------------------------------------- 2085 */ 2086static char * |
2087ParseReadLine(void) |
2088{ 2089 Buffer buf; /* Buffer for current line */ 2090 int c; /* the current character */ 2091 int lastc; /* The most-recent character */ 2092 Boolean semiNL; /* treat semi-colons as newlines */ 2093 Boolean ignDepOp; /* TRUE if should ignore dependency operators 2094 * for the purposes of setting semiNL */ 2095 Boolean ignComment; /* TRUE if should ignore comments (in a --- 32 unchanged lines hidden (view full) --- 2128 break; 2129 } 2130 } 2131 2132 if (c != EOF) { 2133 lastc = c; 2134 buf = Buf_Init(MAKE_BSIZE); 2135 |
2136 while (((c = ParseReadc()) != '\n' || (lastc == '\\')) && |
2137 (c != EOF)) 2138 { 2139test_char: |
2140 switch (c) { |
2141 case '\n': 2142 /* 2143 * Escaped newline: read characters until a non-space or an 2144 * unescaped newline and replace them all by a single space. 2145 * This is done by storing the space over the backslash and 2146 * dropping through with the next nonspace. If it is a 2147 * semi-colon and semiNL is TRUE, it will be recognized as a 2148 * newline in the code below this... 2149 */ 2150 curFile.lineno++; 2151 lastc = ' '; |
2152 while ((c = ParseReadc()) == ' ' || c == '\t') { |
2153 continue; 2154 } 2155 if (c == EOF || c == '\n') { 2156 goto line_read; 2157 } else { 2158 /* 2159 * Check for comments, semiNL's, etc. -- easier than 2160 * ParseUnreadc(c); continue; --- 35 unchanged lines hidden (view full) --- 2196 * was the previous character, so this is really just an 2197 * expanded variable assignment. Revert semi-colons to 2198 * being just semi-colons again and ignore any more 2199 * dependency operators. 2200 * 2201 * XXX: Note that a line like "foo : a:=b" will blow up, 2202 * but who'd write a line like that anyway? 2203 */ |
2204 ignDepOp = TRUE; 2205 semiNL = FALSE; |
2206 } 2207 break; 2208 case '#': 2209 if (!ignComment) { 2210 if (lastc != '\\') { 2211 /* 2212 * If the character is a hash mark and it isn't escaped 2213 * (or we're being compatible), the thing is a comment. --- 25 unchanged lines hidden (view full) --- 2239 } 2240 break; 2241 default: 2242 break; 2243 } 2244 /* 2245 * Copy in the previous character and save this one in lastc. 2246 */ |
2247 Buf_AddByte(buf, (Byte)lastc); |
2248 lastc = c; 2249 2250 } 2251 line_read: 2252 curFile.lineno++; 2253 2254 if (lastc != '\0') { |
2255 Buf_AddByte(buf, (Byte)lastc); |
2256 } |
2257 Buf_AddByte(buf, (Byte)'\0'); 2258 line = (char *)Buf_GetAll(buf, &lineLength); 2259 Buf_Destroy(buf, FALSE); |
2260 2261 /* 2262 * Strip trailing blanks and tabs from the line. 2263 * Do not strip a blank or tab that is preceded by 2264 * a '\' 2265 */ 2266 ep = line; 2267 while (*ep) --- 5 unchanged lines hidden (view full) --- 2273 } 2274 *ep = 0; 2275 2276 if (line[0] == '.') { 2277 /* 2278 * The line might be a conditional. Ask the conditional module 2279 * about it and act accordingly 2280 */ |
2281 switch (Cond_Eval(line)) { |
2282 case COND_SKIP: 2283 /* 2284 * Skip to next conditional that evaluates to COND_PARSE. 2285 */ 2286 do { |
2287 free(line); |
2288 line = ParseSkipLine(1, 0); 2289 } while (line && Cond_Eval(line) != COND_PARSE); 2290 if (line == NULL) 2291 break; 2292 /*FALLTHRU*/ 2293 case COND_PARSE: |
2294 free(line); |
2295 line = ParseReadLine(); 2296 break; 2297 case COND_INVALID: 2298 if (For_Eval(line)) { 2299 int ok; 2300 free(line); 2301 lineno = curFile.lineno; 2302 do { 2303 /* 2304 * Skip after the matching end 2305 */ 2306 line = ParseSkipLine(0, 1); 2307 if (line == NULL) { |
2308 Parse_Error(PARSE_FATAL, |
2309 "Unexpected end of file in for loop.\n"); 2310 break; 2311 } 2312 ok = For_Eval(line); 2313 free(line); 2314 } 2315 while (ok); 2316 if (line != NULL) --- 6 unchanged lines hidden (view full) --- 2323 } 2324 } 2325 return (line); 2326 2327 } else { 2328 /* 2329 * Hit end-of-file, so return a NULL line to indicate this. 2330 */ |
2331 return ((char *)NULL); |
2332 } 2333} 2334 2335/*- 2336 *----------------------------------------------------------------------- 2337 * ParseFinishLine -- 2338 * Handle the end of a dependency group. 2339 * 2340 * Results: 2341 * Nothing. 2342 * 2343 * Side Effects: 2344 * inLine set FALSE. 'targets' list destroyed. 2345 * 2346 *----------------------------------------------------------------------- 2347 */ 2348static void 2349ParseFinishLine(void) 2350{ |
2351 |
2352 if (inLine) { 2353 Lst_ForEach(targets, Suff_EndTransform, (void *)NULL); |
2354 Lst_Destroy(targets, ParseHasCommands); |
2355 targets = NULL; 2356 inLine = FALSE; 2357 } 2358} 2359 2360 2361/*- 2362 *--------------------------------------------------------------------- --- 20 unchanged lines hidden (view full) --- 2383 curFile.fname = name; 2384 curFile.F = stream; 2385 curFile.lineno = 0; 2386 fatals = 0; 2387 2388 Var_Append(".MAKEFILE_LIST", name, VAR_GLOBAL); 2389 2390 do { |
2391 while ((line = ParseReadLine()) != NULL) { |
2392 if (*line == '.') { 2393 /* 2394 * Lines that begin with the special character are either 2395 * include or undef directives. 2396 */ |
2397 for (cp = line + 1; isspace((unsigned char)*cp); cp++) { |
2398 continue; 2399 } |
2400 if (strncmp(cp, "include", 7) == 0) { |
2401 ParseDoInclude (cp + 7); 2402 goto nextLine; |
2403 } else if (strncmp(cp, "error", 5) == 0) { |
2404 ParseDoError(cp + 5); |
2405 goto nextLine; 2406 } else if (strncmp(cp, "warning", 7) == 0) { |
2407 ParseDoWarning(cp + 7); |
2408 goto nextLine; |
2409 } else if (strncmp(cp, "undef", 5) == 0) { 2410 char *cp2; |
2411 for (cp += 5; isspace((unsigned char)*cp); cp++) { |
2412 continue; 2413 } 2414 |
2415 for (cp2 = cp; !isspace((unsigned char)*cp2) && |
2416 (*cp2 != '\0'); cp2++) { 2417 continue; 2418 } 2419 2420 *cp2 = '\0'; 2421 2422 cp = Var_Subst(NULL, cp, VAR_CMD, FALSE); 2423 Var_Delete(cp, VAR_GLOBAL); --- 5 unchanged lines hidden (view full) --- 2429 goto nextLine; 2430 } 2431 2432 if (*line == '\t') { 2433 /* 2434 * If a line starts with a tab, it can only hope to be 2435 * a creation command. 2436 */ |
2437 for (cp = line + 1; isspace((unsigned char)*cp); cp++) { |
2438 continue; 2439 } 2440 if (*cp) { 2441 if (inLine) { 2442 /* 2443 * So long as it's not a blank line and we're actually 2444 * in a dependency spec, add the command to the list of 2445 * commands of all targets in the dependency spec 2446 */ |
2447 Lst_ForEach(targets, ParseAddCmd, cp); 2448 Lst_AtEnd(targCmds, (void *)line); |
2449 continue; 2450 } else { |
2451 Parse_Error(PARSE_FATAL, |
2452 "Unassociated shell command \"%s\"", 2453 cp); 2454 } 2455 } 2456#ifdef SYSVINCLUDE |
2457 } else if (strncmp(line, "include", 7) == 0 && 2458 isspace((unsigned char)line[7]) && |
2459 strchr(line, ':') == NULL) { 2460 /* 2461 * It's an S3/S5-style "include". 2462 */ |
2463 ParseTraditionalInclude(line + 7); |
2464 goto nextLine; 2465#endif |
2466 } else if (Parse_IsVar(line)) { |
2467 ParseFinishLine(); |
2468 Parse_DoVar(line, VAR_GLOBAL); |
2469 } else { 2470 /* 2471 * We now know it's a dependency line so it needs to have all 2472 * variables expanded before being parsed. Tell the variable 2473 * module to complain if some variable is undefined... 2474 * To make life easier on novices, if the line is indented we 2475 * first make sure the line has a dependency operator in it. 2476 * If it doesn't have an operator and we're in a dependency 2477 * line's script, we assume it's actually a shell command 2478 * and add it to the current list of targets. 2479 */ 2480 cp = line; |
2481 if (isspace((unsigned char)line[0])) { 2482 while ((*cp != '\0') && isspace((unsigned char)*cp)) { |
2483 cp++; 2484 } 2485 if (*cp == '\0') { 2486 goto nextLine; 2487 } 2488 } 2489 2490 ParseFinishLine(); 2491 |
2492 cp = Var_Subst(NULL, line, VAR_CMD, TRUE); 2493 free(line); |
2494 line = cp; 2495 2496 /* 2497 * Need a non-circular list for the target nodes 2498 */ 2499 if (targets) 2500 Lst_Destroy(targets, NOFREE); 2501 |
2502 targets = Lst_Init(FALSE); |
2503 inLine = TRUE; 2504 2505 ParseDoDependency (line); 2506 } 2507 2508 nextLine: 2509 |
2510 free(line); |
2511 } 2512 /* 2513 * Reached EOF, but it may be just EOF of an include file... 2514 */ 2515 } while (ParseEOF(1) == CONTINUE); 2516 2517 /* 2518 * Make sure conditionals are clean --- 12 unchanged lines hidden (view full) --- 2531 * Results: 2532 * none 2533 * 2534 * Side Effects: 2535 * the parseIncPath list is initialized... 2536 *--------------------------------------------------------------------- 2537 */ 2538void |
2539Parse_Init(void) |
2540{ |
2541 |
2542 mainNode = NULL; |
2543 parseIncPath = Lst_Init(FALSE); 2544 sysIncPath = Lst_Init(FALSE); 2545 includes = Lst_Init(FALSE); 2546 targCmds = Lst_Init(FALSE); |
2547} 2548 2549void |
2550Parse_End(void) |
2551{ |
2552 |
2553 Lst_Destroy(targCmds, free); 2554 if (targets) 2555 Lst_Destroy(targets, NOFREE); 2556 Lst_Destroy(sysIncPath, Dir_Destroy); 2557 Lst_Destroy(parseIncPath, Dir_Destroy); 2558 Lst_Destroy(includes, NOFREE); /* Should be empty now */ 2559} 2560 --- 12 unchanged lines hidden (view full) --- 2573 * 2574 *----------------------------------------------------------------------- 2575 */ 2576Lst 2577Parse_MainName(void) 2578{ 2579 Lst listmain; /* result list */ 2580 |
2581 listmain = Lst_Init(FALSE); |
2582 2583 if (mainNode == NULL) { |
2584 Punt("no target to make."); |
2585 /*NOTREACHED*/ 2586 } else if (mainNode->type & OP_DOUBLEDEP) { |
2587 Lst_AtEnd(listmain, (void *)mainNode); |
2588 Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW); 2589 } 2590 else |
2591 Lst_AtEnd(listmain, (void *)mainNode); |
2592 return (listmain); 2593} |