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

@@ -55,7 +55,7 @@ extern char *dir_prefix;
and therefore GCC warns about a name clash. */
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;
/* The computed base for output file names. */

View File

@@ -23,10 +23,17 @@
#include "system.h"
#include "error.h"
#include "get-errno.h"
#include "getargs.h"
#include "gl_xlist.h"
#include "gl_array_list.h"
#include "gl_xlist.h"
#include "progname.h"
#include "quote.h"
#include "quotearg.h"
#include "vasnprintf.h"
#include "files.h"
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. */
void fixits_free (void)
{

View File

@@ -23,6 +23,9 @@
/* Declare a fix to apply. */
void fixits_register (location const *loc, char const* update);
/* Apply the fixits: update the source file. */
void fixits_run (void);
/* Free the registered fixits. */
void fixits_free (void);

View File

@@ -36,12 +36,13 @@
#include "quote.h"
#include "uniqstr.h"
bool defines_flag;
bool graph_flag;
bool xml_flag;
bool no_lines_flag;
bool token_table_flag;
bool yacc_flag; /* for -y */
bool defines_flag = false;
bool graph_flag = false;
bool xml_flag = false;
bool no_lines_flag = false;
bool token_table_flag = false;
bool yacc_flag = false; /* for -y */
bool update_flag = false; /* for -u */
bool nondeterministic_parser = false;
bool glr_parser = false;
@@ -283,7 +284,10 @@ Operation modes:\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n\
--print-localedir output directory containing locale-dependent data\n\
and exit\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\
-W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
-f, --feature[=FEATURE] activate miscellaneous features\n\
@@ -478,6 +482,7 @@ static char const short_options[] =
"p:"
"r:"
"t"
"u" /* --update */
"v"
"x::"
"y"
@@ -499,6 +504,7 @@ static struct option const long_options[] =
{ "version", no_argument, 0, 'V' },
{ "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
{ "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
{ "update", no_argument, 0, 'u' },
{ "warnings", optional_argument, 0, 'W' },
/* Parser. */
@@ -684,6 +690,10 @@ getargs (int argc, char *argv[])
MUSCLE_PERCENT_DEFINE_D);
break;
case 'u':
update_flag = true;
break;
case 'v':
report_flag |= report_states;
break;

View File

@@ -40,7 +40,7 @@ extern bool xml_flag; /* for -x */
extern bool no_lines_flag; /* for -l */
extern bool token_table_flag; /* for -k */
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
(Generalized LR) parser, and to output some additional information

View File

@@ -103,6 +103,12 @@ main (int argc, char *argv[])
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)
goto finish;
@@ -206,7 +212,6 @@ main (int argc, char *argv[])
conflicts_free ();
grammar_free ();
output_file_names_free ();
fixits_free ();
/* The scanner memory cannot be released right after parsing, as it
contains things such as user actions, prologue, epilogue etc. */