-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Gary,
According to Gary V. Vaughan on 8/4/2006 2:50 AM: > Hi Eric, > > Eric Blake wrote: >> Would it be worth adding __program__ macro, to go along with __file__ and >> __line__, which expands to argv[0] in the same manner that error messages >> do? That way, if a user invokes m4 via a symlink or absolute path, rather >> than through their PATH, they can match internal m4 messages. They can >> also use that information to invoke a sub-m4 in syscmd using the same >> version of m4 currently running, rather than picking up an arbitrary m4 >> from PATH. > > Yes, I think that is an excellent idea. With that recommendation, branch-1_4 now follows GNU Coding Standards in its error messages. Man, I wish I could get glibc to provide a va_list variant of error/error_at_line (I'm in the process of proposing that, trying to bring gnulib and glibc back in sync and fix other bugs in the error.c module). Without it, and due to the fact that error_print_progname takes no arguments, I have to use the relatively gross hack of another global variable that tells the callback whether it was invoked from error or error_at_line. 2006-08-04 Eric Blake <[EMAIL PROTECTED]> * src/m4.h (program_name): Declare. (suppress_line): New variable. (M4ERROR_AT_LINE): New macro. * src/m4.c (reference_error, main): Follow GNU Coding Standards for error message format. * src/input.c (skip_line, next_token): Use M4ERROR_AT_LINE. * src/macro.c (expand_argument): Likewise. * checks/check-them (examples): Adjust to new message format. * src/builtin.c (m4___program__): New builtin. * doc/m4.texinfo (Location): Split from Errprint into new node, and document __program__. (Builtin, Ifdef, Ifelse, Dumpdef, Trace, Debug Output, Dnl) (Include, Regexp, Patsubst, Incr, Eval): Adjust error message format. (Extensions): Document __program__. * NEWS: Document this change. - -- Life is short - so eat dessert first! Eric Blake [EMAIL PROTECTED] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.1 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFE00k084KuGfSFAYARAhNmAJ48td8V2S9nfJ0D8YTdsQn0vwzUzACg1JsV AS9v4xjFMxJ+JN3Ej8fgroI= =Ylh0 -----END PGP SIGNATURE-----
Index: NEWS =================================================================== RCS file: /sources/m4/m4/NEWS,v retrieving revision 1.1.1.1.2.48 diff -u -p -r1.1.1.1.2.48 NEWS --- NEWS 3 Aug 2006 13:31:40 -0000 1.1.1.1.2.48 +++ NEWS 4 Aug 2006 13:16:26 -0000 @@ -25,6 +25,9 @@ Version 1.4.6 - ?? 2006, by ?? (CVS ver * The changequote and changecom macros now work with 8-bit characters, and quotes and strings that begin with `(' are properly recognized following a word. +* The new macro __program__ is added, which allows the input file to issue + an error message that resembles messages from m4. Warning and error + messages have been reformatted to comply with GNU Coding Standards. Version 1.4.5 - 15 July 2006, by Eric Blake (CVS version 1.4.4c) Index: checks/check-them =================================================================== RCS file: /sources/m4/m4/checks/Attic/check-them,v retrieving revision 1.1.1.1.2.9 diff -u -p -r1.1.1.1.2.9 check-them --- checks/check-them 30 Jul 2006 21:46:10 -0000 1.1.1.1.2.9 +++ checks/check-them 4 Aug 2006 13:16:26 -0000 @@ -66,7 +66,7 @@ do diff $xout $out fi - sed -e '/^dnl @error{}/!d' -e 's///' -e "s| m4:| $m4:|" "$file" > $xerr + sed -e '/^dnl @error{}/!d' -e 's///' -e "s|^m4:|$m4:|" "$file" > $xerr if cmp -s $err $xerr; then : Index: doc/m4.texinfo =================================================================== RCS file: /sources/m4/m4/doc/m4.texinfo,v retrieving revision 1.1.1.1.2.60 diff -u -p -r1.1.1.1.2.60 m4.texinfo --- doc/m4.texinfo 3 Aug 2006 13:31:40 -0000 1.1.1.1.2.60 +++ doc/m4.texinfo 4 Aug 2006 13:16:27 -0000 @@ -234,6 +234,7 @@ Running shell commands Miscellaneous builtin macros * Errprint:: Printing error messages +* Location:: Printing current location * M4exit:: Exiting from m4 Fast loading of frozen state @@ -1680,13 +1681,13 @@ provoke a warning, and result in a void builtin @result{}builtin builtin() [EMAIL PROTECTED]:2: m4: undefined builtin `' [EMAIL PROTECTED]:stdin:2: undefined builtin `' @result{} builtin(`builtin') [EMAIL PROTECTED]:3: m4: Warning: too few arguments to builtin `builtin' [EMAIL PROTECTED]:stdin:3: Warning: too few arguments to builtin `builtin' @result{} builtin(`builtin',) [EMAIL PROTECTED]:4: m4: undefined builtin `' [EMAIL PROTECTED]:stdin:4: undefined builtin `' @result{} @end example @@ -1729,7 +1730,7 @@ define(`foo', `') ifdef(`foo', ``foo' is defined', ``foo' is not defined') @result{}foo is defined ifdef(`no_such_macro', `yes', `no', `extra argument') [EMAIL PROTECTED]:4: m4: Warning: excess arguments to builtin `ifdef' ignored [EMAIL PROTECTED]:stdin:4: Warning: excess arguments to builtin `ifdef' ignored @result{}no @end example @@ -1770,7 +1771,7 @@ case, the warning about missing argument ifelse(`some comments') @result{} ifelse(`foo', `bar') [EMAIL PROTECTED]:2: m4: Warning: too few arguments to builtin `ifelse' [EMAIL PROTECTED]:stdin:2: Warning: too few arguments to builtin `ifelse' @result{} @end example @@ -2005,7 +2006,7 @@ f(popdef(`f')dumpdef(`f')) @error{}f:@tabchar{}``$0'1' @result{}f2 f(popdef(`f')dumpdef(`f')) [EMAIL PROTECTED]:3: m4: undefined macro `f' [EMAIL PROTECTED]:stdin:3: undefined macro `f' @result{}f1 @end example @@ -2078,7 +2079,7 @@ undefine(`foo') ifdef(`foo', `yes', `no') @result{}no indir(`foo') [EMAIL PROTECTED]:8: m4: undefined macro `foo' [EMAIL PROTECTED]:stdin:8: undefined macro `foo' @result{} define(`foo', `blah') @result{} @@ -2235,13 +2236,13 @@ The expansion of @code{debugfile} is voi traceon(`divnum') @result{} divnum(`extra') [EMAIL PROTECTED]:2: m4: Warning: excess arguments to builtin `divnum' ignored [EMAIL PROTECTED]:stdin:2: Warning: excess arguments to builtin `divnum' ignored @error{}m4trace: -1- divnum(`extra') -> `0' @result{}0 debugfile() @result{} divnum(`extra') [EMAIL PROTECTED]:4: m4: Warning: excess arguments to builtin `divnum' ignored [EMAIL PROTECTED]:stdin:4: Warning: excess arguments to builtin `divnum' ignored @result{}0 debugfile @result{} @@ -2301,7 +2302,7 @@ next newline, on whatever line containin @example dnl(`args are ignored, but side effects occur', define(`foo', `like this')) while this text is ignored: undefine(`foo') [EMAIL PROTECTED]:2: m4: Warning: excess arguments to builtin `dnl' ignored [EMAIL PROTECTED]:stdin:2: Warning: excess arguments to builtin `dnl' ignored See how `foo' was defined, foo? @result{}See how foo was defined, like this? @end example @@ -2879,10 +2880,10 @@ parameters. @example include(`none') @result{} [EMAIL PROTECTED]:1: m4: cannot open `none': No such file or directory [EMAIL PROTECTED]:stdin:1: cannot open `none': No such file or directory include() @result{} [EMAIL PROTECTED]:2: m4: cannot open `': No such file or directory [EMAIL PROTECTED]:stdin:2: cannot open `': No such file or directory sinclude(`none') @result{} sinclude() @@ -3333,8 +3334,8 @@ Here are some more examples on the handl regexp(`abc', `\(b\)', `\\\10\a') @result{}\b0a regexp(`abc', `b', `\1\') [EMAIL PROTECTED]:2: m4: Warning: sub-expression 1 not present [EMAIL PROTECTED]:2: m4: Warning: trailing \ ignored in replacement [EMAIL PROTECTED]:stdin:2: Warning: sub-expression 1 not present [EMAIL PROTECTED]:stdin:2: Warning: trailing \ ignored in replacement @result{} @end example @@ -3455,7 +3456,7 @@ patsubst(`GNUs not Unix', `\w+', `(\&)') patsubst(`GNUs not Unix', `[A-Z][a-z]+') @result{}GN not @comment patsubst(`GNUs not Unix', `not', `NOT\') [EMAIL PROTECTED]:6: m4: Warning: trailing \ ignored in replacement [EMAIL PROTECTED]:stdin:6: Warning: trailing \ ignored in replacement @result{}GNUs NOT Unix @end example @@ -3603,10 +3604,10 @@ incr(`4') decr(`7') @result{}6 incr() [EMAIL PROTECTED]:3: m4: empty string treated as 0 in builtin `incr' [EMAIL PROTECTED]:stdin:3: empty string treated as 0 in builtin `incr' @result{}1 decr() [EMAIL PROTECTED]:4: m4: empty string treated as 0 in builtin `decr' [EMAIL PROTECTED]:stdin:4: empty string treated as 0 in builtin `decr' @result{}-1 @end example @@ -3705,7 +3706,7 @@ square(square(`5')`+1') define(`foo', `666') @result{} eval(`foo/6') [EMAIL PROTECTED]:8: m4: bad expression in eval: foo/6 [EMAIL PROTECTED]:stdin:8: bad expression in eval: foo/6 @result{} eval(foo/6) @result{}111 @@ -4047,6 +4048,7 @@ any of the previous chapters. @menu * Errprint:: Printing error messages +* Location:: Printing current location * M4exit:: Exiting from m4 @end menu @@ -4078,17 +4080,22 @@ implementations of @code{m4} do append a @code{errprint} call, while some other implementations only print the first argument. -To make it possible to specify the location of the error, two [EMAIL PROTECTED] Location [EMAIL PROTECTED] Printing current location + +To make it possible to specify the location of an error, three utility builtins exist: @deffn Builtin __file__ @deffnx Builtin __line__ -Expand to the quoted name of the current input file, and the -current input line number in that file. [EMAIL PROTECTED] Builtin __program__ +Expand to the quoted name of the current input file, the +current input line number in that file, and the quoted name of the +current invocation of @code{m4}. @end deffn @example -errprint(`m4:'__file__:__line__: `input error +errprint(__program__:__file__:__line__: `input error ') @error{}m4:stdin:1: input error @result{} @@ -4119,6 +4126,16 @@ as though it came from line 0 of the fil future release of @code{m4} can overcome this limitation and remember which file invoked the call to @code{m4wrap}. +The @code{__program__} macro behaves like @samp{$0} in shell +terminology. If you invoke @code{m4} through an absolute path or a link +with a different spelling, rather than by relying on a @env{PATH} search +for plain @samp{m4}, it will affect how @code{__program__} expands. The +intent is that you can use it to produce error messages with the same +formatting that @code{m4} produces internally. It can also be used +within @code{syscmd} (@pxref{Syscmd}) to pick the same version of [EMAIL PROTECTED] that is currently running, rather than whatever version of [EMAIL PROTECTED] happens to be first in @env{PATH}. + @node M4exit @section Exiting from @code{m4} @@ -4144,7 +4161,7 @@ resulting string to standard error. @example define(`fatal_error', - `errprint(`m4:'__file__:__line__`: fatal error: $* + `errprint(__program__:__file__:__line__`: fatal error: $* ')m4exit(`1')') @result{} fatal_error(`this is a BAD one, buster') @@ -4450,9 +4467,9 @@ There is indirect access to any builtin Macros can be called indirectly through @code{indir} (@pxref{Indir}). @item -The name of the current input file and the current input line number are -accessible through the builtins @code{__file__} and @code{__line__} -(@pxref{Errprint}). +The name of the program, the current input file, and the current input +line number are accessible through the builtins @code{__program__}, [EMAIL PROTECTED], and @code{__line__} (@pxref{Location}). @item The format of the output from @code{dumpdef} and macro tracing can be Index: src/builtin.c =================================================================== RCS file: /sources/m4/m4/src/Attic/builtin.c,v retrieving revision 1.1.1.1.2.30 diff -u -p -r1.1.1.1.2.30 builtin.c --- src/builtin.c 30 Jul 2006 23:46:51 -0000 1.1.1.1.2.30 +++ src/builtin.c 4 Aug 2006 13:16:27 -0000 @@ -43,6 +43,7 @@ extern FILE *popen (); DECLARE (m4___file__); DECLARE (m4___line__); +DECLARE (m4___program__); DECLARE (m4_builtin); DECLARE (m4_changecom); DECLARE (m4_changequote); @@ -97,6 +98,7 @@ builtin_tab[] = { "__file__", TRUE, FALSE, FALSE, m4___file__ }, { "__line__", TRUE, FALSE, FALSE, m4___line__ }, + { "__program__", TRUE, FALSE, FALSE, m4___program__ }, { "builtin", TRUE, FALSE, TRUE, m4_builtin }, { "changecom", FALSE, FALSE, FALSE, m4_changecom }, { "changequote", FALSE, FALSE, FALSE, m4_changequote }, @@ -1192,8 +1194,8 @@ m4_sinclude (struct obstack *obs, int ar include (argc, argv, TRUE); } -/* More miscellaneous builtins -- "maketemp", "errprint", "__file__" and - "__line__". The last two are GNU specific. */ +/* More miscellaneous builtins -- "maketemp", "errprint", "__file__", + "__line__", and "__program__". The last three are GNU specific. */ /*------------------------------------------------------------------. | Use the first argument as at template for a temporary file name. | @@ -1246,6 +1248,16 @@ m4___line__ (struct obstack *obs, int ar return; shipout_int (obs, current_line); } + +static void +m4___program__ (struct obstack *obs, int argc, token_data **argv) +{ + if (bad_argc (argv[0], argc, 1, 1)) + return; + obstack_grow (obs, lquote.string, lquote.length); + obstack_grow (obs, program_name, strlen (program_name)); + obstack_grow (obs, rquote.string, rquote.length); +} /* This section contains various macros for exiting, saving input until EOF is seen, and tracing macro calls. That is: "m4exit", "m4wrap", Index: src/input.c =================================================================== RCS file: /sources/m4/m4/src/Attic/input.c,v retrieving revision 1.1.1.1.2.17 diff -u -p -r1.1.1.1.2.17 input.c --- src/input.c 3 Aug 2006 13:31:40 -0000 1.1.1.1.2.17 +++ src/input.c 4 Aug 2006 13:16:27 -0000 @@ -537,8 +537,8 @@ skip_line (void) if (ch == CHAR_EOF) /* current_file changed to "NONE" if we see CHAR_EOF, use the previous value we stored earlier. */ - error_at_line (warning_status, 0, file, line, - "Warning: end of file treated as newline"); + M4ERROR_AT_LINE ((warning_status, 0, file, line, + "Warning: end of file treated as newline")); } @@ -808,8 +808,8 @@ next_token (token_data *td) else /* current_file changed to "NONE" if we see CHAR_EOF, use the previous value we stored earlier. */ - error_at_line (EXIT_FAILURE, 0, file, line, - "ERROR: end of file in comment"); + M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, + "ERROR: end of file in comment")); type = TOKEN_STRING; } @@ -890,8 +890,8 @@ next_token (token_data *td) if (ch == CHAR_EOF) /* current_file changed to "NONE" if we see CHAR_EOF, use the previous value we stored earlier. */ - error_at_line (EXIT_FAILURE, 0, file, line, - "ERROR: end of file in string"); + M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, + "ERROR: end of file in string")); if (MATCH (ch, rquote.string, TRUE)) { Index: src/m4.c =================================================================== RCS file: /sources/m4/m4/src/Attic/m4.c,v retrieving revision 1.1.1.1.2.24 diff -u -p -r1.1.1.1.2.24 m4.c --- src/m4.c 30 Jul 2006 23:46:51 -0000 1.1.1.1.2.24 +++ src/m4.c 4 Aug 2006 13:16:27 -0000 @@ -86,18 +86,27 @@ typedef struct macro_definition macro_de /* Error handling functions. */ -/*-------------------------------------------------------------------------. -| Print source and line reference on standard error, as a prefix for error | -| messages. Flush standard output first. | -`-------------------------------------------------------------------------*/ +/* TRUE if error_at_line was called. Too bad the error module doesn't + let us pass a parameter to the callback, or take a va_list + argument. */ +boolean suppress_line; + +/*---------------------------------------------------------------. +| Callback used by error to print program name, source, and line | +| reference. | +`---------------------------------------------------------------*/ void reference_error (void) { - int e = errno; - fflush (stdout); - fprintf (stderr, "%s:%d: ", current_file, current_line); - errno = e; + /* error already flushed stdout before calling us. */ + if (suppress_line) + { + fprintf (stderr, "%s:", program_name); + suppress_line = FALSE; + } + else + fprintf (stderr, "%s:%s:%d: ", program_name, current_file, current_line); } #ifdef USE_STACKOVF @@ -269,6 +278,7 @@ main (int argc, char *const *argv, char FILE *fp; program_name = argv[0]; + error_print_progname = reference_error; retcode = EXIT_SUCCESS; include_init (); Index: src/m4.h =================================================================== RCS file: /sources/m4/m4/src/m4.h,v retrieving revision 1.1.1.1.2.24 diff -u -p -r1.1.1.1.2.24 m4.h --- src/m4.h 3 Aug 2006 13:31:40 -0000 1.1.1.1.2.24 +++ src/m4.h 4 Aug 2006 13:16:27 -0000 @@ -90,6 +90,18 @@ typedef struct string STRING; /* Those must come first. */ typedef struct token_data token_data; typedef void builtin_func (struct obstack *, int, token_data **); + +/* Take advantage of GNU C compiler source level optimization hints, + using portable macros. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6) +# define M4_GNUC_ATTRIBUTE(args) __attribute__(args) +#else +# define M4_GNUC_ATTRIBUTE(args) +#endif /* __GNUC__ */ + +#define M4_GNUC_UNUSED M4_GNUC_ATTRIBUTE((__unused__)) +#define M4_GNUC_PRINTF(fmt, arg) \ + M4_GNUC_ATTRIBUTE((__format__ (__printf__, fmt, arg))) /* File: m4.c --- global definitions. */ @@ -109,9 +121,32 @@ extern const char *user_word_regexp; /* /* Error handling. */ extern int retcode; -#define M4ERROR(Arglist) \ - (reference_error (), error Arglist) +extern const char *program_name; + +/* It would be so much nicer if the gnulib error module provided a + va_list version of error, so that we wouldn't need to use macros + and a global hook variable. Oh well. */ +#if 0 +void m4_error (int, int, const char *, ...) M4_GNUC_PRINTF(3, 4); +/* Would be implemented as: +void +m4_error (int status, int errnum, const char *format, ...) +{ + va_list args; + va_start (args, format); + verror_at_line (status, errnum, current_file, current_line, format, args); +} +*/ +#endif +#define M4ERROR(Arglist) (error Arglist) +#define M4ERROR_AT_LINE(Arglist) do { \ + suppress_line = TRUE; \ + (error_at_line Arglist); \ + } while (0) + + +extern boolean suppress_line; void reference_error (void); #ifdef USE_STACKOVF @@ -441,13 +476,3 @@ void reload_frozen_state (const char *); a bit safer than casting to unsigned char, since it catches some type errors that the cast doesn't. */ static inline unsigned char to_uchar (char ch) { return ch; } - -/* Take advantage of GNU C compiler source level optimization hints, - using portable macros. */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) -# define M4_GNUC_ATTRIBUTE(args) __attribute__(args) -#else -# define M4_GNUC_ATTRIBUTE(args) -#endif /* __GNUC__ */ - -#define M4_GNUC_UNUSED M4_GNUC_ATTRIBUTE((unused)) Index: src/macro.c =================================================================== RCS file: /sources/m4/m4/src/Attic/macro.c,v retrieving revision 1.1.1.1.2.9 diff -u -p -r1.1.1.1.2.9 macro.c --- src/macro.c 3 Aug 2006 13:31:40 -0000 1.1.1.1.2.9 +++ src/macro.c 4 Aug 2006 13:16:27 -0000 @@ -167,8 +167,8 @@ expand_argument (struct obstack *obs, to case TOKEN_EOF: /* current_file changed to "NONE" if we see TOKEN_EOF, use the previous value we stored earlier. */ - error_at_line (EXIT_FAILURE, 0, file, line, - "ERROR: end of file in argument list"); + M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line, + "ERROR: end of file in argument list")); break; case TOKEN_WORD:
_______________________________________________ M4-discuss mailing list M4-discuss@gnu.org http://lists.gnu.org/mailman/listinfo/m4-discuss