Sat Nov 7 22:25:20 2020 UTC ()
make(1): clean up parse.c

The generated code stays exactly the same.  The only changes will be the
line numbers of assertions.  To preserve them, the removed lines have
been filled up with comments and will be removed in the follow-up commit.


(rillig)
diff -r1.429 -r1.430 src/usr.bin/make/parse.c

cvs diff -r1.429 -r1.430 src/usr.bin/make/parse.c (expand / switch to unified diff)

--- src/usr.bin/make/parse.c 2020/11/07 10:44:53 1.429
+++ src/usr.bin/make/parse.c 2020/11/07 22:25:19 1.430
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: parse.c,v 1.429 2020/11/07 10:44:53 rillig Exp $ */ 1/* $NetBSD: parse.c,v 1.430 2020/11/07 22:25:19 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -107,27 +107,27 @@ @@ -107,27 +107,27 @@
107#ifndef MAP_FILE 107#ifndef MAP_FILE
108#define MAP_FILE 0 108#define MAP_FILE 0
109#endif 109#endif
110#ifndef MAP_COPY 110#ifndef MAP_COPY
111#define MAP_COPY MAP_PRIVATE 111#define MAP_COPY MAP_PRIVATE
112#endif 112#endif
113 113
114#include "make.h" 114#include "make.h"
115#include "dir.h" 115#include "dir.h"
116#include "job.h" 116#include "job.h"
117#include "pathnames.h" 117#include "pathnames.h"
118 118
119/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ 119/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
120MAKE_RCSID("$NetBSD: parse.c,v 1.429 2020/11/07 10:44:53 rillig Exp $"); 120MAKE_RCSID("$NetBSD: parse.c,v 1.430 2020/11/07 22:25:19 rillig Exp $");
121 121
122/* types and constants */ 122/* types and constants */
123 123
124/* 124/*
125 * Structure for a file being read ("included file") 125 * Structure for a file being read ("included file")
126 */ 126 */
127typedef struct IFile { 127typedef struct IFile {
128 char *fname; /* name of file (relative? absolute?) */ 128 char *fname; /* name of file (relative? absolute?) */
129 Boolean fromForLoop; /* simulated .include by the .for loop */ 129 Boolean fromForLoop; /* simulated .include by the .for loop */
130 int lineno; /* current line number in file */ 130 int lineno; /* current line number in file */
131 int first_lineno; /* line number of start of text */ 131 int first_lineno; /* line number of start of text */
132 unsigned int cond_depth; /* 'if' nesting when file opened */ 132 unsigned int cond_depth; /* 'if' nesting when file opened */
133 Boolean depending; /* state of doing_depend on EOF */ 133 Boolean depending; /* state of doing_depend on EOF */
@@ -363,141 +363,141 @@ loadedfile_create(const char *path) @@ -363,141 +363,141 @@ loadedfile_create(const char *path)
363 lf = bmake_malloc(sizeof *lf); 363 lf = bmake_malloc(sizeof *lf);
364 lf->path = path == NULL ? "(stdin)" : path; 364 lf->path = path == NULL ? "(stdin)" : path;
365 lf->buf = NULL; 365 lf->buf = NULL;
366 lf->len = 0; 366 lf->len = 0;
367 lf->maplen = 0; 367 lf->maplen = 0;
368 lf->used = FALSE; 368 lf->used = FALSE;
369 return lf; 369 return lf;
370} 370}
371 371
372static void 372static void
373loadedfile_destroy(struct loadedfile *lf) 373loadedfile_destroy(struct loadedfile *lf)
374{ 374{
375 if (lf->buf != NULL) { 375 if (lf->buf != NULL) {
376 if (lf->maplen > 0) { 376 if (lf->maplen > 0)
377 munmap(lf->buf, lf->maplen); 377 munmap(lf->buf, lf->maplen);
378 } else { 378 else
379 free(lf->buf); 379 free(lf->buf);
380 } 
381 } 380 }
382 free(lf); 381 free(lf);
383} 382}
 383/* deleteme */
384 384
385/* 385/*
386 * nextbuf() operation for loadedfile, as needed by the weird and twisted 386 * nextbuf() operation for loadedfile, as needed by the weird and twisted
387 * logic below. Once that's cleaned up, we can get rid of lf->used... 387 * logic below. Once that's cleaned up, we can get rid of lf->used...
388 */ 388 */
389static char * 389static char *
390loadedfile_nextbuf(void *x, size_t *len) 390loadedfile_nextbuf(void *x, size_t *len)
391{ 391{
392 struct loadedfile *lf = x; 392 struct loadedfile *lf = x;
393 393
394 if (lf->used) { 394 if (lf->used)
395 return NULL; 395 return NULL;
396 } 396
397 lf->used = TRUE; 397 lf->used = TRUE;
398 *len = lf->len; 398 *len = lf->len;
399 return lf->buf; 399 return lf->buf;
400} 400}
401 401
402/* 402/*
403 * Try to get the size of a file. 403 * Try to get the size of a file.
404 */ 404 */
405static Boolean 405static Boolean
406load_getsize(int fd, size_t *ret) 406load_getsize(int fd, size_t *ret)
407{ 407{
408 struct stat st; 408 struct stat st;
409 409
410 if (fstat(fd, &st) < 0) { 410 if (fstat(fd, &st) < 0)
411 return FALSE; 411 return FALSE;
412 } 
413 412
414 if (!S_ISREG(st.st_mode)) { 413 if (!S_ISREG(st.st_mode))
415 return FALSE; 414 return FALSE;
416 } 
417 415
418 /* 416 /*
419 * st_size is an off_t, which is 64 bits signed; *ret is 417 * st_size is an off_t, which is 64 bits signed; *ret is
420 * size_t, which might be 32 bits unsigned or 64 bits 418 * size_t, which might be 32 bits unsigned or 64 bits
421 * unsigned. Rather than being elaborate, just punt on 419 * unsigned. Rather than being elaborate, just punt on
422 * files that are more than 2^31 bytes. We should never 420 * files that are more than 2^31 bytes. We should never
423 * see a makefile that size in practice... 421 * see a makefile that size in practice...
424 * 422 *
425 * While we're at it reject negative sizes too, just in case. 423 * While we're at it reject negative sizes too, just in case.
426 */ 424 */
427 if (st.st_size < 0 || st.st_size > 0x7fffffff) { 425 if (st.st_size < 0 || st.st_size > 0x7fffffff)
428 return FALSE; 426 return FALSE;
429 } 
430 427
431 *ret = (size_t)st.st_size; 428 *ret = (size_t)st.st_size;
432 return TRUE; 429 return TRUE;
433} 430}
 431/* deleteme */
 432/* deleteme */
 433/* deleteme */
