| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: parse.c,v 1.679 2022/06/11 17:58:15 rillig Exp $ */ | | 1 | /* $NetBSD: parse.c,v 1.680 2022/06/12 13:37:32 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. |
| @@ -95,27 +95,27 @@ | | | @@ -95,27 +95,27 @@ |
95 | */ | | 95 | */ |
96 | | | 96 | |
97 | #include <sys/types.h> | | 97 | #include <sys/types.h> |
98 | #include <sys/stat.h> | | 98 | #include <sys/stat.h> |
99 | #include <errno.h> | | 99 | #include <errno.h> |
100 | #include <stdarg.h> | | 100 | #include <stdarg.h> |
101 | | | 101 | |
102 | #include "make.h" | | 102 | #include "make.h" |
103 | #include "dir.h" | | 103 | #include "dir.h" |
104 | #include "job.h" | | 104 | #include "job.h" |
105 | #include "pathnames.h" | | 105 | #include "pathnames.h" |
106 | | | 106 | |
107 | /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ | | 107 | /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ |
108 | MAKE_RCSID("$NetBSD: parse.c,v 1.679 2022/06/11 17:58:15 rillig Exp $"); | | 108 | MAKE_RCSID("$NetBSD: parse.c,v 1.680 2022/06/12 13:37:32 rillig Exp $"); |
109 | | | 109 | |
110 | /* | | 110 | /* |
111 | * A file being read. | | 111 | * A file being read. |
112 | */ | | 112 | */ |
113 | typedef struct IncludedFile { | | 113 | typedef struct IncludedFile { |
114 | FStr name; /* absolute or relative to the cwd */ | | 114 | FStr name; /* absolute or relative to the cwd */ |
115 | unsigned lineno; /* 1-based */ | | 115 | unsigned lineno; /* 1-based */ |
116 | unsigned readLines; /* the number of physical lines that have | | 116 | unsigned readLines; /* the number of physical lines that have |
117 | * been read from the file */ | | 117 | * been read from the file */ |
118 | unsigned forHeadLineno; /* 1-based */ | | 118 | unsigned forHeadLineno; /* 1-based */ |
119 | unsigned forBodyReadLines; /* the number of physical lines that have | | 119 | unsigned forBodyReadLines; /* the number of physical lines that have |
120 | * been read from the file above the body of | | 120 | * been read from the file above the body of |
121 | * the .for loop */ | | 121 | * the .for loop */ |
| @@ -426,133 +426,133 @@ FindKeyword(const char *str) | | | @@ -426,133 +426,133 @@ FindKeyword(const char *str) |
426 | | | 426 | |
427 | if (diff == 0) | | 427 | if (diff == 0) |
428 | return curr; | | 428 | return curr; |
429 | if (diff < 0) | | 429 | if (diff < 0) |
430 | end = curr - 1; | | 430 | end = curr - 1; |
431 | else | | 431 | else |
432 | start = curr + 1; | | 432 | start = curr + 1; |
433 | } | | 433 | } |
434 | | | 434 | |
435 | return -1; | | 435 | return -1; |
436 | } | | 436 | } |
437 | | | 437 | |
438 | void | | 438 | void |
439 | PrintLocation(FILE *f, bool useVars, const char *fname, unsigned lineno) | | 439 | PrintLocation(FILE *f, bool useVars, const GNode *gn) |
440 | { | | 440 | { |
441 | char dirbuf[MAXPATHLEN + 1]; | | 441 | char dirbuf[MAXPATHLEN + 1]; |
442 | FStr dir, base; | | 442 | FStr dir, base; |
| | | 443 | const char *fname; |
| | | 444 | unsigned lineno; |
| | | 445 | |
| | | 446 | if (gn != NULL) { |
| | | 447 | fname = gn->fname; |
| | | 448 | lineno = gn->lineno; |
| | | 449 | } else if (includes.len > 0) { |
| | | 450 | IncludedFile *curFile = CurFile(); |
| | | 451 | fname = curFile->name.str; |
| | | 452 | lineno = curFile->lineno; |
| | | 453 | } else |
| | | 454 | return; |
443 | | | 455 | |
444 | if (!useVars || fname[0] == '/' || strcmp(fname, "(stdin)") == 0) { | | 456 | if (!useVars || fname[0] == '/' || strcmp(fname, "(stdin)") == 0) { |
445 | (void)fprintf(f, "\"%s\" line %u: ", fname, lineno); | | 457 | (void)fprintf(f, "\"%s\" line %u: ", fname, lineno); |
446 | return; | | 458 | return; |
447 | } | | 459 | } |
448 | | | 460 | |
449 | dir = Var_Value(SCOPE_GLOBAL, ".PARSEDIR"); | | 461 | dir = Var_Value(SCOPE_GLOBAL, ".PARSEDIR"); |
450 | if (dir.str == NULL) | | 462 | if (dir.str == NULL) |
451 | dir.str = "."; | | 463 | dir.str = "."; |
452 | if (dir.str[0] != '/') | | 464 | if (dir.str[0] != '/') |
453 | dir.str = realpath(dir.str, dirbuf); | | 465 | dir.str = realpath(dir.str, dirbuf); |
454 | | | 466 | |
455 | base = Var_Value(SCOPE_GLOBAL, ".PARSEFILE"); | | 467 | base = Var_Value(SCOPE_GLOBAL, ".PARSEFILE"); |
456 | if (base.str == NULL) | | 468 | if (base.str == NULL) |
457 | base.str = str_basename(fname); | | 469 | base.str = str_basename(fname); |
458 | | | 470 | |
459 | (void)fprintf(f, "\"%s/%s\" line %u: ", dir.str, base.str, lineno); | | 471 | (void)fprintf(f, "\"%s/%s\" line %u: ", dir.str, base.str, lineno); |
460 | | | 472 | |
461 | FStr_Done(&base); | | 473 | FStr_Done(&base); |
462 | FStr_Done(&dir); | | 474 | FStr_Done(&dir); |
463 | } | | 475 | } |
464 | | | 476 | |
465 | static void MAKE_ATTR_PRINTFLIKE(6, 0) | | 477 | static void MAKE_ATTR_PRINTFLIKE(5, 0) |
466 | ParseVErrorInternal(FILE *f, bool useVars, const char *fname, unsigned lineno, | | 478 | ParseVErrorInternal(FILE *f, bool useVars, const GNode *gn, |
467 | ParseErrorLevel level, const char *fmt, va_list ap) | | 479 | ParseErrorLevel level, const char *fmt, va_list ap) |
468 | { | | 480 | { |
469 | static bool fatal_warning_error_printed = false; | | 481 | static bool fatal_warning_error_printed = false; |
470 | | | 482 | |
471 | (void)fprintf(f, "%s: ", progname); | | 483 | (void)fprintf(f, "%s: ", progname); |
472 | | | 484 | |
473 | if (fname != NULL) | | 485 | PrintLocation(f, useVars, gn); |
474 | PrintLocation(f, useVars, fname, lineno); | | | |
475 | if (level == PARSE_WARNING) | | 486 | if (level == PARSE_WARNING) |
476 | (void)fprintf(f, "warning: "); | | 487 | (void)fprintf(f, "warning: "); |
477 | (void)vfprintf(f, fmt, ap); | | 488 | (void)vfprintf(f, fmt, ap); |
478 | (void)fprintf(f, "\n"); | | 489 | (void)fprintf(f, "\n"); |
479 | (void)fflush(f); | | 490 | (void)fflush(f); |
480 | | | 491 | |
481 | if (level == PARSE_FATAL) | | 492 | if (level == PARSE_FATAL) |
482 | parseErrors++; | | 493 | parseErrors++; |
483 | if (level == PARSE_WARNING && opts.parseWarnFatal) { | | 494 | if (level == PARSE_WARNING && opts.parseWarnFatal) { |
484 | if (!fatal_warning_error_printed) { | | 495 | if (!fatal_warning_error_printed) { |
485 | Error("parsing warnings being treated as errors"); | | 496 | Error("parsing warnings being treated as errors"); |
486 | fatal_warning_error_printed = true; | | 497 | fatal_warning_error_printed = true; |
487 | } | | 498 | } |
488 | parseErrors++; | | 499 | parseErrors++; |
489 | } | | 500 | } |
490 | | | 501 | |
491 | if (DEBUG(PARSE)) | | 502 | if (DEBUG(PARSE)) |
492 | PrintStackTrace(false); | | 503 | PrintStackTrace(false); |
493 | } | | 504 | } |
494 | | | 505 | |
495 | static void MAKE_ATTR_PRINTFLIKE(4, 5) | | 506 | static void MAKE_ATTR_PRINTFLIKE(3, 4) |
496 | ParseErrorInternal(const char *fname, unsigned lineno, | | 507 | ParseErrorInternal(const GNode *gn, |
497 | ParseErrorLevel level, const char *fmt, ...) | | 508 | ParseErrorLevel level, const char *fmt, ...) |
498 | { | | 509 | { |
499 | va_list ap; | | 510 | va_list ap; |
500 | | | 511 | |
501 | (void)fflush(stdout); | | 512 | (void)fflush(stdout); |
502 | va_start(ap, fmt); | | 513 | va_start(ap, fmt); |
503 | ParseVErrorInternal(stderr, false, fname, lineno, level, fmt, ap); | | 514 | ParseVErrorInternal(stderr, false, gn, level, fmt, ap); |
504 | va_end(ap); | | 515 | va_end(ap); |
505 | | | 516 | |
506 | if (opts.debug_file != stdout && opts.debug_file != stderr) { | | 517 | if (opts.debug_file != stdout && opts.debug_file != stderr) { |
507 | va_start(ap, fmt); | | 518 | va_start(ap, fmt); |
508 | ParseVErrorInternal(opts.debug_file, false, fname, lineno, | | 519 | ParseVErrorInternal(opts.debug_file, false, gn, |
509 | level, fmt, ap); | | 520 | level, fmt, ap); |
510 | va_end(ap); | | 521 | va_end(ap); |
511 | } | | 522 | } |
512 | } | | 523 | } |
513 | | | 524 | |
514 | /* | | 525 | /* |
515 | * Print a parse error message, including location information. | | 526 | * Print a parse error message, including location information. |
516 | * | | 527 | * |
517 | * If the level is PARSE_FATAL, continue parsing until the end of the | | 528 | * If the level is PARSE_FATAL, continue parsing until the end of the |
518 | * current top-level makefile, then exit (see Parse_File). | | 529 | * current top-level makefile, then exit (see Parse_File). |
519 | * | | 530 | * |
520 | * Fmt is given without a trailing newline. | | 531 | * Fmt is given without a trailing newline. |
521 | */ | | 532 | */ |
522 | void | | 533 | void |
523 | Parse_Error(ParseErrorLevel level, const char *fmt, ...) | | 534 | Parse_Error(ParseErrorLevel level, const char *fmt, ...) |
524 | { | | 535 | { |
525 | va_list ap; | | 536 | va_list ap; |
526 | const char *fname; | | | |
527 | unsigned lineno; | | | |
528 | | | | |
529 | if (includes.len == 0) { | | | |
530 | fname = NULL; | | | |
531 | lineno = 0; | | | |
532 | } else { | | | |
533 | IncludedFile *curFile = CurFile(); | | | |
534 | fname = curFile->name.str; | | | |
535 | lineno = curFile->lineno; | | | |
536 | } | | | |
537 | | | 537 | |
538 | (void)fflush(stdout); | | 538 | (void)fflush(stdout); |
539 | va_start(ap, fmt); | | 539 | va_start(ap, fmt); |
540 | ParseVErrorInternal(stderr, true, fname, lineno, level, fmt, ap); | | 540 | ParseVErrorInternal(stderr, true, NULL, level, fmt, ap); |
541 | va_end(ap); | | 541 | va_end(ap); |
542 | | | 542 | |
543 | if (opts.debug_file != stdout && opts.debug_file != stderr) { | | 543 | if (opts.debug_file != stdout && opts.debug_file != stderr) { |
544 | va_start(ap, fmt); | | 544 | va_start(ap, fmt); |
545 | ParseVErrorInternal(opts.debug_file, true, fname, lineno, | | 545 | ParseVErrorInternal(opts.debug_file, true, NULL, |
546 | level, fmt, ap); | | 546 | level, fmt, ap); |
547 | va_end(ap); | | 547 | va_end(ap); |
548 | } | | 548 | } |
549 | } | | 549 | } |
550 | | | 550 | |
551 | | | 551 | |
552 | /* | | 552 | /* |
553 | * Handle an .info, .warning or .error directive. For an .error directive, | | 553 | * Handle an .info, .warning or .error directive. For an .error directive, |
554 | * exit immediately. | | 554 | * exit immediately. |
555 | */ | | 555 | */ |
556 | static void | | 556 | static void |
557 | HandleMessage(ParseErrorLevel level, const char *levelName, const char *umsg) | | 557 | HandleMessage(ParseErrorLevel level, const char *levelName, const char *umsg) |
558 | { | | 558 | { |
| @@ -1911,27 +1911,27 @@ GNode_AddCommand(GNode *gn, char *cmd) | | | @@ -1911,27 +1911,27 @@ GNode_AddCommand(GNode *gn, char *cmd) |
1911 | RememberLocation(gn); | | 1911 | RememberLocation(gn); |
1912 | } else { | | 1912 | } else { |
1913 | #if 0 | | 1913 | #if 0 |
1914 | /* XXX: We cannot do this until we fix the tree */ | | 1914 | /* XXX: We cannot do this until we fix the tree */ |
1915 | Lst_Append(&gn->commands, cmd); | | 1915 | Lst_Append(&gn->commands, cmd); |
1916 | Parse_Error(PARSE_WARNING, | | 1916 | Parse_Error(PARSE_WARNING, |
1917 | "overriding commands for target \"%s\"; " | | 1917 | "overriding commands for target \"%s\"; " |
1918 | "previous commands defined at %s: %u ignored", | | 1918 | "previous commands defined at %s: %u ignored", |
1919 | gn->name, gn->fname, gn->lineno); | | 1919 | gn->name, gn->fname, gn->lineno); |
1920 | #else | | 1920 | #else |
1921 | Parse_Error(PARSE_WARNING, | | 1921 | Parse_Error(PARSE_WARNING, |
1922 | "duplicate script for target \"%s\" ignored", | | 1922 | "duplicate script for target \"%s\" ignored", |
1923 | gn->name); | | 1923 | gn->name); |
1924 | ParseErrorInternal(gn->fname, gn->lineno, PARSE_WARNING, | | 1924 | ParseErrorInternal(gn, PARSE_WARNING, |
1925 | "using previous script for \"%s\" defined here", | | 1925 | "using previous script for \"%s\" defined here", |
1926 | gn->name); | | 1926 | gn->name); |
1927 | #endif | | 1927 | #endif |
1928 | } | | 1928 | } |
1929 | } | | 1929 | } |
1930 | | | 1930 | |
1931 | /* | | 1931 | /* |
1932 | * Add a directory to the path searched for included makefiles bracketed | | 1932 | * Add a directory to the path searched for included makefiles bracketed |
1933 | * by double-quotes. | | 1933 | * by double-quotes. |
1934 | */ | | 1934 | */ |
1935 | void | | 1935 | void |
1936 | Parse_AddIncludeDir(const char *dir) | | 1936 | Parse_AddIncludeDir(const char *dir) |
1937 | { | | 1937 | { |