[SV 46433] Show recipe line offsets in line number messages.

While displaying line numbers, show the relevant line number inside
the recipe not just the first line of the entire recipe.
Sample changes suggested by Brian Vandenberg <phantall@gmail.com>

* gnumake.h (gmk_floc): Add an 'offset' to track the recipe offset.
* read.c (eval, eval_makefile, eval_buffer): Initialize 'offset'.
(record_files, install_pattern_rule): Ditto.
* job.c (new_job, job_next_command): Update 'offset' based on the
line of the recipe we're expanding or invoking.
(child_error): Add 'offset' when showing the line number.
* function.c (func_shell_base): Ditto.
* output.c (error, fatal): Ditto.
* NEWS: Mention the new ability.
* tests/scripts/features/errors: Check the line number on errors.
* tests/scripts/functions/warning: Check the line number on warnings.
* tests/scripts/features/output-sync,
tests/scripts/features/parallelism, tests/scripts/functions/shell,
tests/scripts/functions/error: Update line numbers.
This commit is contained in:
Paul Smith 2016-04-10 17:12:48 -04:00
parent 3fc99a48e1
commit 047bd5a16f
14 changed files with 81 additions and 22 deletions

6
NEWS
View File

@ -24,6 +24,10 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set
The function is expanded to the contents of the file. The contents are
expanded verbatim except that the final newline, if any, is stripped.
* The makefile line numbers shown by GNU make now point directly to the
specific line in the recipe where the failure or warning occurred.
Sample changes suggested by Brian Vandenberg <phantall@gmail.com>
* The interface to GNU make's "jobserver" is stable as documented in the
manual, for tools which may want to access it.
@ -32,7 +36,7 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set
* The amount of parallelism can be determined by querying MAKEFLAGS, even when
the job server is enabled (previously MAKEFLAGS would always contain only
"-j" when job server was enabled).
"-j", with no number, when job server was enabled).
* VMS-specific changes:

View File

@ -1734,7 +1734,8 @@ func_shell_base (char *o, char **argv, int trim_newlines)
if (reading_file && reading_file->filenm)
{
char *p = alloca (strlen (reading_file->filenm)+11+4);
sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno);
sprintf (p, "%s:%lu: ", reading_file->filenm,
reading_file->lineno + reading_file->offset);
error_prefix = p;
}
else

View File

@ -24,6 +24,7 @@ typedef struct
{
const char *filenm;
unsigned long lineno;
unsigned long offset;
} gmk_floc;
typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);

7
job.c
View File

@ -500,7 +500,7 @@ child_error (struct child *child,
else
{
char *a = alloca (strlen (flocp->filenm) + 1 + 11 + 1);
sprintf (a, "%s:%lu", flocp->filenm, flocp->lineno);
sprintf (a, "%s:%lu", flocp->filenm, flocp->lineno + flocp->offset);
nm = a;
}
@ -1745,10 +1745,12 @@ new_job (struct file *file)
memmove (out, in, strlen (in) + 1);
/* Finally, expand the line. */
cmds->fileinfo.offset = i;
lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i],
file);
}
cmds->fileinfo.offset = 0;
c->command_lines = lines;
/* Fetch the first command line to be run. */
@ -1873,12 +1875,15 @@ job_next_command (struct child *child)
{
/* There are no more lines to be expanded. */
child->command_ptr = 0;
child->file->cmds->fileinfo.offset = 0;
return 0;
}
else
/* Get the next line to run. */
child->command_ptr = child->command_lines[child->command_line++];
}
child->file->cmds->fileinfo.offset = child->command_line - 1;
return 1;
}

View File

@ -651,7 +651,7 @@ error (const gmk_floc *flocp, size_t len, const char *fmt, ...)
p = get_buffer (len);
if (flocp && flocp->filenm)
sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno);
sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
else if (makelevel == 0)
sprintf (p, "%s: ", program);
else
@ -683,7 +683,7 @@ fatal (const gmk_floc *flocp, size_t len, const char *fmt, ...)
p = get_buffer (len);
if (flocp && flocp->filenm)
sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno);
sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
else if (makelevel == 0)
sprintf (p, "%s: *** ", program);
else

4
read.c
View File