434 434
435static Boolean 435static Boolean
436loadedfile_mmap(struct loadedfile *lf, int fd) 436loadedfile_mmap(struct loadedfile *lf, int fd)
437{ 437{
438 static unsigned long pagesize = 0; 438 static unsigned long pagesize = 0;
439 439
440 if (load_getsize(fd, &lf->len)) { 440 if (!load_getsize(fd, &lf->len))
 441 return FALSE;
441 442
442 /* found a size, try mmap */ 443 /* found a size, try mmap */
443 if (pagesize == 0) 444 if (pagesize == 0)
444 pagesize = (unsigned long)sysconf(_SC_PAGESIZE); 445 pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
445 if (pagesize == 0 || pagesize == (unsigned long)-1) { 446 if (pagesize == 0 || pagesize == (unsigned long)-1)
446 pagesize = 0x1000; 447 pagesize = 0x1000;
447 } 
448 /* round size up to a page */ 
449 lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize); 
450 448
451 /* 449 /* round size up to a page */
452 * XXX hack for dealing with empty files; remove when 450 lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize);
453 * we're no longer limited by interfacing to the old 
454 * logic elsewhere in this file. 
455 */ 
456 if (lf->maplen == 0) { 
457 lf->maplen = pagesize; 
458 } 
459 451
460 /* 452 /*
461 * FUTURE: remove PROT_WRITE when the parser no longer 453 * XXX hack for dealing with empty files; remove when
462 * needs to scribble on the input. 454 * we're no longer limited by interfacing to the old
463 */ 455 * logic elsewhere in this file.
464 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE, 456 */
465 MAP_FILE|MAP_COPY, fd, 0); 457 if (lf->maplen == 0)
466 if (lf->buf != MAP_FAILED) { 458 lf->maplen = pagesize;
467 /* succeeded */ 459
468 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') { 460 /*
469 char *b = bmake_malloc(lf->len + 1); 461 * FUTURE: remove PROT_WRITE when the parser no longer
470 b[lf->len] = '\n'; 462 * needs to scribble on the input.
471 memcpy(b, lf->buf, lf->len++); 463 */
472 munmap(lf->buf, lf->maplen); 464 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
473 lf->maplen = 0; 465 MAP_FILE|MAP_COPY, fd, 0);
474 lf->buf = b; 466 if (lf->buf == MAP_FAILED)
475 } 467 return FALSE;
476 return TRUE; 468
477 } 469 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
 470 char *b = bmake_malloc(lf->len + 1);
 471 b[lf->len] = '\n';
 472 memcpy(b, lf->buf, lf->len++);
 473 munmap(lf->buf, lf->maplen);
 474 lf->maplen = 0;
 475 lf->buf = b;
478 } 476 }
479 return FALSE; 477
 478 return TRUE;
480} 479}
 480/* deleteme */
 481/* deleteme */
