mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-17 08:13:02 +00:00
diagnostics: update the grammar file
Let's use the fixits to actually update the grammar files. * src/getargs.h, src/getargs.c (update_flag): New. * src/fixits.h, src/fixits.c (fixits_run): New. * src/main.c (main): Invoke fixits_run when --update is passed. * tests/input.at (Deprecated directives): Check --update.
This commit is contained in:
@@ -38,6 +38,7 @@ gnulib_modules='
|
|||||||
readme-release
|
readme-release
|
||||||
realloc-posix
|
realloc-posix
|
||||||
relocatable-prog relocatable-script
|
relocatable-prog relocatable-script
|
||||||
|
rename
|
||||||
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
|
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
|
||||||
timevar
|
timevar
|
||||||
unistd unistd-safer unlink unlocked-io
|
unistd unistd-safer unlink unlocked-io
|
||||||
|
|||||||
3
lib/.gitignore
vendored
3
lib/.gitignore
vendored
@@ -315,3 +315,6 @@
|
|||||||
/xstrndup.h
|
/xstrndup.h
|
||||||
/xtime.c
|
/xtime.c
|
||||||
/xtime.h
|
/xtime.h
|
||||||
|
/rename.c
|
||||||
|
/rmdir.c
|
||||||
|
/same-inode.h
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ extern char *dir_prefix;
|
|||||||
and therefore GCC warns about a name clash. */
|
and therefore GCC warns about a name clash. */
|
||||||
extern uniqstr grammar_file;
|
extern uniqstr grammar_file;
|
||||||
|
|
||||||
/* The current file name. Might change with %include, or with #line. */
|
/* The current file name. Might change with #line. */
|
||||||
extern uniqstr current_file;
|
extern uniqstr current_file;
|
||||||
|
|
||||||
/* The computed base for output file names. */
|
/* The computed base for output file names. */
|
||||||
|
|||||||
97
src/fixits.c
97
src/fixits.c
@@ -23,10 +23,17 @@
|
|||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
#include "get-errno.h"
|
||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
#include "gl_xlist.h"
|
|
||||||
#include "gl_array_list.h"
|
#include "gl_array_list.h"
|
||||||
|
#include "gl_xlist.h"
|
||||||
|
#include "progname.h"
|
||||||
|
#include "quote.h"
|
||||||
#include "quotearg.h"
|
#include "quotearg.h"
|
||||||
|
#include "vasnprintf.h"
|
||||||
|
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -84,6 +91,94 @@ fixits_register (location const *loc, char const* fix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
fixits_run (void)
|
||||||
|
{
|
||||||
|
if (!fixits)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* This is not unlike what is done in location_caret. */
|
||||||
|
uniqstr input = ((fixit *) gl_list_get_at (fixits, 0))->location.start.file;
|
||||||
|
/* Backup the file. */
|
||||||
|
char buf[256];
|
||||||
|
size_t len = sizeof (buf);
|
||||||
|
char *backup = asnprintf (buf, &len, "%s~", input);
|
||||||
|
if (!backup)
|
||||||
|
xalloc_die ();
|
||||||
|
if (rename (input, backup))
|
||||||
|
error (EXIT_FAILURE, get_errno (),
|
||||||
|
_("%s: cannot backup"), quotearg_colon (input));
|
||||||
|
FILE *in = xfopen (backup, "r");
|
||||||
|
FILE *out = xfopen (input, "w");
|
||||||
|
size_t line = 1;
|
||||||
|
size_t offset = 1;
|
||||||
|
fixit const *f = NULL;
|
||||||
|
gl_list_iterator_t iter = gl_list_iterator (fixits);
|
||||||
|
while (gl_list_iterator_next (&iter, (const void**) &f, NULL))
|
||||||
|
{
|
||||||
|
/* Look for the correct line. */
|
||||||
|
while (line < f->location.start.line)
|
||||||
|
{
|
||||||
|
int c = getc (in);
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
++line;
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
|
putc (c, out);
|
||||||
|
}
|
||||||
|
/* Look for the right offset. */
|
||||||
|
while (offset < f->location.start.column)
|
||||||
|
{
|
||||||
|
int c = getc (in);
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
++offset;
|
||||||
|
putc (c, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paste the fix instead. */
|
||||||
|
fputs (f->fix, out);
|
||||||
|
|
||||||
|
/* Skip the bad input. */
|
||||||
|
while (line < f->location.end.line)
|
||||||
|
{
|
||||||
|
int c = getc (in);
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
++line;
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (offset < f->location.end.column)
|
||||||
|
{
|
||||||
|
int c = getc (in);
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
++offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Paste the rest of the file. */
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
while ((c = getc (in)) != EOF)
|
||||||
|
putc (c, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_list_iterator_free (&iter);
|
||||||
|
xfclose (out);
|
||||||
|
xfclose (in);
|
||||||
|
fprintf (stderr, "%s: file %s was updated (backup: %s)\n",
|
||||||
|
program_name, quote_n (0, input), quote_n (1, backup));
|
||||||
|
if (backup != buf)
|
||||||
|
free (backup);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Free the registered fixits. */
|
/* Free the registered fixits. */
|
||||||
void fixits_free (void)
|
void fixits_free (void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
/* Declare a fix to apply. */
|
/* Declare a fix to apply. */
|
||||||
void fixits_register (location const *loc, char const* update);
|
void fixits_register (location const *loc, char const* update);
|
||||||
|
|
||||||
|
/* Apply the fixits: update the source file. */
|
||||||
|
void fixits_run (void);
|
||||||
|
|
||||||
/* Free the registered fixits. */
|
/* Free the registered fixits. */
|
||||||
void fixits_free (void);
|
void fixits_free (void);
|
||||||
|
|
||||||
|
|||||||
@@ -36,12 +36,13 @@
|
|||||||
#include "quote.h"
|
#include "quote.h"
|
||||||
#include "uniqstr.h"
|
#include "uniqstr.h"
|
||||||
|
|
||||||
bool defines_flag;
|
bool defines_flag = false;
|
||||||
bool graph_flag;
|
bool graph_flag = false;
|
||||||
bool xml_flag;
|
bool xml_flag = false;
|
||||||
bool no_lines_flag;
|
bool no_lines_flag = false;
|
||||||
bool token_table_flag;
|
bool token_table_flag = false;
|
||||||
bool yacc_flag; /* for -y */
|
bool yacc_flag = false; /* for -y */
|
||||||
|
bool update_flag = false; /* for -u */
|
||||||
|
|
||||||
bool nondeterministic_parser = false;
|
bool nondeterministic_parser = false;
|
||||||
bool glr_parser = false;
|
bool glr_parser = false;
|
||||||
@@ -283,7 +284,10 @@ Operation modes:\n\
|
|||||||
-h, --help display this help and exit\n\
|
-h, --help display this help and exit\n\
|
||||||
-V, --version output version information and exit\n\
|
-V, --version output version information and exit\n\
|
||||||
--print-localedir output directory containing locale-dependent data\n\
|
--print-localedir output directory containing locale-dependent data\n\
|
||||||
|
and exit\n\
|
||||||
--print-datadir output directory containing skeletons and XSLT\n\
|
--print-datadir output directory containing skeletons and XSLT\n\
|
||||||
|
and exit\n\
|
||||||
|
-u, --update apply fixes to the source grammar file\n\
|
||||||
-y, --yacc emulate POSIX Yacc\n\
|
-y, --yacc emulate POSIX Yacc\n\
|
||||||
-W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
|
-W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
|
||||||
-f, --feature[=FEATURE] activate miscellaneous features\n\
|
-f, --feature[=FEATURE] activate miscellaneous features\n\
|
||||||
@@ -478,6 +482,7 @@ static char const short_options[] =
|
|||||||
"p:"
|
"p:"
|
||||||
"r:"
|
"r:"
|
||||||
"t"
|
"t"
|
||||||
|
"u" /* --update */
|
||||||
"v"
|
"v"
|
||||||
"x::"
|
"x::"
|
||||||
"y"
|
"y"
|
||||||
@@ -499,6 +504,7 @@ static struct option const long_options[] =
|
|||||||
{ "version", no_argument, 0, 'V' },
|
{ "version", no_argument, 0, 'V' },
|
||||||
{ "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
|
{ "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
|
||||||
{ "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
|
{ "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
|
||||||
|
{ "update", no_argument, 0, 'u' },
|
||||||
{ "warnings", optional_argument, 0, 'W' },
|
{ "warnings", optional_argument, 0, 'W' },
|
||||||
|
|
||||||
/* Parser. */
|
/* Parser. */
|
||||||
@@ -684,6 +690,10 @@ getargs (int argc, char *argv[])
|
|||||||
MUSCLE_PERCENT_DEFINE_D);
|
MUSCLE_PERCENT_DEFINE_D);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
update_flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
report_flag |= report_states;
|
report_flag |= report_states;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ extern bool xml_flag; /* for -x */
|
|||||||
extern bool no_lines_flag; /* for -l */
|
extern bool no_lines_flag; /* for -l */
|
||||||
extern bool token_table_flag; /* for -k */
|
extern bool token_table_flag; /* for -k */
|
||||||
extern bool yacc_flag; /* for -y */
|
extern bool yacc_flag; /* for -y */
|
||||||
|
extern bool update_flag; /* for -u */
|
||||||
|
|
||||||
/* GLR_PARSER is true if the input file says to use the GLR
|
/* GLR_PARSER is true if the input file says to use the GLR
|
||||||
(Generalized LR) parser, and to output some additional information
|
(Generalized LR) parser, and to output some additional information
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ main (int argc, char *argv[])
|
|||||||
reader ();
|
reader ();
|
||||||
timevar_pop (tv_reader);
|
timevar_pop (tv_reader);
|
||||||
|
|
||||||
|
/* Fix input file now, even if there are errors: that's less
|
||||||
|
warnings in the following runs. */
|
||||||
|
if (update_flag)
|
||||||
|
fixits_run ();
|
||||||
|
fixits_free ();
|
||||||
|
|
||||||
if (complaint_status == status_complaint)
|
if (complaint_status == status_complaint)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
@@ -206,7 +212,6 @@ main (int argc, char *argv[])
|
|||||||
conflicts_free ();
|
conflicts_free ();
|
||||||
grammar_free ();
|
grammar_free ();
|
||||||
output_file_names_free ();
|
output_file_names_free ();
|
||||||
fixits_free ();
|
|
||||||
|
|
||||||
/* The scanner memory cannot be released right after parsing, as it
|
/* The scanner memory cannot be released right after parsing, as it
|
||||||
contains things such as user actions, prologue, epilogue etc. */
|
contains things such as user actions, prologue, epilogue etc. */
|
||||||
|
|||||||
@@ -2508,28 +2508,7 @@ AT_DATA_GRAMMAR([[input.y]],
|
|||||||
exp : '0'
|
exp : '0'
|
||||||
]])
|
]])
|
||||||
|
|
||||||
AT_BISON_CHECK([[input.y]], [[1]], [[]],
|
AT_DATA([errors-all],
|
||||||
[[input.y:10.1-13: warning: deprecated directive: '%default_prec', use '%default-prec' [-Wdeprecated]
|
|
||||||
input.y:11.1-14: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
|
|
||||||
input.y:12.1-10: warning: deprecated directive: '%expect_rr', use '%expect-rr' [-Wdeprecated]
|
|
||||||
input.y:13.1-14: warning: deprecated directive: '%file-prefix =', use '%file-prefix' [-Wdeprecated]
|
|
||||||
input.y:14.1-15.2: warning: deprecated directive: '%file-prefix\n =', use '%file-prefix' [-Wdeprecated]
|
|
||||||
input.y:17.1-19: warning: deprecated directive: '%fixed-output_files', use '%fixed-output-files' [-Wdeprecated]
|
|
||||||
input.y:18.1-19: warning: deprecated directive: '%fixed_output-files', use '%fixed-output-files' [-Wdeprecated]
|
|
||||||
input.y:20.1-19: warning: deprecated directive: '%name-prefix= "foo"', use '%define api.prefix {foo}' [-Wdeprecated]
|
|
||||||
input.y:21.1-16: warning: deprecated directive: '%no-default_prec', use '%no-default-prec' [-Wdeprecated]
|
|
||||||
input.y:22.1-16: warning: deprecated directive: '%no_default-prec', use '%no-default-prec' [-Wdeprecated]
|
|
||||||
input.y:23.1-9: warning: deprecated directive: '%no_lines', use '%no-lines' [-Wdeprecated]
|
|
||||||
input.y:24.1-9: warning: deprecated directive: '%output =', use '%output' [-Wdeprecated]
|
|
||||||
input.y:25.1-12: warning: deprecated directive: '%pure_parser', use '%pure-parser' [-Wdeprecated]
|
|
||||||
input.y:26.1-12: warning: deprecated directive: '%token_table', use '%token-table' [-Wdeprecated]
|
|
||||||
input.y:27.1-14: warning: deprecated directive: '%error-verbose', use '%define parse.error verbose' [-Wdeprecated]
|
|
||||||
input.y:27-14: error: %define variable 'parse.error' redefined
|
|
||||||
input.y:11-14: previous definition
|
|
||||||
input.y:29.1-18: warning: deprecated directive: '%name-prefix "bar"', use '%define api.prefix {bar}' [-Wdeprecated]
|
|
||||||
]])
|
|
||||||
|
|
||||||
AT_BISON_CHECK([[-ffixit input.y]], [[1]], [[]],
|
|
||||||
[[input.y:10.1-13: warning: deprecated directive: '%default_prec', use '%default-prec' [-Wdeprecated]
|
[[input.y:10.1-13: warning: deprecated directive: '%default_prec', use '%default-prec' [-Wdeprecated]
|
||||||
fix-it:"input.y":{10:1-10:14}:"%default-prec"
|
fix-it:"input.y":{10:1-10:14}:"%default-prec"
|
||||||
input.y:11.1-14: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
|
input.y:11.1-14: warning: deprecated directive: '%error_verbose', use '%define parse.error verbose' [-Wdeprecated]
|
||||||
@@ -2566,6 +2545,72 @@ input.y:29.1-18: warning: deprecated directive: '%name-prefix "bar"', use '%defi
|
|||||||
fix-it:"input.y":{29:1-29:19}:"%define api.prefix {bar}"
|
fix-it:"input.y":{29:1-29:19}:"%define api.prefix {bar}"
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
AT_CHECK([[sed -e '/^fix-it:/d' errors-all >experr]])
|
||||||
|
AT_BISON_CHECK([[input.y]], [[1]], [[]], [experr])
|
||||||
|
|
||||||
|
AT_CHECK([cp errors-all experr])
|
||||||
|
AT_BISON_CHECK([[-ffixit input.y]], [[1]], [[]], [experr])
|
||||||
|
|
||||||
|
# Update the input file.
|
||||||
|
AT_CHECK([cp input.y input.y.orig])
|
||||||
|
AT_CHECK([sed -e '/fix-it/d' <errors-all >experr])
|
||||||
|
AT_CHECK([echo "bison: file 'input.y' was updated (backup: 'input.y~')" >>experr])
|
||||||
|
AT_BISON_CHECK([[--update input.y]], [[1]], [[]], [experr])
|
||||||
|
|
||||||
|
# Check the backup.
|
||||||
|
AT_CHECK([diff input.y.orig input.y~])
|
||||||
|
|
||||||
|
# Check the update.
|
||||||
|
AT_CHECK([cat input.y], [],
|
||||||
|
[[%code top {
|
||||||
|
/* Load config.h, and adjust to the compiler.
|
||||||
|
We used to do it here, but each time we add a new line,
|
||||||
|
we have to adjust all the line numbers in error messages.
|
||||||
|
It's simpler to use a constant include to a varying file. */
|
||||||
|
#include <testsuite.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
%default-prec
|
||||||
|
%define parse.error verbose
|
||||||
|
%expect-rr 0
|
||||||
|
%file-prefix "foo"
|
||||||
|
%file-prefix
|
||||||
|
"bar"
|
||||||
|
%fixed-output-files
|
||||||
|
%fixed-output-files
|
||||||
|
%fixed-output-files
|
||||||
|
%define api.prefix {foo}
|
||||||
|
%no-default-prec
|
||||||
|
%no-default-prec
|
||||||
|
%no-lines
|
||||||
|
%output "foo"
|
||||||
|
%pure-parser
|
||||||
|
%token-table
|
||||||
|
%define parse.error verbose
|
||||||
|
%glr-parser
|
||||||
|
%define api.prefix {bar}
|
||||||
|
%%
|
||||||
|
exp : '0'
|
||||||
|
]])
|
||||||
|
|
||||||
|
# Unfortunately so far we don't remove duplicate definitions,
|
||||||
|
# so there are still warnings.
|
||||||
|
AT_BISON_CHECK([[-fcaret input.y]], [[1]], [],
|
||||||
|
[[input.y:26.1-27: error: %define variable 'parse.error' redefined
|
||||||
|
%define parse.error verbose
|
||||||
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
input.y:11.1-27: previous definition
|
||||||
|
%define parse.error verbose
|
||||||
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
input.y:28.1-24: error: %define variable 'api.prefix' redefined
|
||||||
|
%define api.prefix {bar}
|
||||||
|
^~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
input.y:19.1-24: previous definition
|
||||||
|
%define api.prefix {foo}
|
||||||
|
^~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
]])
|
||||||
|
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user