From 4e8b46ebe56ea7482580f2185f92a63dd3bbfd99 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Sun, 6 Sep 2020 16:24:18 +0200 Subject: [PATCH] add support for --html * bootstrap.conf: We need the "execute" module. * src/files.h, src/files.c (spec_html_file, html_flag): New. * src/getargs.h, src/getargs.c (--html): New. * src/print-xml.h, src/print-xml.c (print_html): New. * src/main.c: Use them. * tests/output.at, tests/report.at: Check --html. --- NEWS | 9 +++++++++ bootstrap.conf | 2 +- lib/.gitignore | 2 ++ lib/timevar.def | 1 + m4/.gitignore | 1 + src/files.c | 9 +++++++++ src/files.h | 5 ++++- src/getargs.c | 14 ++++++++++++++ src/getargs.h | 1 + src/main.c | 10 +++++++++- src/print-xml.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/print-xml.h | 3 +++ src/reader.c | 1 + tests/diagnostics.at | 2 +- tests/local.mk | 2 +- tests/output.at | 7 +++++++ tests/report.at | 34 +++++++++++----------------------- 17 files changed, 117 insertions(+), 28 deletions(-) diff --git a/NEWS b/NEWS index 6cd331f67..70d480f6a 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,15 @@ GNU Bison NEWS %header supersedes %defines. Both --defines and %defines are, of course, maintained for backward compatibility. +*** Option --html + + Since version 2.4 Bison can be used to generate HTML reports. However it + was a two-step process: first bison must be invoked with option --xml, and + then xsltproc must be run to the convert the XML reports into HTML. + + The new option --html combines these steps. The xsltproc program must be + available. + *** A C++ native GLR parser A new version of the generated C++ GLR parser was added as "glr2.cc". It diff --git a/bootstrap.conf b/bootstrap.conf index 577e30e51..6efae84b5 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -22,7 +22,7 @@ gnulib_modules=' calloc-posix close closeout config-h c-strcase configmake dirname - error extensions + error execute extensions fdl fopen-safer fstrcmp getopt-gnu gettext-h git-version-gen gitlog-to-changelog diff --git a/lib/.gitignore b/lib/.gitignore index 337cdb744..37e857dda 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -67,6 +67,8 @@ /errno.in.h /error.c /error.h +/execute.c +/execute.h /exitfail.c /exitfail.h /fatal-signal.c diff --git a/lib/timevar.def b/lib/timevar.def index 6e0d6ff05..39eb84059 100644 --- a/lib/timevar.def +++ b/lib/timevar.def @@ -53,6 +53,7 @@ DEFTIMEVAR (tv_conflicts , "conflicts") /* Time spent outputting results. */ DEFTIMEVAR (tv_report , "outputting report") DEFTIMEVAR (tv_graph , "outputting graph") +DEFTIMEVAR (tv_html , "outputting html") DEFTIMEVAR (tv_xml , "outputting xml") DEFTIMEVAR (tv_actions , "parser action tables") DEFTIMEVAR (tv_parser , "outputting parser") diff --git a/m4/.gitignore b/m4/.gitignore index 57bb666ad..f8e063894 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -19,6 +19,7 @@ /environ.m4 /errno_h.m4 /error.m4 +/execute.m4 /exponentd.m4 /exponentf.m4 /exponentl.m4 diff --git a/src/files.c b/src/files.c index 6675bb2c8..1cf04c512 100644 --- a/src/files.c +++ b/src/files.c @@ -55,6 +55,7 @@ char const *spec_name_prefix = NULL; /* for -p. */ location spec_name_prefix_loc = EMPTY_LOCATION_INIT; char *spec_verbose_file = NULL; /* for --verbose. */ char *spec_graph_file = NULL; /* for -g. */ +char *spec_html_file = NULL; /* for --html. */ char *spec_xml_file = NULL; /* for -x. */ char *spec_header_file = NULL; /* for --header. */ char *spec_mapped_header_file = NULL; @@ -425,6 +426,13 @@ compute_output_file_names (void) output_file_name_check (&spec_graph_file, false); } + if (html_flag) + { + if (! spec_html_file) + spec_html_file = concat2 (all_but_tab_ext, ".html"); + output_file_name_check (&spec_html_file, false); + } + if (xml_flag) { if (! spec_xml_file) @@ -526,6 +534,7 @@ output_file_names_free (void) free (all_but_ext); free (spec_verbose_file); free (spec_graph_file); + free (spec_html_file); free (spec_xml_file); free (spec_header_file); free (spec_mapped_header_file); diff --git a/src/files.h b/src/files.h index dafdbc95e..5d3ee8fa4 100644 --- a/src/files.h +++ b/src/files.h @@ -44,7 +44,10 @@ extern char *spec_verbose_file; /* File name specified for the output graph. */ extern char *spec_graph_file; -/* File name specified for the xml output. */ +/* File name specified for the HTML output. */ +extern char *spec_html_file; + +/* File name specified for the XML output. */ extern char *spec_xml_file; /* File name specified with --header. */ diff --git a/src/getargs.c b/src/getargs.c index df2c6da15..dc7b79158 100644 --- a/src/getargs.c +++ b/src/getargs.c @@ -40,6 +40,7 @@ bool header_flag = false; bool graph_flag = false; +bool html_flag = false; bool xml_flag = false; bool no_lines_flag = false; bool token_table_flag = false; @@ -432,6 +433,7 @@ Output Files:\n\ -b, --file-prefix=PREFIX specify a PREFIX for output files\n\ -o, --output=FILE leave output to FILE\n\ -g, --graph[=FILE] also output a graph of the automaton\n\ + --html[=FILE] also output an HTML report of the automaton\n\ -x, --xml[=FILE] also output an XML report of the automaton\n\ -M, --file-prefix-map=OLD=NEW replace prefix OLD with NEW when writing file paths\n\ in output files\n\ @@ -572,6 +574,7 @@ enum { COLOR_OPTION = CHAR_MAX + 1, FIXED_OUTPUT_FILES_OPTION, + HTML_OPTION, LOCATIONS_OPTION, PRINT_DATADIR_OPTION, PRINT_LOCALEDIR_OPTION, @@ -616,6 +619,7 @@ static struct option const long_options[] = { "file-prefix", required_argument, 0, 'b' }, { "output", required_argument, 0, 'o' }, { "graph", optional_argument, 0, 'g' }, + { "html", optional_argument, 0, HTML_OPTION }, { "xml", optional_argument, 0, 'x' }, { "file-prefix-map", required_argument, 0, 'M' }, @@ -839,6 +843,16 @@ getargs (int argc, char *argv[]) /* Handled in getargs_colors. */ break; + case HTML_OPTION: + html_flag = true; + xml_flag = true; + if (optarg) + { + free (spec_html_file); + spec_html_file = xstrdup (optarg); + } + break; + case FIXED_OUTPUT_FILES_OPTION: complain (&loc, Wdeprecated, _("deprecated option: %s, use %s"), diff --git a/src/getargs.h b/src/getargs.h index c8b2f6597..9e78d0743 100644 --- a/src/getargs.h +++ b/src/getargs.h @@ -36,6 +36,7 @@ extern char const *include; extern bool header_flag; /* for -d/-H */ extern bool graph_flag; /* for -g */ +extern bool html_flag; /* for --html */ extern bool xml_flag; /* for -x */ extern bool no_lines_flag; /* for -l */ extern bool token_table_flag; /* for -k */ diff --git a/src/main.c b/src/main.c index 70954d5b0..946e32d76 100644 --- a/src/main.c +++ b/src/main.c @@ -188,12 +188,20 @@ main (int argc, char *argv[]) } /* Output xml. */ - if (xml_flag) + if (html_flag || xml_flag) { timevar_push (tv_xml); print_xml (); timevar_pop (tv_xml); } + + /* Output html. */ + if (html_flag) + { + timevar_push (tv_html); + print_html (); + timevar_pop (tv_html); + } } /* Stop if there were errors, to avoid trashing previous output diff --git a/src/print-xml.c b/src/print-xml.c index c509089f9..7b833bacc 100644 --- a/src/print-xml.c +++ b/src/print-xml.c @@ -27,12 +27,16 @@ #include #include "closure.h" +#include "complain.h" #include "conflicts.h" +#include "execute.h" #include "files.h" #include "getargs.h" #include "gram.h" #include "lalr.h" #include "lr0.h" +#include "muscle-tab.h" +#include "path-join.h" #include "print.h" #include "reader.h" #include "reduce.h" @@ -531,3 +535,41 @@ print_xml (void) xfclose (out); } + + +void +print_html (void) +{ + assert (xml_flag); + + char *xml2html = xpath_join (pkgdatadir (), "xslt/xml2xhtml.xsl"); + + char const *argv[11]; + int i = 0; + argv[i++] = muscle_percent_define_get ("tool.xsltproc"); + argv[i++] = "-o"; + argv[i++] = spec_html_file; + argv[i++] = xml2html; + argv[i++] = spec_xml_file; + argv[i++] = NULL; + aver (i <= ARRAY_CARDINALITY (argv)); + + if (trace_flag & trace_tools) + { + fputs ("running:", stderr); + for (int j = 0; argv[j]; ++j) + fprintf (stderr, " %s", argv[j]); + fputc ('\n', stderr); + } + + int status + = execute (argv[0], + argv[0], (char **)(void*)(argv), + /* ignore_sigpipe */ false, + /* null_stdin, null_stdout, null_stderr */ true, true, true, + /* slave_process */ true, /* exit_on_error */ false, + NULL); + if (status) + complain (NULL, complaint, _("%s failed with status %d"), argv[0], status); + free (xml2html); +} diff --git a/src/print-xml.h b/src/print-xml.h index 51d3c15cc..9c6be7e23 100644 --- a/src/print-xml.h +++ b/src/print-xml.h @@ -30,4 +30,7 @@ char const *xml_escape_n (int n, char const *str); char const *xml_escape (char const *str); void print_xml (void); +/* Use xsltproc to generate HTML from XML output. */ +void print_html (void); + #endif /* !PRINT_XML_H_ */ diff --git a/src/reader.c b/src/reader.c index 1526ab4e8..0f9b7ee46 100644 --- a/src/reader.c +++ b/src/reader.c @@ -735,6 +735,7 @@ prepare_percent_define_front_end_variables (void) muscle_percent_define_default ("lr.default-reduction", "accepting"); free (lr_type); } + muscle_percent_define_default ("tool.xsltproc", "xsltproc"); /* Check %define front-end variables. */ { diff --git a/tests/diagnostics.at b/tests/diagnostics.at index 42b6d3a87..109eaa978 100644 --- a/tests/diagnostics.at +++ b/tests/diagnostics.at @@ -33,7 +33,7 @@ m4_if(m4_index([$1], [Counterexample]), [-1], [], [AT_KEYWORDS([cex])]) # We need UTF-8 support for correct screen-width computation of UTF-8 # characters. Skip the test if not available. locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q` -AT_SKIP_IF([test x == x"$locale"]) +AT_SKIP_IF([[test x = x"$locale"]]) m4_ifval([$6], [AT_SKIP_IF([$6])]) diff --git a/tests/local.mk b/tests/local.mk index a14ba8fb6..71e1f7a39 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -131,7 +131,7 @@ maintainer-check-posix: $(RUN_TESTSUITE_deps) VALGRIND_OPTS = --leak-check=full --show-reachable=yes --gen-suppressions=all \ $(VALGRIND_OPTS_SUPPRESSION) maintainer-check-valgrind: $(RUN_TESTSUITE_deps) - test 'x$(VALGRIND)' == x || \ + test 'x$(VALGRIND)' = x || \ $(RUN_TESTSUITE) \ PREBISON='$(VALGRIND) -q' PREPARSER='$(VALGRIND) -q' \ VALGRIND_OPTS="$(VALGRIND_OPTS)" diff --git a/tests/output.at b/tests/output.at index a13aaf818..a69fbdff7 100644 --- a/tests/output.at +++ b/tests/output.at @@ -36,6 +36,8 @@ m4_define([AT_CHECK_FILES], # ----------------------------------------------------------------- m4_define([AT_CHECK_OUTPUT], [AT_SETUP([[Output files: ]$2 $3])[ +]m4_bmatch([$3], [--html], + [AT_SKIP_IF([[test x"$XSLTPROC" = x]])])[ ]$7[ for file in ]$1 $4[; do case $file in @@ -90,6 +92,11 @@ AT_CHECK_OUTPUT([foo.y], [%define api.header.include {"./foo.h"}], [-dv -y], AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c], [foo.output foo.tab.c foo.tab.h]) +AT_CHECK_OUTPUT([foo.y], [], [--fixed-output-files -dv -g --html], + [y.dot y.html y.output y.tab.c y.tab.h y.xml]) +AT_CHECK_OUTPUT([foo.y], [], [-Hfoo.header -v -gfoo.gv --html=foo.html], + [foo.gv foo.header foo.html foo.output foo.tab.c foo.xml]) + AT_CHECK_OUTPUT([foo.y], [], [-dv -g --xml --fixed-output-files], [y.dot y.output y.tab.c y.tab.h y.xml]) AT_CHECK_OUTPUT([foo.y], [], [-dv -g --xml -y], diff --git a/tests/report.at b/tests/report.at index 35493b93e..a90c23abf 100644 --- a/tests/report.at +++ b/tests/report.at @@ -59,7 +59,8 @@ exp: | "number" { std::swap ($$, $1); }; ]]) -AT_BISON_CHECK([-o input.cc -v --graph=input.gv --xml input.yy]) +AT_SKIP_IF([[test x"$XSLTPROC" = x]]) +AT_BISON_CHECK([-o input.cc -v --graph=input.gv --html --xml input.yy]) # Check the contents of the report. AT_CHECK([cat input.output], [], @@ -304,7 +305,8 @@ State 19 # Now generate verbose reports. -AT_BISON_CHECK([-o input.cc -rall --graph=input.gv --xml input.yy]) +AT_SKIP_IF([[test x"$XSLTPROC" = x]]) +AT_BISON_CHECK([-o input.cc -rall --graph=input.gv --html --xml input.yy]) # Check the contents of the report. AT_CHECK([cat input.output], [], @@ -1138,14 +1140,7 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version=" ]]) # Check HTML output. -if test x"$XSLTPROC" != x""; then - AT_CHECK([[$XSLTPROC \ - `]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2xhtml.xsl \ - input.xml | \ - sed -e 's/GNU Bison [0-9][-.0-9a-z]*/GNU Bison VERSION/' \ - >input.html]]) - - AT_CHECK([cat input.html], [], +AT_CHECK([[sed -e 's/GNU Bison [0-9][-.0-9a-z]*/GNU Bison VERSION/g' input.html]], [], [[ @@ -1503,7 +1498,6 @@ if test x"$XSLTPROC" != x""; then permitted in any medium, provided this notice is preserved. ]]) -fi AT_BISON_OPTION_POPDEFS AT_CLEANUP @@ -1520,7 +1514,9 @@ AT_KEYWORDS([cex report]) # We need UTF-8 support for correct screen-width computation of UTF-8 # characters. Skip the test if not available. locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q` -AT_SKIP_IF([test x == x"$locale"]) +AT_SKIP_IF([[test x = x"$locale"]]) + +AT_SKIP_IF([[test x"$XSLTPROC" = x]]) AT_BISON_OPTION_PUSHDEFS AT_DATA([input.y], @@ -1534,7 +1530,7 @@ exp | "Ñùṃéℝô" ]]) -AT_CHECK([LC_ALL="$locale" bison -fno-caret -o input.cc -rall -Wcex --graph=input.gv --xml input.y], [], [], +AT_CHECK([LC_ALL="$locale" bison -fno-caret -o input.cc -rall -Wcex --graph=input.gv --html --xml input.y], [], [], [[input.y: warning: 3 shift/reduce conflicts [-Wconflicts-sr] input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples] @@ -2155,15 +2151,8 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version=" ]]) -# Check HTML output. -if test x"$XSLTPROC" != x""; then - AT_CHECK([[$XSLTPROC \ - `]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2xhtml.xsl \ - input.xml | \ - sed -e 's/GNU Bison [0-9][-.0-9a-z]*/GNU Bison VERSION/' \ - >input.html]]) - - AT_CHECK([cat input.html], [], + +AT_CHECK([[sed -e 's/GNU Bison [0-9][-.0-9a-z]*/GNU Bison VERSION/g' input.html]], [], [[ @@ -2391,7 +2380,6 @@ if test x"$XSLTPROC" != x""; then permitted in any medium, provided this notice is preserved. ]]) -fi AT_BISON_OPTION_POPDEFS AT_CLEANUP