481 482
482/* 483/*
483 * Read in a file. 484 * Read in a file.
484 * 485 *
485 * Until the path search logic can be moved under here instead of 486 * Until the path search logic can be moved under here instead of
486 * being in the caller in another source file, we need to have the fd 487 * being in the caller in another source file, we need to have the fd
487 * passed in already open. Bleh. 488 * passed in already open. Bleh.
488 * 489 *
489 * If the path is NULL use stdin and (to insure against fd leaks) 490 * If the path is NULL, use stdin.
490 * assert that the caller passed in -1. 
491 */ 491 */
492static struct loadedfile * 492static struct loadedfile *
493loadfile(const char *path, int fd) 493loadfile(const char *path, int fd)
494{ 494{
495 struct loadedfile *lf; 495 struct loadedfile *lf;
496 ssize_t result; 496 ssize_t result;
497 size_t bufpos; 497 size_t bufpos;
498 498
499 lf = loadedfile_create(path); 499 lf = loadedfile_create(path);
500 500
501 if (path == NULL) { 501 if (path == NULL) {
502 assert(fd == -1); 502 assert(fd == -1);
503 fd = STDIN_FILENO; 503 fd = STDIN_FILENO;
@@ -529,47 +529,47 @@ loadfile(const char *path, int fd) @@ -529,47 +529,47 @@ loadfile(const char *path, int fd)
529 errno = EFBIG; 529 errno = EFBIG;
530 Error("%s: file too large", path); 530 Error("%s: file too large", path);
531 exit(1); 531 exit(1);
532 } 532 }
533 lf->len *= 2; 533 lf->len *= 2;
534 lf->buf = bmake_realloc(lf->buf, lf->len); 534 lf->buf = bmake_realloc(lf->buf, lf->len);
535 } 535 }
536 assert(bufpos < lf->len); 536 assert(bufpos < lf->len);
537 result = read(fd, lf->buf + bufpos, lf->len - bufpos); 537 result = read(fd, lf->buf + bufpos, lf->len - bufpos);
538 if (result < 0) { 538 if (result < 0) {
539 Error("%s: read error: %s", path, strerror(errno)); 539 Error("%s: read error: %s", path, strerror(errno));
540 exit(1); 540 exit(1);
541 } 541 }
542 if (result == 0) { 542 if (result == 0)
543 break; 543 break;
544 } 544
545 bufpos += (size_t)result; 545 bufpos += (size_t)result;
546 } 546 }
547 assert(bufpos <= lf->len); 547 assert(bufpos <= lf->len);
548 lf->len = bufpos; 548 lf->len = bufpos;
549 549
550 /* truncate malloc region to actual length (maybe not useful) */ 550 /* truncate malloc region to actual length (maybe not useful) */
551 if (lf->len > 0) { 551 if (lf->len > 0) {
552 /* as for mmap case, ensure trailing \n */ 552 /* as for mmap case, ensure trailing \n */
553 if (lf->buf[lf->len - 1] != '\n') 553 if (lf->buf[lf->len - 1] != '\n')
554 lf->len++; 554 lf->len++;
555 lf->buf = bmake_realloc(lf->buf, lf->len); 555 lf->buf = bmake_realloc(lf->buf, lf->len);
556 lf->buf[lf->len - 1] = '\n'; 556 lf->buf[lf->len - 1] = '\n';
557 } 557 }
558 558
559done: 559done:
560 if (path != NULL) { 560 if (path != NULL)
561 close(fd); 561 close(fd);
562 } 562
563 return lf; 563 return lf;
564} 564}
565 565
566/* old code */ 566/* old code */
567 567
568/* Check if the current character is escaped on the current line. */ 568/* Check if the current character is escaped on the current line. */
569static Boolean 569static Boolean
570ParseIsEscaped(const char *line, const char *c) 570ParseIsEscaped(const char *line, const char *c)
571{ 571{
572 Boolean active = FALSE; 572 Boolean active = FALSE;
573 for (;;) { 573 for (;;) {
574 if (line == c) 574 if (line == c)
575 return active; 575 return active;
@@ -584,46 +584,46 @@ ParseIsEscaped(const char *line, const c @@ -584,46 +584,46 @@ ParseIsEscaped(const char *line, const c
584static void 584static void
585ParseMark(GNode *gn) 585ParseMark(GNode *gn)
586{ 586{
587 IFile *curFile = CurFile(); 587 IFile *curFile = CurFile();
588 gn->fname = curFile->fname; 588 gn->fname = curFile->fname;
589 gn->lineno = curFile->lineno; 589 gn->lineno = curFile->lineno;
590} 590}
591 591
592/* Look in the table of keywords for one matching the given string. 592/* Look in the table of keywords for one matching the given string.
593 * Return the index of the keyword, or -1 if it isn't there. */ 593 * Return the index of the keyword, or -1 if it isn't there. */
594static int 594static int
595ParseFindKeyword(const char *str) 595ParseFindKeyword(const char *str)
596{ 596{
597 int start, end, cur; 597 int start = 0;
598 int diff; 598 int end = sizeof parseKeywords / sizeof parseKeywords[0] - 1;
599 
600 start = 0; 
601 end = sizeof parseKeywords / sizeof parseKeywords[0] - 1; 
602 599
603 do { 600 do {
604 cur = start + (end - start) / 2; 601 int cur = start + (end - start) / 2;
605 diff = strcmp(str, parseKeywords[cur].name); 602 int diff = strcmp(str, parseKeywords[cur].name);
606 603
607 if (diff == 0) { 604 if (diff == 0)
608 return cur; 605 return cur;
609 } else if (diff < 0) { 606 if (diff < 0)
610 end = cur - 1; 607 end = cur - 1;
611 } else { 608 else
612 start = cur + 1; 609 start = cur + 1;
613 } 
614 } while (start <= end); 610 } while (start <= end);
 611
615 return -1; 612 return -1;
616} 613}
 614/* deleteme */
 615/* deleteme */
 616/* deleteme */
617 617
618static void 618static void
619PrintLocation(FILE *f, const char *filename, size_t lineno) 619PrintLocation(FILE *f, const char *filename, size_t lineno)
620{ 620{
621 char dirbuf[MAXPATHLEN+1]; 621 char dirbuf[MAXPATHLEN+1];
622 const char *dir, *base; 622 const char *dir, *base;
623 void *dir_freeIt, *base_freeIt; 623 void *dir_freeIt, *base_freeIt;
624 624
625 if (*filename == '/' || strcmp(filename, "(stdin)") == 0) { 625 if (*filename == '/' || strcmp(filename, "(stdin)") == 0) {
626 (void)fprintf(f, "\"%s\" line %zu: ", filename, lineno); 626 (void)fprintf(f, "\"%s\" line %zu: ", filename, lineno);
627 return; 627 return;
628 } 628 }
629 629
@@ -961,32 +961,32 @@ ParseDoSrcOther(const char *src, GNodeTy @@ -961,32 +961,32 @@ ParseDoSrcOther(const char *src, GNodeTy
961 * from a special target or link it to its parents, as 961 * from a special target or link it to its parents, as
962 * appropriate. 962 * appropriate.
963 * 963 *
964 * In the case of a source that was the object of a :: operator, 964 * In the case of a source that was the object of a :: operator,
965 * the attribute is applied to all of its instances (as kept in 965 * the attribute is applied to all of its instances (as kept in
966 * the 'cohorts' list of the node) or all the cohorts are linked 966 * the 'cohorts' list of the node) or all the cohorts are linked
967 * to all the targets. 967 * to all the targets.
968 */ 968 */
969 969
970 /* Find/create the 'src' node and attach to all targets */ 970 /* Find/create the 'src' node and attach to all targets */
971 gn = Targ_GetNode(src); 971 gn = Targ_GetNode(src);
972 if (doing_depend) 972 if (doing_depend)
973 ParseMark(gn); 973 ParseMark(gn);
974 if (tOp) { 974 if (tOp)
975 gn->type |= tOp; 975 gn->type |= tOp;
976 } else { 976 else
977 LinkToTargets(gn, specType != SP_NOT); 977 LinkToTargets(gn, specType != SP_NOT);
978 } 
979} 978}
 979/* deleteme */
980 980
981/* Given the name of a source in a dependency line, figure out if it is an 981/* Given the name of a source in a dependency line, figure out if it is an
982 * attribute (such as .SILENT) and apply it to the targets if it is. Else 982 * attribute (such as .SILENT) and apply it to the targets if it is. Else
983 * decide if there is some attribute which should be applied *to* the source 983 * decide if there is some attribute which should be applied *to* the source
984 * because of some special target (such as .PHONY) and apply it if so. 984 * because of some special target (such as .PHONY) and apply it if so.
985 * Otherwise, make the source a child of the targets in the list 'targets'. 985 * Otherwise, make the source a child of the targets in the list 'targets'.
986 * 986 *
987 * Input: 987 * Input:
988 * tOp operator (if any) from special targets 988 * tOp operator (if any) from special targets
989 * src name of the source to handle 989 * src name of the source to handle
990 */ 990 */
991static void 991static void
992ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType) 992ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType)
@@ -1114,36 +1114,36 @@ ParseDependencyTargetWord(/*const*/ char @@ -1114,36 +1114,36 @@ ParseDependencyTargetWord(/*const*/ char
1114 * .INTERRUPT Are not to be considered the 1114 * .INTERRUPT Are not to be considered the
1115 * main target. 1115 * main target.
1116 * .NOTPARALLEL Make only one target at a time. 1116 * .NOTPARALLEL Make only one target at a time.
1117 * .SINGLESHELL Create a shell for each command. 1117 * .SINGLESHELL Create a shell for each command.
1118 * .ORDER Must set initial predecessor to NULL 1118 * .ORDER Must set initial predecessor to NULL
1119 */ 1119 */
1120static void 1120static void
1121ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType, 1121ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType,
1122 const char *line, 1122 const char *line,
1123 SearchPathList **inout_paths) 1123 SearchPathList **inout_paths)
1124{ 1124{
1125 switch (*inout_specType) { 1125 switch (*inout_specType) {
1126 case SP_PATH: 1126 case SP_PATH:
1127 if (*inout_paths == NULL) { 1127 if (*inout_paths == NULL)
1128 *inout_paths = Lst_New(); 1128 *inout_paths = Lst_New();
1129 } 
1130 Lst_Append(*inout_paths, dirSearchPath); 1129 Lst_Append(*inout_paths, dirSearchPath);
1131 break; 1130 break;
 1131/* deleteme */
1132 case SP_MAIN: 1132 case SP_MAIN:
1133 if (!Lst_IsEmpty(opts.create)) { 1133 if (!Lst_IsEmpty(opts.create))
1134 *inout_specType = SP_NOT; 1134 *inout_specType = SP_NOT;
1135 } 
1136 break; 1135 break;
 1136/* deleteme */
1137 case SP_BEGIN: 1137 case SP_BEGIN:
1138 case SP_END: 1138 case SP_END:
1139 case SP_STALE: 1139 case SP_STALE:
1140 case SP_ERROR: 1140 case SP_ERROR:
1141 case SP_INTERRUPT: { 1141 case SP_INTERRUPT: {
1142 GNode *gn = Targ_GetNode(line); 1142 GNode *gn = Targ_GetNode(line);
1143 if (doing_depend) 1143 if (doing_depend)
1144 ParseMark(gn); 1144 ParseMark(gn);
1145 gn->type |= OP_NOTMAIN|OP_SPECIAL; 1145 gn->type |= OP_NOTMAIN|OP_SPECIAL;
1146 Lst_Append(targets, gn); 1146 Lst_Append(targets, gn);
1147 break; 1147 break;
1148 } 1148 }
1149 case SP_DEFAULT: { 1149 case SP_DEFAULT: {
@@ -1175,32 +1175,32 @@ ParseDoDependencyTargetSpecial(ParseSpec @@ -1175,32 +1175,32 @@ ParseDoDependencyTargetSpecial(ParseSpec
1175 * Call on the suffix module to give us a path to modify. 1175 * Call on the suffix module to give us a path to modify.
1176 */ 1176 */
1177static Boolean 1177static Boolean
1178ParseDoDependencyTargetPath(const char *line, SearchPathList **inout_paths) 1178ParseDoDependencyTargetPath(const char *line, SearchPathList **inout_paths)
1179{ 1179{
1180 SearchPath *path; 1180 SearchPath *path;
1181 1181
1182 path = Suff_GetPath(&line[5]); 1182 path = Suff_GetPath(&line[5]);
1183 if (path == NULL) { 1183 if (path == NULL) {
1184 Parse_Error(PARSE_FATAL, 1184 Parse_Error(PARSE_FATAL,
1185 "Suffix '%s' not defined (yet)", 1185 "Suffix '%s' not defined (yet)",
1186 &line[5]); 1186 &line[5]);
1187 return FALSE; 1187 return FALSE;
1188 } else { 
1189 if (*inout_paths == NULL) { 
1190 *inout_paths = Lst_New(); 
1191 } 
1192 Lst_Append(*inout_paths, path); 
1193 } 1188 }
 1189
 1190 if (*inout_paths == NULL)
 1191 *inout_paths = Lst_New();
 1192 Lst_Append(*inout_paths, path);
 1193
1194 return TRUE; 1194 return TRUE;
1195} 1195}
1196 1196
1197/* 1197/*
1198 * See if it's a special target and if so set specType to match it. 1198 * See if it's a special target and if so set specType to match it.
1199 */ 1199 */
1200static Boolean 1200static Boolean
1201ParseDoDependencyTarget(const char *line, ParseSpecial *inout_specType, 1201ParseDoDependencyTarget(const char *line, ParseSpecial *inout_specType,
1202 GNodeType *out_tOp, SearchPathList **inout_paths) 1202 GNodeType *out_tOp, SearchPathList **inout_paths)
1203{ 1203{
1204 int keywd; 1204 int keywd;
1205 1205
1206 if (!(*line == '.' && ch_isupper(line[1]))) 1206 if (!(*line == '.' && ch_isupper(line[1])))
@@ -1263,39 +1263,39 @@ ParseDoDependencyTargetMundane(char *lin @@ -1263,39 +1263,39 @@ ParseDoDependencyTargetMundane(char *lin
1263 if (doing_depend) 1263 if (doing_depend)
1264 ParseMark(gn); 1264 ParseMark(gn);
1265 1265
1266 Lst_Append(targets, gn); 1266 Lst_Append(targets, gn);
1267 } 1267 }
1268} 1268}
1269 1269
1270static void 1270static void
1271ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart) 1271ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart)
1272{ 1272{
1273 Boolean warning = FALSE; 1273 Boolean warning = FALSE;
1274 char *cp = *pp; 1274 char *cp = *pp;
1275 1275
1276 while (*cp && (ParseIsEscaped(lstart, cp) || 1276 while (*cp != '\0') {
1277 (*cp != '!' && *cp != ':'))) { 1277 if (!ParseIsEscaped(lstart, cp) && (*cp == '!' || *cp == ':'))
1278 if (ParseIsEscaped(lstart, cp) || 1278 break;
1279 (*cp != ' ' && *cp != '\t')) { 1279 if (ParseIsEscaped(lstart, cp) || (*cp != ' ' && *cp != '\t'))
1280 warning = TRUE; 1280 warning = TRUE;
1281 } 
1282 cp++; 1281 cp++;
1283 } 1282 }
1284 if (warning) { 1283 if (warning)
1285 Parse_Error(PARSE_WARNING, "Extra target ignored"); 1284 Parse_Error(PARSE_WARNING, "Extra target ignored");
1286 } 1285
1287 *pp = cp; 1286 *pp = cp;
1288} 1287}
 1288/* deleteme */
1289 1289
1290static void 1290static void
1291ParseDoDependencyCheckSpec(ParseSpecial specType) 1291ParseDoDependencyCheckSpec(ParseSpecial specType)
1292{ 1292{
1293 switch (specType) { 1293 switch (specType) {
1294 default: 1294 default:
1295 Parse_Error(PARSE_WARNING, 1295 Parse_Error(PARSE_WARNING,
1296 "Special and mundane targets don't mix. Mundane ones ignored"); 1296 "Special and mundane targets don't mix. Mundane ones ignored");
1297 break; 1297 break;
1298 case SP_DEFAULT: 1298 case SP_DEFAULT:
1299 case SP_STALE: 1299 case SP_STALE:
1300 case SP_BEGIN: 1300 case SP_BEGIN:
1301 case SP_END: 1301 case SP_END:
@@ -1505,81 +1505,81 @@ ParseDoDependencyTargets(char **inout_cp @@ -1505,81 +1505,81 @@ ParseDoDependencyTargets(char **inout_cp
1505 1505
1506 /* Insert a null terminator. */ 1506 /* Insert a null terminator. */
1507 savec = *cp; 1507 savec = *cp;
1508 *cp = '\0'; 1508 *cp = '\0';
1509 1509
1510 if (!ParseDoDependencyTarget(line, inout_specType, inout_tOp, 1510 if (!ParseDoDependencyTarget(line, inout_specType, inout_tOp,
1511 inout_paths)) 1511 inout_paths))
1512 return FALSE; 1512 return FALSE;
1513 1513
1514 /* 1514 /*
1515 * Have word in line. Get or create its node and stick it at 1515 * Have word in line. Get or create its node and stick it at
1516 * the end of the targets list 1516 * the end of the targets list
1517 */ 1517 */
1518 if (*inout_specType == SP_NOT && *line != '\0') { 1518 if (*inout_specType == SP_NOT && *line != '\0')
1519 ParseDoDependencyTargetMundane(line, curTargs); 1519 ParseDoDependencyTargetMundane(line, curTargs);
1520 } else if (*inout_specType == SP_PATH && *line != '.' && *line != '\0') { 1520 else if (*inout_specType == SP_PATH && *line != '.' && *line != '\0')
1521 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 1521 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1522 } 
1523 1522
1524 /* Don't need the inserted null terminator any more. */ 1523 /* Don't need the inserted null terminator any more. */
1525 *cp = savec; 1524 *cp = savec;
1526 1525
1527 /* 1526 /*
1528 * If it is a special type and not .PATH, it's the only target we 1527 * If it is a special type and not .PATH, it's the only target we
1529 * allow on this line... 1528 * allow on this line...
1530 */ 1529 */
1531 if (*inout_specType != SP_NOT && *inout_specType != SP_PATH) { 1530 if (*inout_specType != SP_NOT && *inout_specType != SP_PATH)
1532 ParseDoDependencyTargetExtraWarn(&cp, lstart); 1531 ParseDoDependencyTargetExtraWarn(&cp, lstart);
1533 } else { 1532 else
1534 pp_skip_whitespace(&cp); 1533 pp_skip_whitespace(&cp);
1535 } 1534
1536 line = cp; 1535 line = cp;
1537 if (*line == '\0') 1536 if (*line == '\0')
1538 break; 1537 break;
1539 if ((*line == '!' || *line == ':') && !ParseIsEscaped(lstart, line)) 1538 if ((*line == '!' || *line == ':') && !ParseIsEscaped(lstart, line))
1540 break; 1539 break;
1541 } 1540 }
1542 1541
1543 *inout_cp = cp; 1542 *inout_cp = cp;
1544 *inout_line = line; 1543 *inout_line = line;
1545 return TRUE; 1544 return TRUE;
1546} 1545}
 1546/* deleteme */
1547 1547
1548static void 1548static void
1549ParseDoDependencySourcesSpecial(char *start, char *end, 1549ParseDoDependencySourcesSpecial(char *start, char *end,
1550 ParseSpecial specType, SearchPathList *paths) 1550 ParseSpecial specType, SearchPathList *paths)
1551{ 1551{
1552 char savec; 1552 char savec;
1553 1553
1554 while (*start) { 1554 while (*start) {
1555 while (*end && !ch_isspace(*end)) 1555 while (*end && !ch_isspace(*end))
1556 end++; 1556 end++;
1557 savec = *end; 1557 savec = *end;
1558 *end = '\0'; 1558 *end = '\0';
1559 ParseDoDependencySourceSpecial(specType, start, paths); 1559 ParseDoDependencySourceSpecial(specType, start, paths);
1560 *end = savec; 1560 *end = savec;
1561 if (savec != '\0') 1561 if (savec != '\0')
1562 end++; 1562 end++;
1563 pp_skip_whitespace(&end); 1563 pp_skip_whitespace(&end);
1564 start = end; 1564 start = end;
1565 } 1565 }
1566} 1566}
1567 1567
1568static Boolean 1568static Boolean
1569ParseDoDependencySourcesMundane(char *start, char *end, 1569ParseDoDependencySourcesMundane(char *start, char *end,
1570 ParseSpecial specType, GNodeType tOp) 1570 ParseSpecial specType, GNodeType tOp)
1571{ 1571{
1572 while (*start) { 1572 while (*start != '\0') {
1573 /* 1573 /*
1574 * The targets take real sources, so we must beware of archive 1574 * The targets take real sources, so we must beware of archive
1575 * specifications (i.e. things with left parentheses in them) 1575 * specifications (i.e. things with left parentheses in them)
1576 * and handle them accordingly. 1576 * and handle them accordingly.
1577 */ 1577 */
1578 for (; *end && !ch_isspace(*end); end++) { 1578 for (; *end && !ch_isspace(*end); end++) {
1579 if (*end == '(' && end > start && end[-1] != '$') { 1579 if (*end == '(' && end > start && end[-1] != '$') {
1580 /* 1580 /*
1581 * Only stop for a left parenthesis if it isn't at the 1581 * Only stop for a left parenthesis if it isn't at the
1582 * start of a word (that'll be for variable changes 1582 * start of a word (that'll be for variable changes
1583 * later) and isn't preceded by a dollar sign (a dynamic 1583 * later) and isn't preceded by a dollar sign (a dynamic
1584 * source). 1584 * source).
1585 */ 1585 */
@@ -1978,33 +1978,33 @@ VarAssign_EvalShell(const char *name, co @@ -1978,33 +1978,33 @@ VarAssign_EvalShell(const char *name, co
1978 * The actual value of the variable is returned in *out_avalue and 1978 * The actual value of the variable is returned in *out_avalue and
1979 * *out_avalue_freeIt. Especially for VAR_SUBST and VAR_SHELL this can differ 1979 * *out_avalue_freeIt. Especially for VAR_SUBST and VAR_SHELL this can differ
1980 * from the literal value. 1980 * from the literal value.
1981 * 1981 *
1982 * Return whether the assignment was actually done. The assignment is only 1982 * Return whether the assignment was actually done. The assignment is only
1983 * skipped if the operator is '?=' and the variable already exists. */ 1983 * skipped if the operator is '?=' and the variable already exists. */
1984static Boolean 1984static Boolean
1985VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue, 1985VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
1986 GNode *ctxt, const char **out_avalue, void **out_avalue_freeIt) 1986 GNode *ctxt, const char **out_avalue, void **out_avalue_freeIt)
1987{ 1987{
1988 const char *avalue = uvalue; 1988 const char *avalue = uvalue;
1989 void *avalue_freeIt = NULL; 1989 void *avalue_freeIt = NULL;
1990 1990
1991 if (op == VAR_APPEND) { 1991 if (op == VAR_APPEND)
1992 Var_Append(name, uvalue, ctxt); 1992 Var_Append(name, uvalue, ctxt);
1993 } else if (op == VAR_SUBST) { 1993 else if (op == VAR_SUBST)
1994 VarAssign_EvalSubst(name, uvalue, ctxt, &avalue, &avalue_freeIt); 1994 VarAssign_EvalSubst(name, uvalue, ctxt, &avalue, &avalue_freeIt);
1995 } else if (op == VAR_SHELL) { 1995 else if (op == VAR_SHELL)
1996 VarAssign_EvalShell(name, uvalue, ctxt, &avalue, &avalue_freeIt); 1996 VarAssign_EvalShell(name, uvalue, ctxt, &avalue, &avalue_freeIt);
1997 } else { 1997 else {
1998 if (op == VAR_DEFAULT && Var_Exists(name, ctxt)) { 1998 if (op == VAR_DEFAULT && Var_Exists(name, ctxt)) {
1999 *out_avalue_freeIt = NULL; 1999 *out_avalue_freeIt = NULL;
2000 return FALSE; 2000 return FALSE;
2001 } 2001 }
2002 2002
2003 /* Normal assignment -- just do it. */ 2003 /* Normal assignment -- just do it. */
2004 Var_Set(name, uvalue, ctxt); 2004 Var_Set(name, uvalue, ctxt);
2005 } 2005 }
2006 2006
2007 *out_avalue = avalue; 2007 *out_avalue = avalue;
2008 *out_avalue_freeIt = avalue_freeIt; 2008 *out_avalue_freeIt = avalue_freeIt;
2009 return TRUE; 2009 return TRUE;
2010} 2010}
@@ -2012,32 +2012,32 @@ VarAssign_Eval(const char *name, VarAssi @@ -2012,32 +2012,32 @@ VarAssign_Eval(const char *name, VarAssi
2012static void 2012static void
2013VarAssignSpecial(const char *name, const char *avalue) 2013VarAssignSpecial(const char *name, const char *avalue)
2014{ 2014{
2015 if (strcmp(name, MAKEOVERRIDES) == 0) 2015 if (strcmp(name, MAKEOVERRIDES) == 0)
2016 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */ 2016 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */
2017 else if (strcmp(name, ".CURDIR") == 0) { 2017 else if (strcmp(name, ".CURDIR") == 0) {
2018 /* 2018 /*
2019 * Someone is being (too?) clever... 2019 * Someone is being (too?) clever...
2020 * Let's pretend they know what they are doing and 2020 * Let's pretend they know what they are doing and
2021 * re-initialize the 'cur' CachedDir. 2021 * re-initialize the 'cur' CachedDir.
2022 */ 2022 */
2023 Dir_InitCur(avalue); 2023 Dir_InitCur(avalue);
2024 Dir_SetPATH(); 2024 Dir_SetPATH();
2025 } else if (strcmp(name, MAKE_JOB_PREFIX) == 0) { 2025 } else if (strcmp(name, MAKE_JOB_PREFIX) == 0)
2026 Job_SetPrefix(); 2026 Job_SetPrefix();
2027 } else if (strcmp(name, MAKE_EXPORTED) == 0) { 2027 else if (strcmp(name, MAKE_EXPORTED) == 0)
2028 Var_Export(avalue, FALSE); 2028 Var_Export(avalue, FALSE);
2029 } 
2030} 2029}
 2030/* deleteme */
2031 2031
2032/* Perform the variable variable assignment in the given context. */ 2032/* Perform the variable variable assignment in the given context. */
2033void 2033void
2034Parse_DoVar(VarAssign *var, GNode *ctxt) 2034Parse_DoVar(VarAssign *var, GNode *ctxt)
2035{ 2035{
2036 const char *avalue; /* actual value (maybe expanded) */ 2036 const char *avalue; /* actual value (maybe expanded) */
2037 void *avalue_freeIt; 2037 void *avalue_freeIt;
2038 2038
2039 VarCheckSyntax(var->op, var->value, ctxt); 2039 VarCheckSyntax(var->op, var->value, ctxt);
2040 if (VarAssign_Eval(var->varname, var->op, var->value, ctxt, 2040 if (VarAssign_Eval(var->varname, var->op, var->value, ctxt,
2041 &avalue, &avalue_freeIt)) 2041 &avalue, &avalue_freeIt))
2042 VarAssignSpecial(var->varname, avalue); 2042 VarAssignSpecial(var->varname, avalue);
2043 2043
@@ -2178,35 +2178,33 @@ Parse_include_file(char *file, Boolean i @@ -2178,35 +2178,33 @@ Parse_include_file(char *file, Boolean i
2178 2178
2179 if (fullname == NULL) { 2179 if (fullname == NULL) {
2180 /* 2180 /*
2181 * Makefile wasn't found in same directory as included makefile. 2181 * Makefile wasn't found in same directory as included makefile.
2182 * Search for it first on the -I search path, 2182 * Search for it first on the -I search path,
2183 * then on the .PATH search path, if not found in a -I directory. 2183 * then on the .PATH search path, if not found in a -I directory.
2184 * If we have a suffix specific path we should use that. 2184 * If we have a suffix specific path we should use that.
2185 */ 2185 */
2186 char *suff; 2186 char *suff;
2187 SearchPath *suffPath = NULL; 2187 SearchPath *suffPath = NULL;
2188 2188
2189 if ((suff = strrchr(file, '.'))) { 2189 if ((suff = strrchr(file, '.'))) {
2190 suffPath = Suff_GetPath(suff); 2190 suffPath = Suff_GetPath(suff);
2191 if (suffPath != NULL) { 2191 if (suffPath != NULL)
2192 fullname = Dir_FindFile(file, suffPath); 2192 fullname = Dir_FindFile(file, suffPath);
2193 } 
2194 } 2193 }
2195 if (fullname == NULL) { 2194 if (fullname == NULL) {
2196 fullname = Dir_FindFile(file, parseIncPath); 2195 fullname = Dir_FindFile(file, parseIncPath);
2197 if (fullname == NULL) { 2196 if (fullname == NULL)
2198 fullname = Dir_FindFile(file, dirSearchPath); 2197 fullname = Dir_FindFile(file, dirSearchPath);
2199 } 
2200 } 2198 }
2201 } 2199 }
2202 } 2200 }
2203 2201
2204 /* Looking for a system file or file still not found */ 2202 /* Looking for a system file or file still not found */
2205 if (fullname == NULL) { 2203 if (fullname == NULL) {
2206 /* 2204 /*
2207 * Look for it on the system path 2205 * Look for it on the system path
2208 */ 2206 */
2209 SearchPath *path = Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath; 2207 SearchPath *path = Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath;
2210 fullname = Dir_FindFile(file, path); 2208 fullname = Dir_FindFile(file, path);
2211 } 2209 }
2212 2210
@@ -2224,65 +2222,67 @@ Parse_include_file(char *file, Boolean i @@ -2224,65 +2222,67 @@ Parse_include_file(char *file, Boolean i
2224 free(fullname); 2222 free(fullname);
2225 return; 2223 return;
2226 } 2224 }
2227 2225
2228 /* load it */ 2226 /* load it */
2229 lf = loadfile(fullname, fd); 2227 lf = loadfile(fullname, fd);
2230 2228
2231 /* Start reading from this file next */ 2229 /* Start reading from this file next */
2232 Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf); 2230 Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
2233 CurFile()->lf = lf; 2231 CurFile()->lf = lf;
2234 if (depinc) 2232 if (depinc)
2235 doing_depend = depinc; /* only turn it on */ 2233 doing_depend = depinc; /* only turn it on */
2236} 2234}
 2235/* deleteme */
 2236/* deleteme */
2237 2237
2238static void 2238static void
2239ParseDoInclude(char *line) 2239ParseDoInclude(char *line)
2240{ 2240{
2241 char endc; /* the character which ends the file spec */ 2241 char endc; /* the character which ends the file spec */
2242 char *cp; /* current position in file spec */ 2242 char *cp; /* current position in file spec */
2243 int silent = *line != 'i'; 2243 int silent = *line != 'i';
2244 char *file = line + (silent ? 8 : 7); 2244 char *file = line + (silent ? 8 : 7);
2245 2245
2246 /* Skip to delimiter character so we know where to look */ 2246 /* Skip to delimiter character so we know where to look */
2247 pp_skip_hspace(&file); 2247 pp_skip_hspace(&file);
2248 2248
2249 if (*file != '"' && *file != '<') { 2249 if (*file != '"' && *file != '<') {
2250 Parse_Error(PARSE_FATAL, 2250 Parse_Error(PARSE_FATAL,
2251 ".include filename must be delimited by '\"' or '<'"); 2251 ".include filename must be delimited by '\"' or '<'");
2252 return; 2252 return;
2253 } 2253 }
2254 2254
2255 /* 2255 /*
2256 * Set the search path on which to find the include file based on the 2256 * Set the search path on which to find the include file based on the
2257 * characters which bracket its name. Angle-brackets imply it's 2257 * characters which bracket its name. Angle-brackets imply it's
2258 * a system Makefile while double-quotes imply it's a user makefile 2258 * a system Makefile while double-quotes imply it's a user makefile
2259 */ 2259 */
2260 if (*file == '<') { 2260 if (*file == '<')
2261 endc = '>'; 2261 endc = '>';
2262 } else { 2262 else
2263 endc = '"'; 2263 endc = '"';
2264 } 
2265 2264
2266 /* Skip to matching delimiter */ 2265 /* Skip to matching delimiter */
2267 for (cp = ++file; *cp && *cp != endc; cp++) 2266 for (cp = ++file; *cp && *cp != endc; cp++)
2268 continue; 2267 continue;
2269 2268
2270 if (*cp != endc) { 2269 if (*cp != endc) {
2271 Parse_Error(PARSE_FATAL, 2270 Parse_Error(PARSE_FATAL,
2272 "Unclosed %cinclude filename. '%c' expected", 2271 "Unclosed %cinclude filename. '%c' expected",
2273 '.', endc); 2272 '.', endc);
2274 return; 2273 return;
2275 } 2274 }
 2275
2276 *cp = '\0'; 2276 *cp = '\0';
2277 2277
2278 /* 2278 /*
2279 * Substitute for any variables in the file name before trying to 2279 * Substitute for any variables in the file name before trying to
2280 * find the thing. 2280 * find the thing.
2281 */ 2281 */
2282 (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &file); 2282 (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &file);
2283 /* TODO: handle errors */ 2283 /* TODO: handle errors */
2284 2284
2285 Parse_include_file(file, endc == '>', *line == 'd', silent); 2285 Parse_include_file(file, endc == '>', *line == 'd', silent);
2286 free(file); 2286 free(file);
2287} 2287}
2288 2288
@@ -2472,34 +2472,34 @@ IsInclude(const char *dir, Boolean sysv) @@ -2472,34 +2472,34 @@ IsInclude(const char *dir, Boolean sysv)
2472 2472
2473#ifdef SYSVINCLUDE 2473#ifdef SYSVINCLUDE
2474/* Check if the line is a SYSV include directive. */ 2474/* Check if the line is a SYSV include directive. */
2475static Boolean 2475static Boolean
2476IsSysVInclude(const char *line) 2476IsSysVInclude(const char *line)
2477{ 2477{
2478 const char *p; 2478 const char *p;
2479 2479
2480 if (!IsInclude(line, TRUE)) 2480 if (!IsInclude(line, TRUE))
2481 return FALSE; 2481 return FALSE;
2482 2482
2483 /* Avoid interpreting a dependency line as an include */ 2483 /* Avoid interpreting a dependency line as an include */
2484 for (p = line; (p = strchr(p, ':')) != NULL;) { 2484 for (p = line; (p = strchr(p, ':')) != NULL;) {
2485 if (*++p == '\0') { 2485
2486 /* end of line -> dependency */ 2486 /* end of line -> it's a dependency */
 2487 if (*++p == '\0')
2487 return FALSE; 2488 return FALSE;
2488 } 2489
2489 if (*p == ':' || ch_isspace(*p)) { 2490 /* '::' operator or ': ' -> it's a dependency */
2490 /* :: operator or ': ' -> dependency */ 2491 if (*p == ':' || ch_isspace(*p))
2491 return FALSE; 2492 return FALSE;
2492 } 
2493 } 2493 }
2494 return TRUE; 2494 return TRUE;
2495} 2495}
2496 2496
2497/* Push to another file. The line points to the word "include". */ 2497/* Push to another file. The line points to the word "include". */
2498static void 2498static void
2499ParseTraditionalInclude(char *line) 2499ParseTraditionalInclude(char *line)
2500{ 2500{
2501 char *cp; /* current position in file spec */ 2501 char *cp; /* current position in file spec */
2502 Boolean done = FALSE; 2502 Boolean done = FALSE;
2503 int silent = line[0] != 'i'; 2503 int silent = line[0] != 'i';
2504 char *file = line + (silent ? 8 : 7); 2504 char *file = line + (silent ? 8 : 7);
2505 char *all_files; 2505 char *all_files;
@@ -2584,30 +2584,28 @@ ParseEOF(void) @@ -2584,30 +2584,28 @@ ParseEOF(void)
2584 char *ptr; 2584 char *ptr;
2585 size_t len; 2585 size_t len;
2586 IFile *curFile = CurFile(); 2586 IFile *curFile = CurFile();
2587 2587
2588 assert(curFile->nextbuf != NULL); 2588 assert(curFile->nextbuf != NULL);
2589 2589
2590 doing_depend = curFile->depending; /* restore this */ 2590 doing_depend = curFile->depending; /* restore this */
2591 /* get next input buffer, if any */ 2591 /* get next input buffer, if any */
2592 ptr = curFile->nextbuf(curFile->nextbuf_arg, &len); 2592 ptr = curFile->nextbuf(curFile->nextbuf_arg, &len);
2593 curFile->buf_ptr = ptr; 2593 curFile->buf_ptr = ptr;
2594 curFile->buf_freeIt = ptr; 2594 curFile->buf_freeIt = ptr;
2595 curFile->buf_end = ptr + len; 2595 curFile->buf_end = ptr + len;
2596 curFile->lineno = curFile->first_lineno; 2596 curFile->lineno = curFile->first_lineno;
2597 if (ptr != NULL) { 2597 if (ptr != NULL)
2598 /* Iterate again */ 2598 return TRUE; /* Iterate again */
2599 return TRUE; 
2600 } 
2601 2599
2602 /* Ensure the makefile (or loop) didn't have mismatched conditionals */ 2600 /* Ensure the makefile (or loop) didn't have mismatched conditionals */
2603 Cond_restore_depth(curFile->cond_depth); 2601 Cond_restore_depth(curFile->cond_depth);
2604 2602
2605 if (curFile->lf != NULL) { 2603 if (curFile->lf != NULL) {
2606 loadedfile_destroy(curFile->lf); 2604 loadedfile_destroy(curFile->lf);
2607 curFile->lf = NULL; 2605 curFile->lf = NULL;
2608 } 2606 }
2609 2607
2610 /* Dispose of curFile info */ 2608 /* Dispose of curFile info */
2611 /* Leak curFile->fname because all the gnodes have pointers to it */ 2609 /* Leak curFile->fname because all the gnodes have pointers to it */
2612 free(curFile->buf_freeIt); 2610 free(curFile->buf_freeIt);
2613 Vector_Pop(&includes); 2611 Vector_Pop(&includes);
@@ -2853,42 +2851,44 @@ ParseReadLine(void) @@ -2853,42 +2851,44 @@ ParseReadLine(void)
2853 } while (For_Accum(line)); 2851 } while (For_Accum(line));
2854 /* Stash each iteration as a new 'input file' */ 2852 /* Stash each iteration as a new 'input file' */
2855 For_Run(lineno); 2853 For_Run(lineno);
2856 /* Read next line from for-loop buffer */ 2854 /* Read next line from for-loop buffer */
2857 continue; 2855 continue;
2858 } 2856 }
2859 return line; 2857 return line;
2860 } 2858 }
2861} 2859}
2862 2860
2863static void 2861static void
2864FinishDependencyGroup(void) 2862FinishDependencyGroup(void)
2865{ 2863{
2866 if (targets != NULL) { 2864 GNodeListNode *ln;
2867 GNodeListNode *ln; 
2868 for (ln = targets->first; ln != NULL; ln = ln->next) { 
2869 GNode *gn = ln->datum; 
2870 2865
2871 Suff_EndTransform(gn); 2866 if (targets == NULL)
 2867 return;
2872 2868
2873 /* Mark the target as already having commands if it does, to 2869 for (ln = targets->first; ln != NULL; ln = ln->next) {
2874 * keep from having shell commands on multiple dependency lines. */ 2870 GNode *gn = ln->datum;
2875 if (!Lst_IsEmpty(gn->commands)) 
2876 gn->type |= OP_HAS_COMMANDS; 
2877 } 
2878 2871
2879 Lst_Free(targets); 2872 Suff_EndTransform(gn);
2880 targets = NULL; 2873
 2874 /* Mark the target as already having commands if it does, to
 2875 * keep from having shell commands on multiple dependency lines. */
 2876 if (!Lst_IsEmpty(gn->commands))
 2877 gn->type |= OP_HAS_COMMANDS;
2881 } 2878 }
 2879
 2880 Lst_Free(targets);
 2881 targets = NULL;
2882} 2882}
2883 2883
2884/* Add the command to each target from the current dependency spec. */ 2884/* Add the command to each target from the current dependency spec. */
2885static void 2885static void
2886ParseLine_ShellCommand(const char *p) 2886ParseLine_ShellCommand(const char *p)
2887{ 2887{
2888 cpp_skip_whitespace(&p); 2888 cpp_skip_whitespace(&p);
2889 if (*p == '\0') 2889 if (*p == '\0')
2890 return; /* skip empty commands */ 2890 return; /* skip empty commands */
2891 2891
2892 if (targets == NULL) { 2892 if (targets == NULL) {
2893 Parse_Error(PARSE_FATAL, "Unassociated shell command \"%s\"", p); 2893 Parse_Error(PARSE_FATAL, "Unassociated shell command \"%s\"", p);
2894 return; 2894 return;
@@ -2950,61 +2950,61 @@ ParseDirective(char *line) @@ -2950,61 +2950,61 @@ ParseDirective(char *line)
2950 strncmp(cp, "error", 5) == 0 || 2950 strncmp(cp, "error", 5) == 0 ||
2951 strncmp(cp, "warning", 7) == 0) { 2951 strncmp(cp, "warning", 7) == 0) {
2952 if (ParseMessage(cp)) 2952 if (ParseMessage(cp))
2953 return TRUE; 2953 return TRUE;
2954 } 2954 }
2955 } 2955 }
2956 return FALSE; 2956 return FALSE;
2957} 2957}
2958 2958
2959static Boolean 2959static Boolean
2960ParseVarassign(const char *line) 2960ParseVarassign(const char *line)
2961{ 2961{
2962 VarAssign var; 2962 VarAssign var;
2963 if (Parse_IsVar(line, &var)) { 2963
2964 FinishDependencyGroup(); 2964 if (!Parse_IsVar(line, &var))
2965 Parse_DoVar(&var, VAR_GLOBAL); 2965 return FALSE;
2966 return TRUE; 2966
2967 } 2967 FinishDependencyGroup();
2968 return FALSE; 2968 Parse_DoVar(&var, VAR_GLOBAL);
 2969 return TRUE;
2969} 2970}
2970 2971
2971static char * 2972static char *
2972FindSemicolon(char *p) 2973FindSemicolon(char *p)
2973{ 2974{
2974 int level = 0; 2975 int level = 0;
2975 2976
2976 for (; *p != '\0'; p++) { 2977 for (; *p != '\0'; p++) {
2977 if (*p == '\\' && p[1] != '\0') { 2978 if (*p == '\\' && p[1] != '\0') {
2978 p++; 2979 p++;
2979 continue; 2980 continue;
2980 } 2981 }
2981 2982
2982 if (*p == '$' && (p[1] == '(' || p[1] == '{')) { 2983 if (*p == '$' && (p[1] == '(' || p[1] == '{'))
2983 level++; 2984 level++;
2984 continue; 2985 else if (level > 0 && (*p == ')' || *p == '}'))
2985 } 
2986 
2987 if (level > 0 && (*p == ')' || *p == '}')) { 
2988 level--; 2986 level--;
2989 continue; 2987 else if (level == 0 && *p == ';')
2990 } 
2991 
2992 if (level == 0 && *p == ';') { 
2993 break; 2988 break;
2994 } 
2995 } 2989 }
2996 return p; 2990 return p;
2997} 2991}
 2992/* deleteme */
 2993/* deleteme */
 2994/* deleteme */
 2995/* deleteme */
 2996/* deleteme */
 2997/* deleteme */
2998 2998
2999/* dependency -> target... op [source...] 2999/* dependency -> target... op [source...]
3000 * op -> ':' | '::' | '!' */ 3000 * op -> ':' | '::' | '!' */
3001static void 3001static void
3002ParseDependency(char *line) 3002ParseDependency(char *line)
3003{ 3003{
3004 VarEvalFlags eflags; 3004 VarEvalFlags eflags;
3005 char *expanded_line; 3005 char *expanded_line;
3006 const char *shellcmd = NULL; 3006 const char *shellcmd = NULL;
3007 3007
3008 /* 3008 /*
3009 * For some reason - probably to make the parser impossible - 3009 * For some reason - probably to make the parser impossible -
3010 * a ';' can be used to separate commands from dependencies. 3010 * a ';' can be used to separate commands from dependencies.
@@ -3133,27 +3133,27 @@ Parse_File(const char *name, int fd) @@ -3133,27 +3133,27 @@ Parse_File(const char *name, int fd)
3133 do { 3133 do {
3134 while ((line = ParseReadLine()) != NULL) { 3134 while ((line = ParseReadLine()) != NULL) {
3135 DEBUG2(PARSE, "ParseReadLine (%d): '%s'\n", 3135 DEBUG2(PARSE, "ParseReadLine (%d): '%s'\n",
3136 CurFile()->lineno, line); 3136 CurFile()->lineno, line);
3137 ParseLine(line); 3137 ParseLine(line);
3138 } 3138 }
3139 /* 3139 /*
3140 * Reached EOF, but it may be just EOF of an include file... 3140 * Reached EOF, but it may be just EOF of an include file...
3141 */ 3141 */
3142 } while (ParseEOF()); 3142 } while (ParseEOF());
3143 3143
3144 FinishDependencyGroup(); 3144 FinishDependencyGroup();
3145 3145
3146 if (fatals) { 3146 if (fatals != 0) {
3147 (void)fflush(stdout); 3147 (void)fflush(stdout);
3148 (void)fprintf(stderr, 3148 (void)fprintf(stderr,
3149 "%s: Fatal errors encountered -- cannot continue", 3149 "%s: Fatal errors encountered -- cannot continue",
3150 progname); 3150 progname);
3151 PrintOnError(NULL, NULL); 3151 PrintOnError(NULL, NULL);
3152 exit(1); 3152 exit(1);
3153 } 3153 }
3154} 3154}
3155 3155
3156/* Initialize the parsing module. */ 3156/* Initialize the parsing module. */
3157void 3157void
3158Parse_Init(void) 3158Parse_Init(void)
3159{ 3159{
@@ -3194,30 +3194,30 @@ Parse_End(void) @@ -3194,30 +3194,30 @@ Parse_End(void)
3194 * 3194 *
3195 * Side Effects: 3195 * Side Effects:
3196 * None. 3196 * None.
3197 * 3197 *
3198 *----------------------------------------------------------------------- 3198 *-----------------------------------------------------------------------
3199 */ 3199 */
3200GNodeList * 3200GNodeList *
3201Parse_MainName(void) 3201Parse_MainName(void)
3202{ 3202{
3203 GNodeList *mainList; 3203 GNodeList *mainList;
3204 3204
3205 mainList = Lst_New(); 3205 mainList = Lst_New();
3206 3206
3207 if (mainNode == NULL) { 3207 if (mainNode == NULL)
3208 Punt("no target to make."); 3208 Punt("no target to make.");
3209 /*NOTREACHED*/ 3209
3210 } else if (mainNode->type & OP_DOUBLEDEP) { 3210 if (mainNode->type & OP_DOUBLEDEP) {
3211 Lst_Append(mainList, mainNode); 3211 Lst_Append(mainList, mainNode);
3212 Lst_AppendAll(mainList, mainNode->cohorts); 3212 Lst_AppendAll(mainList, mainNode->cohorts);
3213 } else 3213 } else
3214 Lst_Append(mainList, mainNode); 3214 Lst_Append(mainList, mainNode);
3215 Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL); 3215 Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL);
3216 return mainList; 3216 return mainList;
3217} 3217}
3218 3218
3219int 3219int
3220Parse_GetFatals(void) 3220Parse_GetFatals(void)
3221{ 3221{
3222 return fatals; 3222 return fatals;
3223} 3223}