bison-patches
[Top][All Lists]
Advanced

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

[PATCH 08/12] diagnostics: update the grammar file


From: Akim Demaille
Subject: [PATCH 08/12] diagnostics: update the grammar file
Date: Sun, 13 Jan 2019 15:24:03 +0100

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.
---
 bootstrap.conf |  1 +
 lib/.gitignore |  3 ++
 src/files.h    |  2 +-
 src/fixits.c   | 97 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/fixits.h   |  3 ++
 src/getargs.c  | 22 ++++++++----
 src/getargs.h  |  2 +-
 src/main.c     |  7 +++-
 tests/input.at | 89 +++++++++++++++++++++++++++++++++------------
 9 files changed, 194 insertions(+), 32 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index 1b1dd00c..2450ff07 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -38,6 +38,7 @@ gnulib_modules='
   readme-release
   realloc-posix
   relocatable-prog relocatable-script
+  rename
   spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
   timevar
   unistd unistd-safer unlink unlocked-io
diff --git a/lib/.gitignore b/lib/.gitignore
index d2ac6986..919f23c4 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -315,3 +315,6 @@
 /xstrndup.h
 /xtime.c
 /xtime.h
+/rename.c
+/rmdir.c
+/same-inode.h
diff --git a/src/files.h b/src/files.h
index 2ec10c95..9c60dcd5 100644
--- a/src/files.h
+++ b/src/files.h
@@ -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.  */
diff --git a/src/fixits.c b/src/fixits.c
index d1001280..769b8508 100644
--- a/src/fixits.c
+++ b/src/fixits.c
@@ -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)
 {
diff --git a/src/fixits.h b/src/fixits.h
index 0c531ab4..5adaf685 100644
--- a/src/fixits.h
+++ b/src/fixits.h
@@ -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);
 
diff --git a/src/getargs.c b/src/getargs.c
index 9874c429..83ebcb09 100644
--- a/src/getargs.c
+++ b/src/getargs.c
@@ -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;
diff --git a/src/getargs.h b/src/getargs.h
index 925ef58e..f44f2183 100644
--- a/src/getargs.h
+++ b/src/getargs.h
@@ -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
diff --git a/src/main.c b/src/main.c
index f728e727..94782573 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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.  */
diff --git a/tests/input.at b/tests/input.at
index 522eda54..ea30991c 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -2508,28 +2508,7 @@ AT_DATA_GRAMMAR([[input.y]],
 exp : '0'
 ]])
 
-AT_BISON_CHECK([[input.y]], [[1]], [[]],
-[[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]], [[]],
+AT_DATA([errors-all],
 [[input.y:10.1-13: warning: deprecated directive: '%default_prec', use 
'%default-prec' [-Wdeprecated]
 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]
@@ -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}"
 ]])
 
+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
 
 
-- 
2.20.1




reply via email to

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