[Top][All Lists]
[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);
- [PATCH] Fix variadic declaration of yyerror() and yylex() function prototypes,
Jeannot Langlois <=