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:
Akim Demaille
2019-01-12 19:30:21 +01:00
parent 79e79be298
commit 41aaa8374c
9 changed files with 194 additions and 32 deletions

View File

@@ -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
View File

@@ -315,3 +315,6 @@
/xstrndup.h /xstrndup.h
/xtime.c /xtime.c
/xtime.h /xtime.h
/rename.c
/rmdir.c
/same-inode.h

View File

@@ -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. */

View File

@@ -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)
{ {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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. */

View File

@@ -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