bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

fix some error-reporting macro bugs


From: Joel E. Denny
Subject: fix some error-reporting macro bugs
Date: Sun, 7 Oct 2007 21:53:21 -0400 (EDT)

I committed this.

Index: ChangeLog
===================================================================
RCS file: /sources/bison/bison/ChangeLog,v
retrieving revision 1.1731
diff -p -u -r1.1731 ChangeLog
--- ChangeLog   5 Oct 2007 02:54:33 -0000       1.1731
+++ ChangeLog   8 Oct 2007 01:46:32 -0000
@@ -1,3 +1,22 @@
+2007-10-07  Joel E. Denny  <address@hidden>
+
+       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  <address@hidden>
 
        Implement --print-datadir.
Index: data/bison.m4
===================================================================
RCS file: /sources/bison/bison/data/bison.m4,v
retrieving revision 1.21
diff -p -u -r1.21 bison.m4
--- data/bison.m4       25 Sep 2007 05:47:25 -0000      1.21
+++ data/bison.m4       8 Oct 2007 01:46:33 -0000
@@ -61,50 +61,75 @@ version 2.2 of Bison.])])
 ## 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(address@hidden(invalid input@)]])
+m4_define([b4_cat],
+[m4_syscmd([cat <<'_m4eof'
+]m4_bpatsubst(m4_dquote($1), [_m4eof], address@hidden)[@
+_m4eof])dnl
+m4_if(m4_sysval, [0], [], [m4_fatal([$0: cannot write to stdout])])])
+
 # 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_divert_push(0)address@hidden(]$2[]m4_if([$#], [2], [],
-[m4_foreach([b4_arg],
-            m4_dquote(m4_shift(m4_shift($@))),
-            [[@,]b4_arg])])[@)]m4_divert_pop(0)])
+[b4_cat(address@hidden(]$2[]]dnl
+[m4_if([$#], [2], [],
+       [m4_foreach([b4_arg],
+                   m4_dquote(m4_shift(m4_shift($@))),
+                   [[@,]b4_arg])])[@)]])])
 
 # 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_divert_push(0)address@hidden(]$2[@,]$3[@,]$4[]m4_if([$#], [4], [],
-[m4_foreach([b4_arg],
-            m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
-            [[@,]b4_arg])])[@)]m4_divert_pop(0)])
+[b4_cat(address@hidden(]$2[@,]$3[@,]$4[]]dnl
+[m4_if([$#], [4], [],
+       [m4_foreach([b4_arg],
+                   m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))),
+                   [[@,]b4_arg])])[@)]])])
 
 # 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:
 #
+#   m4_divert(-1)
 #   m4_define([asdf], [ASDF])
 #   m4_define([fsa], [FSA])
 #   m4_define([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([asdf), asdf], [fsa), fsa], [fdsa), fdsa])
-#   m4_divert(0)
 #   b4_warn()
-#   m4_divert(0)
 #   b4_warn(1)
-#   m4_divert(0)
 #   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(@)
 #   @warn(1@)
 #   @warn(1@,2@)
@@ -113,37 +138,47 @@ m4_define([b4_warn],
 
 # 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],
 [b4_error_at([[warn]], $@)])
 
 # 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],
 [b4_error([[complain]], $@)])
 
 # 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],
 [b4_error_at([[complain]], $@)])
 
 # 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],
-[b4_error([[fatal]], $@)])
+[b4_error([[fatal]], $@)dnl
+m4_exit(1)])
 
 # 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],
-[b4_error_at([[fatal]], $@)])
+[b4_error_at([[fatal]], $@)dnl
+m4_exit(1)])
 
 
 ## ---------------- ##
Index: src/scan-skel.l
===================================================================
RCS file: /sources/bison/bison/src/scan-skel.l,v
retrieving revision 1.52
diff -p -u -r1.52 scan-skel.l
--- src/scan-skel.l     15 Aug 2007 20:21:31 -0000      1.52
+++ src/scan-skel.l     8 Oct 2007 01:46:34 -0000
@@ -70,9 +70,11 @@ static void fail_for_invalid_at (char co
   char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX];
 %}
 
-"@@"      fputc ('@', yyout);
-"@{"      fputc ('[', yyout);
-"@}"      fputc (']', yyout);
+"@@" fputc ('@', yyout);
+"@{" fputc ('[', yyout);
+"@}" fputc (']', yyout);
+"@`" /* Emtpy.  Used by b4_cat in ../data/bison.m4.  */
address@hidden  /* Likewise.  */
 
 "@oline@"  fprintf (yyout, "%d", out_lineno + 1);
 "@ofile@"  QPUTS (outname);
@@ -87,7 +89,7 @@ static void fail_for_invalid_at (char co
 }
 
   /* This pattern must not match more than the previous @ patterns. */
address@hidden@{}(\n]* fail_for_invalid_at (yytext);
address@hidden@{}`(\n]* fail_for_invalid_at (yytext);
 \n        out_lineno++; ECHO;
 address@hidden    ECHO;
 
@@ -108,6 +110,7 @@ static void fail_for_invalid_at (char co
   "@}" { obstack_1grow (&obstack_for_string, ']'); }
   "@`" /* Emtpy.  Useful for starting an argument
           that begins with whitespace. */
+  @\n  /* Empty.  */
 
   @[,)] {
     if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX)
Index: tests/skeletons.at
===================================================================
RCS file: /sources/bison/bison/tests/skeletons.at,v
retrieving revision 1.7
diff -p -u -r1.7 skeletons.at
--- tests/skeletons.at  28 Aug 2007 07:14:11 -0000      1.7
+++ tests/skeletons.at  8 Oct 2007 01:46:34 -0000
@@ -147,8 +147,6 @@ AT_CLEANUP
 
 AT_SETUP([[%define Boolean variables: invalid skeleton defaults]])
 
-AT_CHECK([[mkdir tmp]])
-
 AT_DATA([[skel.c]],
 [[b4_percent_define_default([[foo]], [[bogus value]])
 b4_percent_define_flag_if([[foo]])
@@ -167,3 +165,98 @@ AT_CHECK([[bison input.y]], [[1]], [[]],
 AT_CLEANUP
 
 
+## --------------------------------------------- ##
+## Complaining during macro argument expansion.  ##
+## --------------------------------------------- ##
+
+AT_SETUP([[Complaining during macro argument expansion]])
+
+AT_DATA([[skel1.c]],
+[[m4@&address@hidden([foow], [b4_warn([[foow fubar]])])
+m4@&address@hidden([foowat], [b4_warn_at([[foow.y:2.3]],
+                                    [[foow.y:5.4]], [[foowat fubar]])])
+m4@&address@hidden([fooc], [b4_complain([[fooc fubar]])])
+m4@&address@hidden([foocat], [b4_complain_at([[fooc.y:1.1]],
+                                        [[fooc.y:10.6]], [[foocat fubar]])])
+m4@&address@hidden([foof], [b4_fatal([[foof fubar]])])
+m4@&address@hidden(foow, [1], [yes])
+m4@&address@hidden(foowat, [1], [yes])
+m4@&address@hidden(fooc, [1], [yes])
+m4@&address@hidden(foocat, [1], [yes])
+m4@&address@hidden(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@&address@hidden([foofat], [b4_fatal_at([[foof.y:12.11]],
+                                       [[foof.y:100.123]], [[foofat fubar]])])
+m4@&address@hidden(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@&address@hidden([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@&address@hidden([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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]