@ -324,6 +324,7 @@ eval_makefile (const char *filename, int flags)
ebuf.floc.filenm = filename; /* Use the original file name. */
ebuf.floc.lineno = 1;
ebuf.floc.offset = 0;
if (ISDB (DB_VERBOSE))
{
@ -470,6 +471,7 @@ eval_buffer (char *buffer, const gmk_floc *floc)
{
ebuf.floc.filenm = NULL;
ebuf.floc.lineno = 1;
ebuf.floc.offset = 0;
}
curfile = reading_file;
@ -592,6 +594,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (filenames != 0) \
{ \
fi.lineno = tgts_started; \
fi.offset = 0; \
record_files (filenames, pattern, pattern_percent, depstr, \
cmds_started, commands, commands_idx, two_colon, \
prefix, &fi); \
@ -1958,6 +1961,7 @@ record_files (struct nameseq *filenames, const char *pattern,
cmds = xmalloc (sizeof (struct commands));
cmds->fileinfo.filenm = flocp->filenm;
cmds->fileinfo.lineno = cmds_started;
cmds->fileinfo.offset = 0;
cmds->commands = xstrndup (commands, commands_idx);
cmds->command_lines = 0;
cmds->recipe_prefix = prefix;

1
rule.c
View File

@ -380,6 +380,7 @@ install_pattern_rule (struct pspec *p, int terminal)
r->cmds = xmalloc (sizeof (struct commands));
r->cmds->fileinfo.filenm = 0;
r->cmds->fileinfo.lineno = 0;
r->cmds->fileinfo.offset = 0;
/* These will all be string literals, but we malloc space for them
anyway because somebody might want to free them later. */
r->cmds->commands = xstrdup (p->commands);

View File

@ -90,4 +90,18 @@ if (!$vos) {
&compare_output($answer,&get_logfile(1));
}
# Test that error line offset works
run_make_test(q!
all:
@echo hi
@echo there
@exit 1
!,
'', "hi\nthere\n#MAKE#: *** [#MAKEFILE#:5: all] Error 1", 512);
1;
### Local Variables:
### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
### End:

View File

@ -204,7 +204,7 @@ bar: end
#MAKE#[1]: Entering directory '#PWD#/foo'
foo-fail: start
foo-fail: end
#MAKE#[1]: *** [Makefile:20: foo-fail] Error 1
#MAKE#[1]: *** [Makefile:23: foo-fail] Error 1
#MAKE#[1]: Leaving directory '#PWD#/foo'
#MAKE#: *** [#MAKEFILE#:4: make-foo-fail] Error 2\n",
512);

View File

@ -99,12 +99,12 @@ ok:
\@$sleep_command 4
\@echo Ok done",
'-rR -j5', "Fail
#MAKE#: *** [#MAKEFILE#:6: fail.1] Error 1
#MAKE#: *** [#MAKEFILE#:8: fail.1] Error 1
#MAKE#: *** Waiting for unfinished jobs....
Fail
#MAKE#: *** [#MAKEFILE#:6: fail.2] Error 1
#MAKE#: *** [#MAKEFILE#:8: fail.2] Error 1
Fail
#MAKE#: *** [#MAKEFILE#:6: fail.3] Error 1
#MAKE#: *** [#MAKEFILE#:8: fail.3] Error 1
Ok done",
512);

View File

@ -54,7 +54,7 @@ $answer = "Some stuff\n$makefile:12: *** error is maybe. Stop.\n";
# Test #4
&run_make_with_options($makefile, "ERROR4=definitely", &get_logfile, 512);
$answer = "Some stuff\n$makefile:16: *** error is definitely. Stop.\n";
$answer = "Some stuff\n$makefile:17: *** error is definitely. Stop.\n";
&compare_output($answer,&get_logfile(1));
# Test #5
@ -66,8 +66,6 @@ $answer = "$makefile:22: *** Error found!. Stop.\n";
# This tells the test driver that the perl test script executed properly.
1;
### Local Variables:
### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
### End:

View File

@ -44,4 +44,17 @@ export HI = $(shell echo hi)
all: ; @echo $$HI
','','hi');
# Test shell errors in recipes including offset
run_make_test('
all:
@echo hi
$(shell ./basdfdfsed there)
@echo there
',
'', "#MAKE#: ./basdfdfsed: Command not found\nhi\nthere\n");
1;
### Local Variables:
### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
### End:

View File

@ -52,14 +52,32 @@ $answer = "Some stuff\n$makefile:10: warning is maybe\nhi\n";
# Test #4
&run_make_with_options($makefile, "WARNING4=definitely", &get_logfile, 0);
$answer = "Some stuff\n$makefile:14: warning is definitely\nhi\nthere\n";
$answer = "Some stuff\n$makefile:15: warning is definitely\nhi\nthere\n";
&compare_output($answer,&get_logfile(1));
# Test linenumber offset
run_make_test(q!
all: one two
$(warning in $@ line 3)
@true
$(warning in $@ line 5)
one two:
$(warning in $@ line 8)
@true
$(warning in $@ line 10)
!,
'', "#MAKEFILE#:8: in one line 8
#MAKEFILE#:10: in one line 10
#MAKEFILE#:8: in two line 8
#MAKEFILE#:10: in two line 10
#MAKEFILE#:3: in all line 3
#MAKEFILE#:5: in all line 5\n");
# This tells the test driver that the perl test script executed properly.
1;
### Local Variables:
### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
### End:

View File

@ -1657,7 +1657,7 @@ print_variable (const void *item, void *arg)
fputs (" private", stdout);
if (v->fileinfo.filenm)
printf (_(" (from '%s', line %lu)"),
v->fileinfo.filenm, v->fileinfo.lineno);
v->fileinfo.filenm, v->fileinfo.lineno + v->fileinfo.offset);
putchar ('\n');
fputs (prefix, stdout);