Sun Jun 12 13:37:32 2022 UTC ()
make: reorganize Parse_Error

Determining the location where the error occurred is now done by
ParseVErrorInternal.  This frees the remaining code from keeping the
filename and the line number together.  It also makes Parse_Error short
enough that it might be worth providing a separate function for each of
the 3 log levels.

No functional change.


(rillig)
diff -r1.302 -r1.303 src/usr.bin/make/make.h
diff -r1.679 -r1.680 src/usr.bin/make/parse.c
diff -r1.1021 -r1.1022 src/usr.bin/make/var.c

cvs diff -r1.302 -r1.303 src/usr.bin/make/make.h (expand / switch to unified diff)

--- src/usr.bin/make/make.h 2022/05/07 17:49:47 1.302
+++ src/usr.bin/make/make.h 2022/06/12 13:37:32 1.303
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: make.h,v 1.302 2022/05/07 17:49:47 rillig Exp $ */ 1/* $NetBSD: make.h,v 1.303 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.
@@ -842,27 +842,27 @@ void Punt(const char *, ...) MAKE_ATTR_P @@ -842,27 +842,27 @@ void Punt(const char *, ...) MAKE_ATTR_P
842void DieHorribly(void) MAKE_ATTR_DEAD; 842void DieHorribly(void) MAKE_ATTR_DEAD;
843void Finish(int) MAKE_ATTR_DEAD; 843void Finish(int) MAKE_ATTR_DEAD;
844bool unlink_file(const char *) MAKE_ATTR_USE; 844bool unlink_file(const char *) MAKE_ATTR_USE;
845void execDie(const char *, const char *); 845void execDie(const char *, const char *);
846char *getTmpdir(void) MAKE_ATTR_USE; 846char *getTmpdir(void) MAKE_ATTR_USE;
847bool ParseBoolean(const char *, bool) MAKE_ATTR_USE; 847bool ParseBoolean(const char *, bool) MAKE_ATTR_USE;
848const char *cached_realpath(const char *, char *); 848const char *cached_realpath(const char *, char *);
849bool GetBooleanExpr(const char *, bool); 849bool GetBooleanExpr(const char *, bool);
850 850
851/* parse.c */ 851/* parse.c */
852void Parse_Init(void); 852void Parse_Init(void);
853void Parse_End(void); 853void Parse_End(void);
854 854
855void PrintLocation(FILE *, bool, const char *, unsigned); 855void PrintLocation(FILE *, bool, const GNode *);
856void PrintStackTrace(bool); 856void PrintStackTrace(bool);
857void Parse_Error(ParseErrorLevel, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3); 857void Parse_Error(ParseErrorLevel, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);
858bool Parse_VarAssign(const char *, bool, GNode *) MAKE_ATTR_USE; 858bool Parse_VarAssign(const char *, bool, GNode *) MAKE_ATTR_USE;
859void Parse_AddIncludeDir(const char *); 859void Parse_AddIncludeDir(const char *);
860void Parse_File(const char *, int); 860void Parse_File(const char *, int);
861void Parse_PushInput(const char *, unsigned, unsigned, Buffer, 861void Parse_PushInput(const char *, unsigned, unsigned, Buffer,
862 struct ForLoop *); 862 struct ForLoop *);
863void Parse_MainName(GNodeList *); 863void Parse_MainName(GNodeList *);
864int Parse_NumErrors(void) MAKE_ATTR_USE; 864int Parse_NumErrors(void) MAKE_ATTR_USE;
865 865
866 866
867/* suff.c */ 867/* suff.c */
868void Suff_Init(void); 868void Suff_Init(void);

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

