| @@ -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" */ |
120 | MAKE_RCSID("$NetBSD: parse.c,v 1.429 2020/11/07 10:44:53 rillig Exp $"); | | 120 | MAKE_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 | */ |
127 | typedef struct IFile { | | 127 | typedef 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 | |
372 | static void | | 372 | static void |
373 | loadedfile_destroy(struct loadedfile *lf) | | 373 | loadedfile_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 | */ |
389 | static char * | | 389 | static char * |
390 | loadedfile_nextbuf(void *x, size_t *len) | | 390 | loadedfile_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 | */ |
405 | static Boolean | | 405 | static Boolean |
406 | load_getsize(int fd, size_t *ret) | | 406 | load_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 | |
435 | static Boolean | | 435 | static Boolean |
436 | loadedfile_mmap(struct loadedfile *lf, int fd) | | 436 | loadedfile_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 | */ |
492 | static struct loadedfile * | | 492 | static struct loadedfile * |
493 | loadfile(const char *path, int fd) | | 493 | loadfile(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 | |
559 | done: | | 559 | done: |
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. */ |
569 | static Boolean | | 569 | static Boolean |
570 | ParseIsEscaped(const char *line, const char *c) | | 570 | ParseIsEscaped(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 |
584 | static void | | 584 | static void |
585 | ParseMark(GNode *gn) | | 585 | ParseMark(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. */ |
594 | static int | | 594 | static int |
595 | ParseFindKeyword(const char *str) | | 595 | ParseFindKeyword(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 | |
618 | static void | | 618 | static void |
619 | PrintLocation(FILE *f, const char *filename, size_t lineno) | | 619 | PrintLocation(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 | */ |
991 | static void | | 991 | static void |
992 | ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType) | | 992 | ParseDoSrc(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 | */ |
1120 | static void | | 1120 | static void |
1121 | ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType, | | 1121 | ParseDoDependencyTargetSpecial(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 | */ |
1177 | static Boolean | | 1177 | static Boolean |
1178 | ParseDoDependencyTargetPath(const char *line, SearchPathList **inout_paths) | | 1178 | ParseDoDependencyTargetPath(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 | */ |
1200 | static Boolean | | 1200 | static Boolean |
1201 | ParseDoDependencyTarget(const char *line, ParseSpecial *inout_specType, | | 1201 | ParseDoDependencyTarget(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 | |
1270 | static void | | 1270 | static void |
1271 | ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart) | | 1271 | ParseDoDependencyTargetExtraWarn(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 | |
1290 | static void | | 1290 | static void |
1291 | ParseDoDependencyCheckSpec(ParseSpecial specType) | | 1291 | ParseDoDependencyCheckSpec(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 | |
1548 | static void | | 1548 | static void |
1549 | ParseDoDependencySourcesSpecial(char *start, char *end, | | 1549 | ParseDoDependencySourcesSpecial(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 | |
1568 | static Boolean | | 1568 | static Boolean |
1569 | ParseDoDependencySourcesMundane(char *start, char *end, | | 1569 | ParseDoDependencySourcesMundane(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. */ |
1984 | static Boolean | | 1984 | static Boolean |
1985 | VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue, | | 1985 | VarAssign_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 |
2012 | static void | | 2012 | static void |
2013 | VarAssignSpecial(const char *name, const char *avalue) | | 2013 | VarAssignSpecial(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. */ |
2033 | void | | 2033 | void |
2034 | Parse_DoVar(VarAssign *var, GNode *ctxt) | | 2034 | Parse_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 | |
2238 | static void | | 2238 | static void |
2239 | ParseDoInclude(char *line) | | 2239 | ParseDoInclude(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. */ |
2475 | static Boolean | | 2475 | static Boolean |
2476 | IsSysVInclude(const char *line) | | 2476 | IsSysVInclude(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". */ |
2498 | static void | | 2498 | static void |
2499 | ParseTraditionalInclude(char *line) | | 2499 | ParseTraditionalInclude(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 | |
2863 | static void | | 2861 | static void |
2864 | FinishDependencyGroup(void) | | 2862 | FinishDependencyGroup(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. */ |
2885 | static void | | 2885 | static void |
2886 | ParseLine_ShellCommand(const char *p) | | 2886 | ParseLine_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 | |
2959 | static Boolean | | 2959 | static Boolean |
2960 | ParseVarassign(const char *line) | | 2960 | ParseVarassign(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 | |
2971 | static char * | | 2972 | static char * |
2972 | FindSemicolon(char *p) | | 2973 | FindSemicolon(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 -> ':' | '::' | '!' */ |
3001 | static void | | 3001 | static void |
3002 | ParseDependency(char *line) | | 3002 | ParseDependency(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. */ |
3157 | void | | 3157 | void |
3158 | Parse_Init(void) | | 3158 | Parse_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 | */ |
3200 | GNodeList * | | 3200 | GNodeList * |
3201 | Parse_MainName(void) | | 3201 | Parse_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 | |
3219 | int | | 3219 | int |
3220 | Parse_GetFatals(void) | | 3220 | Parse_GetFatals(void) |
3221 | { | | 3221 | { |
3222 | return fatals; | | 3222 | return fatals; |
3223 | } | | 3223 | } |