mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
Fix some error-reporting macro bugs.
* data/bison.m4 (b4_cat): New. (b4_error, b4_error_at): Use b4_cat to send error directives directly to stdout so they don't become arguments to other macros. Update comments and add examples. (b4_warn, b4_warn_at, b4_complain, b4_complain_at): Update comments and add examples. (b4_fatal, b4_fatal_at): Likewise, and invoke m4_exit(1) immediately after printing the error directive so that M4 doesn't report subsequent problems that are induced by this problem. * src/scan-skel.l: Recognize @` digraph outside of directive arguments instead of just in them. Recognize @\n in both places. Both expand to the empty string. Needed by b4_cat. * tests/skeletons.at (Complaining during macro argument expansion): New test case. (Fatal errors make M4 exit immediately): New test case.
This commit is contained in:
19
ChangeLog
19
ChangeLog
@@ -1,3 +1,22 @@
|
|||||||
|
2007-10-07 Joel E. Denny <jdenny@ces.clemson.edu>
|
||||||
|
|
||||||
|
Fix some error-reporting macro bugs.
|
||||||
|
* data/bison.m4 (b4_cat): New.
|
||||||
|
(b4_error, b4_error_at): Use b4_cat to send error directives directly
|
||||||
|
to stdout so they don't become arguments to other macros. Update
|
||||||
|
comments and add examples.
|
||||||
|
(b4_warn, b4_warn_at, b4_complain, b4_complain_at): Update comments and
|
||||||
|
add examples.
|
||||||
|
(b4_fatal, b4_fatal_at): Likewise, and invoke m4_exit(1) immediately
|
||||||
|
after printing the error directive so that M4 doesn't report subsequent
|
||||||
|
problems that are induced by this problem.
|
||||||
|
* src/scan-skel.l: Recognize @` digraph outside of directive arguments
|
||||||
|
instead of just in them. Recognize @\n in both places. Both expand to
|
||||||
|
the empty string. Needed by b4_cat.
|
||||||
|
* tests/skeletons.at (Complaining during macro argument expansion):
|
||||||
|
New test case.
|
||||||
|
(Fatal errors make M4 exit immediately): New test case.
|
||||||
|
|
||||||
2007-10-04 Joel E. Denny <jdenny@ces.clemson.edu>
|
2007-10-04 Joel E. Denny <jdenny@ces.clemson.edu>
|
||||||
|
|
||||||
Implement --print-datadir.
|
Implement --print-datadir.
|
||||||
|
|||||||
@@ -61,50 +61,75 @@ version 2.2 of Bison.])])
|
|||||||
## Error handling. ##
|
## Error handling. ##
|
||||||
## ---------------- ##
|
## ---------------- ##
|
||||||
|
|
||||||
|
# The following error handling macros print error directives that should not
|
||||||
|
# become arguments of other macro invocations since they would likely then be
|
||||||
|
# mangled. Thus, they print to stdout directly.
|
||||||
|
|
||||||
|
# b4_cat(TEXT)
|
||||||
|
# ------------
|
||||||
|
# Write TEXT to stdout. Precede the final newline with an @ so that it's
|
||||||
|
# escaped. For example:
|
||||||
|
#
|
||||||
|
# b4_cat([[@complain(invalid input@)]])
|
||||||
|
m4_define([b4_cat],
|
||||||
|
[m4_syscmd([cat <<'_m4eof'
|
||||||
|
]m4_bpatsubst(m4_dquote($1), [_m4eof], [_m4@`eof])[@
|
||||||
|
_m4eof])dnl
|
||||||
|
m4_if(m4_sysval, [0], [], [m4_fatal([$0: cannot write to stdout])])])
|
||||||
|
|
||||||
# b4_error(KIND, FORMAT, [ARG1], [ARG2], ...)
|
# b4_error(KIND, FORMAT, [ARG1], [ARG2], ...)
|
||||||
# -------------------------------------------
|
# -------------------------------------------
|
||||||
# Write @KIND(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @KIND(FORMAT@,ARG1@,ARG2@,...@) to stdout.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# b4_error([[warn]], [[invalid value for `%s': %s]], [[foo]], [[3]])
|
||||||
m4_define([b4_error],
|
m4_define([b4_error],
|
||||||
[m4_divert_push(0)[@]$1[(]$2[]m4_if([$#], [2], [],
|
[b4_cat([[@]$1[(]$2[]]dnl
|
||||||
[m4_foreach([b4_arg],
|
[m4_if([$#], [2], [],
|
||||||
|
[m4_foreach([b4_arg],
|
||||||
m4_dquote(m4_shift(m4_shift($@))),
|
m4_dquote(m4_shift(m4_shift($@))),
|
||||||
[[@,]b4_arg])])[@)]m4_divert_pop(0)])
|
[[@,]b4_arg])])[@)]])])
|
||||||
|
|
||||||
# b4_error_at(KIND, START, END, FORMAT, [ARG1], [ARG2], ...)
|
# b4_error_at(KIND, START, END, FORMAT, [ARG1], [ARG2], ...)
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# Write @KIND(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @KIND_at(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# b4_error_at([[complain]], [[input.y:2.3]], [[input.y:5.4]],
|
||||||
|
# [[invalid %s]], [[foo]])
|
||||||
m4_define([b4_error_at],
|
m4_define([b4_error_at],
|
||||||
[m4_divert_push(0)[@]$1[_at(]$2[@,]$3[@,]$4[]m4_if([$#], [4], [],
|
[b4_cat([[@]$1[_at(]$2[@,]$3[@,]$4[]]dnl
|
||||||
[m4_foreach([b4_arg],
|
[m4_if([$#], [4], [],
|
||||||
|
[m4_foreach([b4_arg],
|
||||||
m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
|
m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
|
||||||
[[@,]b4_arg])])[@)]m4_divert_pop(0)])
|
[[@,]b4_arg])])[@)]])])
|
||||||
|
|
||||||
# b4_warn(FORMAT, [ARG1], [ARG2], ...)
|
# b4_warn(FORMAT, [ARG1], [ARG2], ...)
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
# Write @warn(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @warn(FORMAT@,ARG1@,ARG2@,...@) to stdout.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# b4_warn([[invalid value for `%s': %s]], [[foo]], [[3]])
|
||||||
#
|
#
|
||||||
# As a simple test suite, this:
|
# As a simple test suite, this:
|
||||||
#
|
#
|
||||||
|
# m4_divert(-1)
|
||||||
# m4_define([asdf], [ASDF])
|
# m4_define([asdf], [ASDF])
|
||||||
# m4_define([fsa], [FSA])
|
# m4_define([fsa], [FSA])
|
||||||
# m4_define([fdsa], [FDSA])
|
# m4_define([fdsa], [FDSA])
|
||||||
# b4_warn([[[asdf), asdf]]], [[[fsa), fsa]]], [[[fdsa), fdsa]]])
|
# b4_warn([[[asdf), asdf]]], [[[fsa), fsa]]], [[[fdsa), fdsa]]])
|
||||||
# m4_divert(0)
|
|
||||||
# b4_warn([[asdf), asdf]], [[fsa), fsa]], [[fdsa), fdsa]])
|
# b4_warn([[asdf), asdf]], [[fsa), fsa]], [[fdsa), fdsa]])
|
||||||
# m4_divert(0)
|
|
||||||
# b4_warn([asdf), asdf], [fsa), fsa], [fdsa), fdsa])
|
|
||||||
# m4_divert(0)
|
|
||||||
# b4_warn()
|
# b4_warn()
|
||||||
# m4_divert(0)
|
|
||||||
# b4_warn(1)
|
# b4_warn(1)
|
||||||
# m4_divert(0)
|
|
||||||
# b4_warn(1, 2)
|
# b4_warn(1, 2)
|
||||||
#
|
#
|
||||||
# Should produce this:
|
# Should produce this without newlines:
|
||||||
#
|
#
|
||||||
# @warn([asdf), asdf]@,[fsa), fsa]@,[fdsa), fdsa]@)
|
# @warn([asdf), asdf]@,[fsa), fsa]@,[fdsa), fdsa]@)
|
||||||
# @warn(asdf), asdf@,fsa), fsa@,fdsa), fdsa@)
|
# @warn(asdf), asdf@,fsa), fsa@,fdsa), fdsa@)
|
||||||
# @warn(ASDF), ASDF@,FSA), FSA@,FDSA), FDSA@)
|
|
||||||
# @warn(@)
|
# @warn(@)
|
||||||
# @warn(1@)
|
# @warn(1@)
|
||||||
# @warn(1@,2@)
|
# @warn(1@,2@)
|
||||||
@@ -113,37 +138,47 @@ m4_define([b4_warn],
|
|||||||
|
|
||||||
# b4_warn_at(START, END, FORMAT, [ARG1], [ARG2], ...)
|
# b4_warn_at(START, END, FORMAT, [ARG1], [ARG2], ...)
|
||||||
# ---------------------------------------------------
|
# ---------------------------------------------------
|
||||||
# Write @warn(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @warn(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# b4_warn_at([[input.y:2.3]], [[input.y:5.4]], [[invalid %s]], [[foo]])
|
||||||
m4_define([b4_warn_at],
|
m4_define([b4_warn_at],
|
||||||
[b4_error_at([[warn]], $@)])
|
[b4_error_at([[warn]], $@)])
|
||||||
|
|
||||||
# b4_complain(FORMAT, [ARG1], [ARG2], ...)
|
# b4_complain(FORMAT, [ARG1], [ARG2], ...)
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
# Write @complain(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @complain(FORMAT@,ARG1@,ARG2@,...@) to stdout.
|
||||||
#
|
#
|
||||||
# See the test suite for b4_warn above.
|
# See b4_warn example.
|
||||||
m4_define([b4_complain],
|
m4_define([b4_complain],
|
||||||
[b4_error([[complain]], $@)])
|
[b4_error([[complain]], $@)])
|
||||||
|
|
||||||
# b4_complain_at(START, END, FORMAT, [ARG1], [ARG2], ...)
|
# b4_complain_at(START, END, FORMAT, [ARG1], [ARG2], ...)
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
# Write @complain(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @complain(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout.
|
||||||
|
#
|
||||||
|
# See b4_warn_at example.
|
||||||
m4_define([b4_complain_at],
|
m4_define([b4_complain_at],
|
||||||
[b4_error_at([[complain]], $@)])
|
[b4_error_at([[complain]], $@)])
|
||||||
|
|
||||||
# b4_fatal(FORMAT, [ARG1], [ARG2], ...)
|
# b4_fatal(FORMAT, [ARG1], [ARG2], ...)
|
||||||
# -------------------------------------
|
# -------------------------------------
|
||||||
# Write @fatal(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @fatal(FORMAT@,ARG1@,ARG2@,...@) to stdout and exit.
|
||||||
#
|
#
|
||||||
# See the test suite for b4_warn above.
|
# See b4_warn example.
|
||||||
m4_define([b4_fatal],
|
m4_define([b4_fatal],
|
||||||
[b4_error([[fatal]], $@)])
|
[b4_error([[fatal]], $@)dnl
|
||||||
|
m4_exit(1)])
|
||||||
|
|
||||||
# b4_fatal_at(START, END, FORMAT, [ARG1], [ARG2], ...)
|
# b4_fatal_at(START, END, FORMAT, [ARG1], [ARG2], ...)
|
||||||
# ----------------------------------------------------
|
# ----------------------------------------------------
|
||||||
# Write @fatal(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
|
# Write @fatal(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to stdout and exit.
|
||||||
|
#
|
||||||
|
# See b4_warn_at example.
|
||||||
m4_define([b4_fatal_at],
|
m4_define([b4_fatal_at],
|
||||||
[b4_error_at([[fatal]], $@)])
|
[b4_error_at([[fatal]], $@)dnl
|
||||||
|
m4_exit(1)])
|
||||||
|
|
||||||
|
|
||||||
## ---------------- ##
|
## ---------------- ##
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ static void fail_for_invalid_at (char const *at);
|
|||||||
"@@" fputc ('@', yyout);
|
"@@" fputc ('@', yyout);
|
||||||
"@{" fputc ('[', yyout);
|
"@{" fputc ('[', yyout);
|
||||||
"@}" fputc (']', yyout);
|
"@}" fputc (']', yyout);
|
||||||
|
"@`" /* Emtpy. Used by b4_cat in ../data/bison.m4. */
|
||||||
|
@\n /* Likewise. */
|
||||||
|
|
||||||
"@oline@" fprintf (yyout, "%d", out_lineno + 1);
|
"@oline@" fprintf (yyout, "%d", out_lineno + 1);
|
||||||
"@ofile@" QPUTS (outname);
|
"@ofile@" QPUTS (outname);
|
||||||
@@ -87,7 +89,7 @@ static void fail_for_invalid_at (char const *at);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* This pattern must not match more than the previous @ patterns. */
|
/* This pattern must not match more than the previous @ patterns. */
|
||||||
@[^@{}(\n]* fail_for_invalid_at (yytext);
|
@[^@{}`(\n]* fail_for_invalid_at (yytext);
|
||||||
\n out_lineno++; ECHO;
|
\n out_lineno++; ECHO;
|
||||||
[^@\n]+ ECHO;
|
[^@\n]+ ECHO;
|
||||||
|
|
||||||
@@ -108,6 +110,7 @@ static void fail_for_invalid_at (char const *at);
|
|||||||
"@}" { obstack_1grow (&obstack_for_string, ']'); }
|
"@}" { obstack_1grow (&obstack_for_string, ']'); }
|
||||||
"@`" /* Emtpy. Useful for starting an argument
|
"@`" /* Emtpy. Useful for starting an argument
|
||||||
that begins with whitespace. */
|
that begins with whitespace. */
|
||||||
|
@\n /* Empty. */
|
||||||
|
|
||||||
@[,)] {
|
@[,)] {
|
||||||
if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
|
if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
|
||||||
|
|||||||
@@ -147,8 +147,6 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([[%define Boolean variables: invalid skeleton defaults]])
|
AT_SETUP([[%define Boolean variables: invalid skeleton defaults]])
|
||||||
|
|
||||||
AT_CHECK([[mkdir tmp]])
|
|
||||||
|
|
||||||
AT_DATA([[skel.c]],
|
AT_DATA([[skel.c]],
|
||||||
[[b4_percent_define_default([[foo]], [[bogus value]])
|
[[b4_percent_define_default([[foo]], [[bogus value]])
|
||||||
b4_percent_define_flag_if([[foo]])
|
b4_percent_define_flag_if([[foo]])
|
||||||
@@ -167,3 +165,98 @@ AT_CHECK([[bison input.y]], [[1]], [[]],
|
|||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
|
||||||
|
## --------------------------------------------- ##
|
||||||
|
## Complaining during macro argument expansion. ##
|
||||||
|
## --------------------------------------------- ##
|
||||||
|
|
||||||
|
AT_SETUP([[Complaining during macro argument expansion]])
|
||||||
|
|
||||||
|
AT_DATA([[skel1.c]],
|
||||||
|
[[m4@&t@_define([foow], [b4_warn([[foow fubar]])])
|
||||||
|
m4@&t@_define([foowat], [b4_warn_at([[foow.y:2.3]],
|
||||||
|
[[foow.y:5.4]], [[foowat fubar]])])
|
||||||
|
m4@&t@_define([fooc], [b4_complain([[fooc fubar]])])
|
||||||
|
m4@&t@_define([foocat], [b4_complain_at([[fooc.y:1.1]],
|
||||||
|
[[fooc.y:10.6]], [[foocat fubar]])])
|
||||||
|
m4@&t@_define([foof], [b4_fatal([[foof fubar]])])
|
||||||
|
m4@&t@_if(foow, [1], [yes])
|
||||||
|
m4@&t@_if(foowat, [1], [yes])
|
||||||
|
m4@&t@_if(fooc, [1], [yes])
|
||||||
|
m4@&t@_if(foocat, [1], [yes])
|
||||||
|
m4@&t@_if(foof, [1], [yes])
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_DATA([[input1.y]],
|
||||||
|
[[%skeleton "./skel1.c"
|
||||||
|
%%
|
||||||
|
start: ;
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CHECK([[bison input1.y]], [[1]], [[]],
|
||||||
|
[[input1.y: warning: foow fubar
|
||||||
|
foow.y:2.3-5.3: warning: foowat fubar
|
||||||
|
input1.y: fooc fubar
|
||||||
|
fooc.y:1.1-10.5: foocat fubar
|
||||||
|
input1.y: fatal error: foof fubar
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_DATA([[skel2.c]],
|
||||||
|
[[m4@&t@_define([foofat], [b4_fatal_at([[foof.y:12.11]],
|
||||||
|
[[foof.y:100.123]], [[foofat fubar]])])
|
||||||
|
m4@&t@_if(foofat, [1], [yes])
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_DATA([[input2.y]],
|
||||||
|
[[%skeleton "./skel2.c"
|
||||||
|
%%
|
||||||
|
start: ;
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CHECK([[bison input2.y]], [[1]], [[]],
|
||||||
|
[[foof.y:12.11-100.122: fatal error: foofat fubar
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CLEANUP
|
||||||
|
|
||||||
|
|
||||||
|
## --------------------------------------- ##
|
||||||
|
## Fatal errors make M4 exit immediately. ##
|
||||||
|
## --------------------------------------- ##
|
||||||
|
|
||||||
|
AT_SETUP([[Fatal errors make M4 exit immediately]])
|
||||||
|
|
||||||
|
AT_DATA([[skel1.c]],
|
||||||
|
[[b4_complain([[non-fatal error]])
|
||||||
|
b4_fatal([[M4 should exit immediately here]])
|
||||||
|
m4@&t@_fatal([this should never be evaluated])
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_DATA([[input1.y]],
|
||||||
|
[[%skeleton "./skel1.c"
|
||||||
|
%%
|
||||||
|
start: ;
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CHECK([[bison input1.y]], [[1]], [[]],
|
||||||
|
[[input1.y: non-fatal error
|
||||||
|
input1.y: fatal error: M4 should exit immediately here
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_DATA([[skel2.c]],
|
||||||
|
[[b4_warn([[morning]])
|
||||||
|
b4_fatal_at([[foo.y:1.5]], [[foo.y:1.7]], [[M4 should exit immediately here]])
|
||||||
|
m4@&t@_fatal([this should never be evaluated])
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_DATA([[input2.y]],
|
||||||
|
[[%skeleton "./skel2.c"
|
||||||
|
%%
|
||||||
|
start: ;
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CHECK([[bison input2.y]], [[1]], [[]],
|
||||||
|
[[input2.y: warning: morning
|
||||||
|
foo.y:1.5-6: fatal error: M4 should exit immediately here
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CLEANUP
|
||||||
|
|||||||
Reference in New Issue
Block a user