--- src/usr.bin/make/parse.c 2022/06/11 17:58:15 1.679
+++ src/usr.bin/make/parse.c 2022/06/12 13:37:32 1.680
@@ -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" */
108MAKE_RCSID("$NetBSD: parse.c,v 1.679 2022/06/11 17:58:15 rillig Exp $"); 108MAKE_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 */
113typedef struct IncludedFile { 113typedef 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
438void 438void
439PrintLocation(FILE *f, bool useVars, const char *fname, unsigned lineno) 439PrintLocation(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
465static void MAKE_ATTR_PRINTFLIKE(6, 0) 477static void MAKE_ATTR_PRINTFLIKE(5, 0)
466ParseVErrorInternal(FILE *f, bool useVars, const char *fname, unsigned lineno, 478ParseVErrorInternal(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
495static void MAKE_ATTR_PRINTFLIKE(4, 5) 506static void MAKE_ATTR_PRINTFLIKE(3, 4)
496ParseErrorInternal(const char *fname, unsigned lineno, 507ParseErrorInternal(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 */
522void 533void
523Parse_Error(ParseErrorLevel level, const char *fmt, ...) 534Parse_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 */
556static void 556static void
557HandleMessage(ParseErrorLevel level, const char *levelName, const char *umsg) 557HandleMessage(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 */
1935void 1935void
1936Parse_AddIncludeDir(const char *dir) 1936Parse_AddIncludeDir(const char *dir)
1937{ 1937{

cvs diff -r1.1021 -r1.1022 src/usr.bin/make/var.c (expand / switch to unified diff)

--- src/usr.bin/make/var.c 2022/05/14 12:25:16 1.1021
+++ src/usr.bin/make/var.c 2022/06/12 13:37:32 1.1022
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.1021 2022/05/14 12:25:16 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.1022 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.
@@ -129,27 +129,27 @@ @@ -129,27 +129,27 @@
129#include <regex.h> 129#include <regex.h>
130#endif 130#endif
131#include <errno.h> 131#include <errno.h>
132#include <inttypes.h> 132#include <inttypes.h>
133#include <limits.h> 133#include <limits.h>
134#include <time.h> 134#include <time.h>
135 135
136#include "make.h" 136#include "make.h"
137#include "dir.h" 137#include "dir.h"
138#include "job.h" 138#include "job.h"
139#include "metachar.h" 139#include "metachar.h"
140 140
141/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 141/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
142MAKE_RCSID("$NetBSD: var.c,v 1.1021 2022/05/14 12:25:16 rillig Exp $"); 142MAKE_RCSID("$NetBSD: var.c,v 1.1022 2022/06/12 13:37:32 rillig Exp $");
143 143
144/* 144/*
145 * Variables are defined using one of the VAR=value assignments. Their 145 * Variables are defined using one of the VAR=value assignments. Their
146 * value can be queried by expressions such as $V, ${VAR}, or with modifiers 146 * value can be queried by expressions such as $V, ${VAR}, or with modifiers
147 * such as ${VAR:S,from,to,g:Q}. 147 * such as ${VAR:S,from,to,g:Q}.
148 * 148 *
149 * There are 3 kinds of variables: scope variables, environment variables, 149 * There are 3 kinds of variables: scope variables, environment variables,
150 * undefined variables. 150 * undefined variables.
151 * 151 *
152 * Scope variables are stored in a GNode.scope. The only way to undefine 152 * Scope variables are stored in a GNode.scope. The only way to undefine
153 * a scope variable is using the .undef directive. In particular, it must 153 * a scope variable is using the .undef directive. In particular, it must
154 * not be possible to undefine a variable during the evaluation of an 154 * not be possible to undefine a variable during the evaluation of an
155 * expression, or Var.name might point nowhere. (There is another, 155 * expression, or Var.name might point nowhere. (There is another,
@@ -4513,28 +4513,27 @@ Var_Parse(const char **pp, GNode *scope, @@ -4513,28 +4513,27 @@ Var_Parse(const char **pp, GNode *scope,
4513 } else { 4513 } else {
4514 VarParseResult res; 4514 VarParseResult res;
4515 if (!ParseVarnameLong(&p, startc, scope, emode, 4515 if (!ParseVarnameLong(&p, startc, scope, emode,
4516 pp, &res, out_val, 4516 pp, &res, out_val,
4517 &endc, &v, &haveModifier, &extramodifiers, 4517 &endc, &v, &haveModifier, &extramodifiers,
4518 &dynamic, &expr.defined)) 4518 &dynamic, &expr.defined))
4519 return res; 4519 return res;
4520 } 4520 }
4521 4521
4522 expr.name = v->name.str; 4522 expr.name = v->name.str;
4523 if (v->inUse) { 4523 if (v->inUse) {
4524 if (scope->fname != NULL) { 4524 if (scope->fname != NULL) {
4525 fprintf(stderr, "In a command near "); 4525 fprintf(stderr, "In a command near ");
4526 PrintLocation(stderr, false, 4526 PrintLocation(stderr, false, scope);
4527 scope->fname, scope->lineno); 
4528 } 4527 }
4529 Fatal("Variable %s is recursive.", v->name.str); 4528 Fatal("Variable %s is recursive.", v->name.str);
4530 } 4529 }
4531 4530
4532 /* 4531 /*
4533 * XXX: This assignment creates an alias to the current value of the 4532 * XXX: This assignment creates an alias to the current value of the
4534 * variable. This means that as long as the value of the expression 4533 * variable. This means that as long as the value of the expression
4535 * stays the same, the value of the variable must not change. 4534 * stays the same, the value of the variable must not change.
4536 * Using the '::=' modifier, it could be possible to trigger exactly 4535 * Using the '::=' modifier, it could be possible to trigger exactly
4537 * this situation. 4536 * this situation.
4538 * 4537 *
4539 * At the bottom of this function, the resulting value is compared to 4538 * At the bottom of this function, the resulting value is compared to
4540 * the then-current value of the variable. This might also invoke 4539 * the then-current value of the variable. This might also invoke