bug-bison
[Top][All Lists]
Advanced

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

[PATCH] Fix variadic declaration of yyerror() and yylex() function proto


From: Jeannot Langlois
Subject: [PATCH] Fix variadic declaration of yyerror() and yylex() function prototypes
Date: Tue, 24 May 2005 21:11:56 -0400
User-agent: Mozilla Thunderbird 0.8 (X11/20040913)

Hi Mr. Eggert,


I have been working with Bison 2.0 for some time, and noticed a couple of warning messages when I recently added "-Wall" to my Bison-generated C parser compile rule:

--------[SNIP]--------
gcc -o myparser myparser.tab.c my_scanner.c -DYYERROR_VERBOSE=1 -g -Wall `pkg-config glib-2.0 --cflags` `pkg-config glib-2.0 --libs`
ircparser.tab.c: In function `yyFail':
ircparser.tab.c:2169: warning: implicit declaration of function `yyerror'
ircparser.tab.c: In function `yyprocessOneStack':
ircparser.tab.c:7746: warning: implicit declaration of function `yylex'
--------[SNIP]--------

(This is a reentrant, glr grammar that makes use of one %lex-param and two %parse-param directives).

Apparently, the default function prototypes declarations for yylex() and yyerror() are NOT being generated by Bison as I would expect.

I was *really* motivated into fixing this as the warnings were annoying me (I thought it would be easy, but it actually took me several days to debug and understand many quoting tricks as I am a M4 newbie (which quites reminds me LISP nightmares :-))).

I didn't want to manually do the yyerror() and yylex() C protypes declarations myself in the prologue section as I am using %lex-param, I would also need to declare YYSTYPE in the prologue section manually (since the YYSTYPE declaration apparently happens *AFTER* the prologue section) so it would be recognized as a valid type for the yyerror() prototype declaration, which quite defeats the user-friendlyness of %union and gets my parser's grammar file way too complicated just to fix two simple warnings.

So, I started playing around with both yacc.c and glr.c skeleton files and after a few days of (work/pain) with M4, I managed to add necessary macros to autogenerate the variadic signatures of yylex() and yyerror() automagically - and the good news is that it apparently works in all cases ( at least with C-parser generation of lalr/glr impure/pure grammars - I haven't done any modifications for C++ code generation ).
I have ran the Bison testsuite several times and *most* tests cases are ok.

In fact, the only problems I have faced and could not solve properly were with testcases #117 through #126 of the testsuite, because of this common code they all contain the following:

--------[SNIP - prologue section]--------
%{
 #include <stdio.h>
 #define YYSTYPE char const *

 #define YYINITDEPTH 10
 static char *format (char const *, ...);
 struct YYLTYPE;
#if YYPURE
# if YYLSP_NEEDED
#  define LEX_PARAMETERS YYSTYPE *lvalp, struct YYLTYPE *llocp
#  define ERROR_PARAMETERS struct YYLTYPE *llocp, char const *s
# else
#  define LEX_PARAMETERS YYSTYPE *lvalp
# endif
#endif
#ifndef LEX_PARAMETERS
# define LEX_PARAMETERS void
#endif
#ifndef ERROR_PARAMETERS
# define ERROR_PARAMETERS char const *s
#endif
 int yylex (LEX_PARAMETERS);
 int yyerror (ERROR_PARAMETERS);
%}
--------[SNIP]--------


--------[SNIP - epilogue section ]--------
int
yyerror (ERROR_PARAMETERS)
{
#if YYPURE && YYLSP_NEEDED
 /* Pacify GCC by using llocp.  */
 if (! llocp)
   abort ();
#endif
 fprintf (stderr, "%s\n", s);
 return 0;
}
--------[SNIP]--------


The testcases are failing not because of incorrectly-generated yyerror() input parameters as I would have expected, but rather because the return value is different. As shown above, testscases #117 through #126 all use "int" as the return value for yyerror(), while all other cases of the testsuite use "void".

Looking through the latest Bison docs I could find...

http://www.gnu.org/software/bison/manual/html_mono/bison.html#Yacc-Library

...I understood that the "int" return-type form of yyerror() was only required for POSIX compliance with "Yacc library", and was ignored by Bison. I am not too sure about what that "Yacc library" is, but as I get it, it would imply that I would make use of "-ly" in the compiler command line - which I am not actually doing - but I am still getting a prototype signature mismatch error anyway.

The M4 macros I have created assume the return type for yyerror() is *ALWAYS* "void", so they generate proper yyerror() prototype declarations with "void" as the return type. As my M4 macros have no way [that I know of] to check for previously-user-declared yyerror() prototypes that could conflict, the code shown above causes testcases #117 to #126 to fail as two yyerror() prototypes are declared and conflicting return types are detected. I tried to modify testcases #117 through #126 so they all use "void" as the return type for yyerror() instead of "int" and I get *ALL* the testcases to pass -- but I doubt this should be a good thing to do unless you also approve this testsuite change...


My questions:

1- Can you have a look at my attached patch and tell me what you think of it? It has been generated from released Bison-2.0 tree though... is that okay? 2- Would there be a better way to check for the return type of a user-declared yyerror() prototype that could exist, before my M4 macros generate a potentially-conflicting yyerror() declaration? 3- Why would "int" be used as the return type of user-declared yyerror() in testcases #117 to #126? Doesn't Bison recommend to use "void" as the return type? 4- I would appreciate any other comments regarding my current "tentative" patch, and will hope it might interest you enough to be considered for inclusion in the next release.... :-)


Regards,

--
*Jeannot Langlois*
B. Sc.  Computer Science / B. Sc.  Informatique
Software Developer / Programmeur-Analyste
System/Network Administrator / Administrateur Système/Réseau
**

LINUX_LOGO



diff -u -r data/glr.c data/glr.c
--- data/glr.c  2005-05-24 20:00:56.000000000 -0400
+++ data/glr.c  2005-05-24 20:04:56.000000000 -0400
@@ -49,6 +49,17 @@
 m4_define([b4_user_formals],
 [m4_ifset([b4_parse_param], [, b4_c_ansi_formals(b4_parse_param)])])
 
+# b4_alt_user_formals
+# -------------------------
+m4_define([b4_alt_user_formals],
+[m4_ifset([b4_parse_param], [b4_c_ansi_formals(b4_parse_param), ])])
+
+# b4_yyerror_params
+# -----------------
+m4_define([b4_yyerror_params],
+[b4_pure_if([b4_location_if([YYLTYPE *yylocationp, 
])[]b4_alt_user_formals[]])]dnl
+[const char* yymsg]dnl
+)
 
 # b4_yyerror_args
 # ---------------
@@ -411,10 +422,16 @@
   ]b4_stos[
 };
 
