summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2013-04-28 19:09:20 -0400
committerPaul Smith <psmith@gnu.org>2013-04-28 19:09:20 -0400
commitf88eb23b02088e7549c46231d0dfa4ee8d35a365 (patch)
treef4aa139eaa7cd62e90cf918e96e77402b7355f8f
parent441b64335590ab91854b997bec07a9578086d895 (diff)
downloadgunmake-f88eb23b02088e7549c46231d0dfa4ee8d35a365.tar.gz
Ensure error messages are printed with sync'd output.
Enhance the child_error() function so that it will write error output to the child's sync output buffer, if it exists. If it doesn't the output goes to stdout/stderr.
-rw-r--r--ChangeLog7
-rw-r--r--job.c75
-rw-r--r--makeint.h4
-rw-r--r--misc.c73
-rw-r--r--tests/ChangeLog1
-rw-r--r--tests/scripts/features/output-sync8
6 files changed, 145 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 254f926..1144dc2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2013-04-28 Paul Smith <psmith@gnu.org>
+ * makeint.h (message_s, error_s): Functions that print to strings
+ rather than directly to files.
+ * misc.c (message_s, error_s): Create them.
+ * job.c (child_error): Print error messages to the output sync
+ logs, if one exists, rather then directly to the terminal.
+ (reap_children): Move the per-line sync after child_error().
+
* configure.ac: Remove support for pre-ANSI variadic function calls.
* makeint.h: Ditto.
* misc.c: Ditto.
diff --git a/job.c b/job.c
index 6ee6b8f..91da29b 100644
--- a/job.c
+++ b/job.c
@@ -467,19 +467,46 @@ is_bourne_compatible_shell (const char *path)
}
+/* Write a message relating to a child. Write it to the child's output
+ sync file if present, otherwise to the terminal. */
+
+static void
+child_out (const struct child *child, const char *msg, int out)
+{
+ int outfd = out ? child->outfd : child->errfd;
+
+ if (outfd >= 0)
+ {
+ lseek (outfd, 0, SEEK_END);
+ write (outfd, msg, strlen (msg));
+ write (outfd, "\n", 1);
+ }
+ else
+ {
+ FILE *outf = out ? stdout : stderr;
+
+ fputs (msg, outf);
+ putc ('\n', outf);
+ fflush (outf);
+ }
+}
+
/* Write an error message describing the exit status given in
EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.
Append "(ignored)" if IGNORED is nonzero. */
static void
-child_error (const struct file *file,
+child_error (const struct child *child,
int exit_code, int exit_sig, int coredump, int ignored)
{
- const char *nm;
const char *pre = "*** ";
const char *post = "";
const char *dump = "";
- gmk_floc *flocp = &file->cmds->fileinfo;
+ const struct file *f = child->file;
+ gmk_floc *flocp = &f->cmds->fileinfo;
+ const char *msg;
+ const char *nm;
+ unsigned int l;
if (ignored && silent_flag)
return;
@@ -501,18 +528,32 @@ child_error (const struct file *file,
sprintf (a, "%s:%lu", flocp->filenm, flocp->lineno);
nm = a;
}
- message (0, _("%s: recipe for target '%s' failed"), nm, file->name);
+
+ msg = message_s (strlen (nm) + strlen (f->name),
+ 0, _("%s: recipe for target '%s' failed"), nm, f->name);
+ child_out (child, msg, 1);
+
+ l = strlen (pre) + strlen (f->name) + strlen (post);
#ifdef VMS
- if (!(exit_code & 1))
- error (NILF, _("%s[%s] Error 0x%x%s"), pre, file->name, exit_code, post);
+ if (exit_code & 1 != 0)
+ return;
+
+ msg = error_s (l + INTEGER_LENGTH, NILF, _("%s[%s] Error 0x%x%s"),
+ pre, f->name, exit_code, post);
#else
if (exit_sig == 0)
- error (NILF, _("%s[%s] Error %d%s"), pre, file->name, exit_code, post);
+ msg = error_s (l + INTEGER_LENGTH, NILF, _("%s[%s] Error %d%s"),
+ pre, f->name, exit_code, post);
else
- error (NILF, _("%s[%s] %s%s%s"),
- pre, file->name, strsignal (exit_sig), dump, post);
+ {
+ const char *s = strsignal (exit_sig);
+ msg = error_s (l + strlen (s) + strlen (dump),
+ NILF, _("%s[%s] %s%s%s"), pre, f->name, s, dump, post);
+ }
#endif /* VMS */
+
+ child_out (child, msg, 0);
}
@@ -1006,11 +1047,6 @@ reap_children (int block, int err)
c->sh_batch_file = NULL;
}
-#ifdef OUTPUT_SYNC
- if (output_sync == OUTPUT_SYNC_JOB)
- sync_output (c);
-#endif
-
/* If this child had the good stdin, say it is now free. */
if (c->good_stdin)
good_stdin_used = 0;
@@ -1024,7 +1060,7 @@ reap_children (int block, int err)
static int delete_on_error = -1;
if (!dontcare)
- child_error (c->file, exit_code, exit_sig, coredump, 0);
+ child_error (c, exit_code, exit_sig, coredump, 0);
c->file->update_status = 2;
if (delete_on_error == -1)
@@ -1040,7 +1076,7 @@ reap_children (int block, int err)
if (child_failed)
{
/* The commands failed, but we don't care. */
- child_error (c->file, exit_code, exit_sig, coredump, 1);
+ child_error (c, exit_code, exit_sig, coredump, 1);
child_failed = 0;
}
@@ -1057,6 +1093,11 @@ reap_children (int block, int err)
}
else
{
+#ifdef OUTPUT_SYNC
+ /* If we're sync'ing per job, write it now. */
+ if (output_sync == OUTPUT_SYNC_JOB)
+ sync_output (c);
+#endif
/* Check again whether to start remotely.
Whether or not we want to changes over time.
Also, start_remote_job may need state set up
@@ -1089,7 +1130,7 @@ reap_children (int block, int err)
#ifdef OUTPUT_SYNC
/* Synchronize parallel output if requested */
- if (output_sync > OUTPUT_SYNC_JOB)
+ if (output_sync)
sync_output (c);
#endif /* OUTPUT_SYNC */
diff --git a/makeint.h b/makeint.h
index 3b0336e..812ead1 100644
--- a/makeint.h
+++ b/makeint.h
@@ -383,6 +383,10 @@ extern struct rlimit stack_limit;
const char *concat (unsigned int, ...);
+const char *message_s (unsigned int length, int prefix, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+const char *error_s (unsigned int length, const gmk_floc *flocp, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
void message (int prefix, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
void error (const gmk_floc *flocp, const char *fmt, ...)
diff --git a/misc.c b/misc.c
index 366e856..12b9d3d 100644
--- a/misc.c
+++ b/misc.c
@@ -179,6 +179,79 @@ concat (unsigned int num, ...)
return result;
}
+/* If we had a standard-compliant vsnprintf() this would be a lot simpler.
+ Maybe in the future we'll include gnulib's version. */
+
+/* Return a formatted string buffer. */
+
+const char *
+message_s (unsigned int length, int prefix, const char *fmt, ...)
+{
+ static char *buffer = NULL;
+ static unsigned int bsize = 0;
+ char *bp;
+ va_list args;
+
+ /* Compute the maximum buffer size we'll need, and make sure we have it. */
+ length += strlen (fmt) + strlen (program) + 4 + INTEGER_LENGTH + 1;
+ if (length > bsize)
+ {
+ bsize = length * 2;
+ buffer = xrealloc (buffer, bsize);
+ }
+
+ bp = buffer;
+ if (prefix)
+ {
+ if (makelevel == 0)
+ sprintf (bp, "%s: ", program);
+ else
+ sprintf (bp, "%s[%u]: ", program, makelevel);
+ bp += strlen (buffer);
+ }
+
+ va_start (args, fmt);
+ vsprintf (bp, fmt, args);
+ va_end (args);
+
+ return buffer;
+}
+
+/* Return a formatted error message in a buffer. */
+
+const char *
+error_s (unsigned int length, const gmk_floc *flocp, const char *fmt, ...)
+{
+ static char *buffer = NULL;
+ static unsigned int bsize = 0;
+ char *bp;
+ va_list args;
+
+ /* Compute the maximum buffer size we'll need, and make sure we have it. */
+ length += (strlen (fmt) + strlen (program) + 4 + INTEGER_LENGTH + 1
+ + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0));
+ if (length > bsize)
+ {
+ bsize = length * 2;
+ buffer = xrealloc (buffer, bsize);
+ }
+
+ bp = buffer;
+ if (flocp && flocp->filenm)
+ sprintf (bp, "%s:%lu: ", flocp->filenm, flocp->lineno);
+ else if (makelevel == 0)
+ sprintf (bp, "%s: ", program);
+ else
+ sprintf (bp, "%s[%u]: ", program, makelevel);
+ bp += strlen (bp);
+
+ va_start (args, fmt);
+ vsprintf (bp, fmt, args);
+ va_end (args);
+
+ return buffer;
+}
+
/* Print a message on stdout. */
void
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 642ba85..98c5970 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -2,6 +2,7 @@
* scripts/features/output-sync (output_sync_set): Add tests for
the per-job syntax mode.
+ (output_sync_set): Test improved error message location.
2013-04-15 Paul Smith <psmith@gnu.org>
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
index d1b743d..c8ff291 100644
--- a/tests/scripts/features/output-sync
+++ b/tests/scripts/features/output-sync
@@ -197,14 +197,10 @@ bar: end
#MAKE#[1]: Leaving directory '#PWD#/bar'
#MAKE#[1]: Leaving directory '#PWD#/bar'
#MAKE#[1]: Entering directory '#PWD#/foo'
-Makefile:20: recipe for target 'foo-fail' failed
-#MAKE#[1]: Leaving directory '/home/psmith/src/make/make/tests/foo'
-#MAKE#[1]: Entering directory '/home/psmith/src/make/make/tests/foo'
-#MAKE#[1]: *** [foo-fail] Error 1
-#MAKE#[1]: Leaving directory '/home/psmith/src/make/make/tests/foo'
-#MAKE#[1]: Entering directory '/home/psmith/src/make/make/tests/foo'
foo-fail: start
foo-fail: end
+Makefile:20: recipe for target 'foo-fail' failed
+#MAKE#[1]: *** [foo-fail] Error 1
#MAKE#[1]: Leaving directory '#PWD#/foo'
#MAKE#[1]: Leaving directory '#PWD#/foo'
#MAKEFILE#:4: recipe for target 'make-foo-fail' failed