Here's the diff. It's a bit longer than expected, because I took the
opportunity to expand a bit on the error-reporting engine.
The actual "new error" is the bit in var.c.
The rest:
- makes the engine record the current "parse location" while expanding
commands in a gnode.
- tests fatal_errors before running the actual command.
That seems to be giving the expected results.
I haven't run this thru a make build yet. It is likely to uncover various
makefile problems !!! as this effectively turns all runtime Parse_Fatal
errors into actual fatal errors (which they weren't).
(if you think the compat/normal job runner is messy, yes, it is. I have
slated an unification of both in the near future).
Index: engine.c
===================================================================
RCS file: /cvs/src/usr.bin/make/engine.c,v
retrieving revision 1.29
diff -u -p -r1.29 engine.c
--- engine.c 22 Mar 2012 13:47:12 -0000 1.29
+++ engine.c 19 Aug 2012 10:17:55 -0000
@@ -738,6 +739,7 @@ expand_commands(GNode *gn)
LstNode ln;
char *cmd;
+ Parse_SetLocation(&gn->origin);
for (ln = Lst_First(&gn->commands); ln != NULL; ln = Lst_Adv(ln)) {
cmd = Var_Subst(Lst_Datum(ln), &gn->context, false);
Lst_AtEnd(&gn->expanded, cmd);
@@ -749,6 +751,8 @@ run_gnode(GNode *gn)
{
if (gn != NULL && (gn->type & OP_DUMMY) == 0) {
expand_commands(gn);
+ if (fatal_errors)
+ exit(1);
return run_prepared_gnode(gn);
} else {
return NOSUCHNODE;
Index: job.c
===================================================================
RCS file: /cvs/src/usr.bin/make/job.c,v
retrieving revision 1.122
diff -u -p -r1.122 job.c
--- job.c 11 Apr 2012 18:27:30 -0000 1.122
+++ job.c 19 Aug 2012 10:17:55 -0000
@@ -779,6 +826,8 @@ prepare_job(GNode *gn, int flags)
*/
cmdsOK = Job_CheckCommands(gn);
expand_commands(gn);
+ if (fatal_errors)
+ Punt("can't continue");
if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) {
/*
Index: lowparse.c
===================================================================
RCS file: /cvs/src/usr.bin/make/lowparse.c,v
retrieving revision 1.27
diff -u -p -r1.27 lowparse.c
--- lowparse.c 22 Mar 2012 13:50:30 -0000 1.27
+++ lowparse.c 19 Aug 2012 10:17:55 -0000
@@ -73,6 +73,9 @@ static struct input_stream *current; /*
static LIST input_stack; /* Stack of input_stream waiting to be parsed
* (includes and loop reparses) */
+/* record gnode location for proper reporting at runtime */
+static Location *post_parse = NULL;
+
/* input_stream ctors.
*
* obj = new_input_file(filename, filehandle);
@@ -433,10 +436,20 @@ Parse_Getfilename(void)
}
void
+Parse_SetLocation(Location *origin)
+{
+ post_parse = origin;
+}
+
+void
Parse_FillLocation(Location *origin)
{
- origin->lineno = Parse_Getlineno();
- origin->fname = Parse_Getfilename();
+ if (post_parse) {
+ *origin = *post_parse;
+ } else {
+ origin->lineno = Parse_Getlineno();
+ origin->fname = Parse_Getfilename();
+ }
}
#ifdef CLEANUP
Index: lowparse.h
===================================================================
RCS file: /cvs/src/usr.bin/make/lowparse.h,v
retrieving revision 1.8
diff -u -p -r1.8 lowparse.h
--- lowparse.h 22 Mar 2012 13:47:12 -0000 1.8
+++ lowparse.h 19 Aug 2012 10:17:55 -0000
@@ -81,6 +81,13 @@ extern const char *Parse_Getfilename(voi
* Fill the location pointed by origin with the current location. */
extern void Parse_FillLocation(Location *);
+/* Parse_SetLocation(origin)
+ * Set the "parse location" to a given origin.
+ * Used for parse errors that occur during variable expansion at
+ * runtime.
+ */
+extern void Parse_SetLocation(Location *);
+
/* continue = Parse_NextFile();
* Advance parsing to the next file in the input stack. Returns true
* if there is parsing left to do.
Index: var.c
===================================================================
RCS file: /cvs/src/usr.bin/make/var.c,v
retrieving revision 1.89
diff -u -p -r1.89 var.c
--- var.c 22 Mar 2012 13:47:12 -0000 1.89
+++ var.c 19 Aug 2012 10:17:55 -0000
@@ -761,11 +761,12 @@ parse_base_variable_name(const char **ps
case '{':
/* Find eventual modifiers in the variable */
tstr = VarName_Get(str+2, name, ctxt, false, find_pos(str[1]));
- if (*tstr == ':')
+ if (*tstr == '\0')
+ Parse_Error(PARSE_FATAL, "Unterminated variable spec
in %s", *pstr);
+ else if (*tstr == ':')
has_modifier = true;
- else if (*tstr != '\0') {
+ else
tstr++;
- }
break;
default:
name->s = str+1;
Index: varname.c
===================================================================
RCS file: /cvs/src/usr.bin/make/varname.c,v
retrieving revision 1.5
diff -u -p -r1.5 varname.c
--- varname.c 19 Jul 2010 19:46:44 -0000 1.5
+++ varname.c 19 Aug 2012 10:17:55 -0000
@@ -32,7 +32,8 @@
#include "varname.h"
const char *
-VarName_Get(const char *start, struct Name *name, SymTable *ctxt, bool err,
const char *(*cont)(const char *))
+VarName_Get(const char *start, struct Name *name, SymTable *ctxt, bool err,
+ const char *(*cont)(const char *))
{
const char *p;
size_t len;
@@ -41,7 +42,7 @@ VarName_Get(const char *start, struct Na
/* If we don't want recursive variables, we skip over '$' */
if (!FEATURES(FEATURE_RECVARS)) {
while (*p == '$')
- p = cont(p);
+ p = cont(p+1);
}
if (*p != '$') {
name->s = start;