-
+
 /* Prevent warning if -Wmissing-prototypes.  */
 ]b4_c_ansi_function_decl([yyparse], [int], b4_parse_param)[
 
+/* Prevent warning if -Wmissing-prototypes.  */
+]b4_c_ansi_function_decl([yylex], [int], b4_lex_param)[
+
+/* Prevent warning if -Wmissing-prototypes.  */
+]b4_c_function_decl([yyerror], [void], b4_yyerror_params)[
+
 /* Error token number */
 #define YYTERROR 1
 
diff -u -r data/yacc.c data/yacc.c
--- data/yacc.c 2005-05-24 20:00:56.000000000 -0400
+++ data/yacc.c 2005-05-24 20:05:19.000000000 -0400
@@ -62,6 +62,15 @@
 m4_ifdef([b4_lex_param], b4_lex_param)))
 
 
+# b4_yyerror_params
+# ----------------
+m4_define([b4_yyecho_pp], $1)
+
+m4_define([b4_yyerror_params],
+[b4_Pure_if([b4_location_if([YYLTYPE *yylocationp, ])]dnl
+m4_ifset([b4_parse_param], [[m4_map_sep([b4_yyecho_pp], [, ], 
m4_dquote(m4_map_sep([b4_yyecho_pp], [, ], m4_dquote(b4_parse_param))))]][[, 
]]))]dnl
+[const char* yymsg]dnl
+)
 
 ## ------------ ##
 ## Data Types.  ##
@@ -724,6 +733,22 @@
 #endif /* ! YYPARSE_PARAM */
 
 
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYLEX_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yylex (void *YYLEX_PARAM);
+# else
+int yylex ();
+# endif
+#else
+b4_c_function_decl([yylex], [int], b4_lex_param)
+#endif /* ! YYLEX_PARAM */
+
+/* Prevent warnings from -Wmissing-prototypes. */
+b4_c_function_decl([yyerror], [void], b4_yyerror_params)
+
+
 m4_divert_push([KILL])# ======================== M4 code.
 # b4_declare_parser_variables
 # ---------------------------
diff -u -r tests/testsuite tests/testsuite
--- tests/testsuite     2005-05-24 20:00:57.000000000 -0400
+++ tests/testsuite     2005-05-23 20:16:33.000000000 -0400
@@ -58390,7 +58390,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -58520,7 +58520,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -58764,7 +58764,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -58897,7 +58897,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -59141,7 +59141,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -59271,7 +59271,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -59280,7 +59280,6 @@
     abort ();
 #endif
   fprintf (stderr, "%s\n", s);
-  return 0;
 }
 
 
@@ -59515,7 +59514,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -59648,7 +59647,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -59892,7 +59891,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -60022,7 +60021,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -60271,7 +60270,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -60404,7 +60403,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -60653,7 +60652,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -60783,7 +60782,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -61032,7 +61031,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -61165,7 +61164,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -61414,7 +61413,7 @@
 # define ERROR_PARAMETERS char const *s
 #endif
   int yylex (LEX_PARAMETERS);
-  int yyerror (ERROR_PARAMETERS);
+  void yyerror (ERROR_PARAMETERS);
 %}
 
 %token TYPENAME ID
@@ -61544,7 +61543,7 @@
     }
 }
 
-int
+void
 yyerror (ERROR_PARAMETERS)
 {
 #if YYPURE && YYLSP_NEEDED
@@ -61755,7 +61754,7 @@
 #define YYSTYPE int
 static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1);
 int yylex (void);
-int yyerror (char const *msg);
+void yyerror (char const *msg);
 %}
 
 
@@ -61791,7 +61790,7 @@
   return yyparse ();
 }
 
-int
+void
 yyerror (char const *msg)
 {
   fprintf (stderr, "%s\n", msg);

reply via email to

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