From bd9d212b13d6ba9678bd55048bd8f5b55fa37e72 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Tue, 12 Dec 2006 06:47:39 +0000 Subject: [PATCH] * tests/testsuite.at (AT_CHECK): When checking if $1 starts with `bison ', use m4_index instead of m4_substr since chopping up a string containing M4-special characters causes problems here. Fix a couple of bugs related to special characters in user-specified file names, and make it easier for skeletons to compute output file names with the same file name prefix as Bison-computed output file names. * data/glr.cc, data/push.c, data/yacc.c: In @output, use b4_parser_file_name and b4_spec_defines_file instead of @output_parser_name@ and @output_header_name@, which are now redundant. * data/glr.c, data/lalr1.cc: Likewise. Also, in header #include's, use b4_parser_file_name, b4_spec_defines_file, and the new @basename(FILENAME@) instead of @output_parser_name@ and @output_header_name@, which inappropriately escaped the file names as C string literals. * src/files.c (all_but_ext): Remove static qualifier. (compute_output_file_names): Move `free (all_but_ext)' to... (output_file_names_free): ... here since all_but_ext is needed later. * src/files.h (all_but_ext): Extern. * src/muscle_tab.h (MUSCLE_INSERT_STRING_RAW): New macro that does exactly what MUSCLE_INSERT_STRING used to do. (MUSCLE_INSERT_STRING): Use MUSCLE_OBSTACK_SGROW so that M4-special characters are escaped properly. * src/output.c (prepare): Define muscle file_name_all_but_ext as all_but_ext. For pkgdatadir muscle, maintain previous functionality by using MUSCLE_INSERT_STRING_RAW instead of MUSCLE_INSERT_STRING. The problem is that b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs would never be expanded. Hopefully no one has M4-special characters in his Bison installation path. * src/scan-skel.l: Don't parse @output_header_name@ and @output_parser_name@ anymore since they're now redundant. In @output, use decode_at_digraphs. Parse a new @basename command that invokes last_component. (decode_at_digraphs): New. (BASE_QPUTS): Remove unused. * tests/output.at (AT_CHECK_OUTPUT_FILE_NAME): New macro. (Output file name): New tests. --- ChangeLog | 42 +++++++++++++++++++++++++++++++ data/glr.c | 6 ++--- data/glr.cc | 2 +- data/lalr1.cc | 8 +++--- data/push.c | 4 +-- data/yacc.c | 4 +-- src/files.c | 4 +-- src/files.h | 3 +++ src/muscle_tab.h | 9 ++++++- src/output.c | 8 +++++- src/scan-skel.l | 62 ++++++++++++++++++++++++++++++---------------- tests/output.at | 51 +++++++++++++++++++++++++++++++++++++- tests/testsuite.at | 2 +- 13 files changed, 165 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f6eb374..f8505423 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +2006-12-12 Joel E. Denny + + * tests/testsuite.at (AT_CHECK): When checking if $1 starts with + `bison ', use m4_index instead of m4_substr since chopping up a string + containing M4-special characters causes problems here. + + Fix a couple of bugs related to special characters in user-specified + file names, and make it easier for skeletons to compute output file + names with the same file name prefix as Bison-computed output file + names. + * data/glr.cc, data/push.c, data/yacc.c: In @output, use + b4_parser_file_name and b4_spec_defines_file instead of + @output_parser_name@ and @output_header_name@, which are now redundant. + * data/glr.c, data/lalr1.cc: Likewise. Also, in header #include's, use + b4_parser_file_name, b4_spec_defines_file, and the new + @basename(FILENAME@) instead of @output_parser_name@ and + @output_header_name@, which inappropriately escaped the file names as + C string literals. + * src/files.c (all_but_ext): Remove static qualifier. + (compute_output_file_names): Move `free (all_but_ext)' to... + (output_file_names_free): ... here since all_but_ext is needed later. + * src/files.h (all_but_ext): Extern. + * src/muscle_tab.h (MUSCLE_INSERT_STRING_RAW): New macro that does + exactly what MUSCLE_INSERT_STRING used to do. + (MUSCLE_INSERT_STRING): Use MUSCLE_OBSTACK_SGROW so that M4-special + characters are escaped properly. + * src/output.c (prepare): Define muscle file_name_all_but_ext as + all_but_ext. + For pkgdatadir muscle, maintain previous functionality by using + MUSCLE_INSERT_STRING_RAW instead of MUSCLE_INSERT_STRING. The problem + is that b4_pkgdatadir is used inside m4_include in the skeletons, so + digraphs would never be expanded. Hopefully no one has M4-special + characters in his Bison installation path. + * src/scan-skel.l: Don't parse @output_header_name@ and + @output_parser_name@ anymore since they're now redundant. + In @output, use decode_at_digraphs. + Parse a new @basename command that invokes last_component. + (decode_at_digraphs): New. + (BASE_QPUTS): Remove unused. + * tests/output.at (AT_CHECK_OUTPUT_FILE_NAME): New macro. + (Output file name): New tests. + 2006-12-09 Joel E. Denny Warn about output files that are generated by the skeletons and that diff --git a/data/glr.c b/data/glr.c index e51d5904..9ac721ba 100644 --- a/data/glr.c +++ b/data/glr.c @@ -142,7 +142,7 @@ m4_define([b4_rhs_location], # We do want M4 expansion after # for CPP macros. m4_changecom() m4_divert(0)dnl -@output @output_parser_name@ +@output b4_parser_file_name b4_copyright([Skeleton implementation for Bison GLR parsers in C], [2002, 2003, 2004, 2005, 2006]) [ @@ -207,7 +207,7 @@ typedef struct YYLTYPE ]b4_user_provides])[]dnl ]) -b4_defines_if([#include @output_header_name@], +b4_defines_if([[#include "@basename(]b4_spec_defines_file[@)"]], [b4_shared_declarations])[ /* Enabling traces. */ @@ -2629,7 +2629,7 @@ dnl glr.cc produces its own header. dnl m4_if(b4_skeleton, ["glr.c"], [b4_defines_if( -[@output @output_header_name@ +[@output b4_spec_defines_file b4_copyright([Skeleton interface for Bison GLR parsers in C], [2002, 2003, 2004, 2005, 2006]) diff --git a/data/glr.cc b/data/glr.cc index 3a0b2161..d9364902 100644 --- a/data/glr.cc +++ b/data/glr.cc @@ -216,7 +216,7 @@ m4_defn([b4_parse_param])))], m4_include(b4_pkgdatadir/[glr.c]) m4_popdef([b4_parse_param]) -@output @output_header_name@ +@output b4_spec_defines_file b4_copyright([Skeleton interface for Bison GLR parsers in C++], [2002, 2003, 2004, 2005, 2006])[ diff --git a/data/lalr1.cc b/data/lalr1.cc index efb639f1..c76a1a10 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -33,7 +33,7 @@ m4_include(b4_pkgdatadir/[location.cc]) m4_changecom() m4_divert(0)dnl b4_defines_if( -[@output @output_header_name@ +[@output b4_spec_defines_file b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++], [2002, 2003, 2004, 2005, 2006]) dnl FIXME: This is wrong, we want computed header guards. @@ -301,7 +301,7 @@ m4_ifdef([b4_provides], [#endif /* ! defined PARSER_HEADER_H */] ])dnl -@output @output_parser_name@ +@output b4_parser_file_name b4_copyright([Skeleton implementation for Bison LALR(1) parsers in C++], [2002, 2003, 2004, 2005, 2006]) m4_if(b4_prefix, [yy], [], @@ -312,8 +312,8 @@ m4_if(b4_prefix, [yy], [], /* First part of user declarations. */ ]b4_user_pre_prologue -b4_defines_if([ -#include @output_header_name@])[ +b4_defines_if([[ +#include "@basename(]b4_spec_defines_file[@)"]])[ /* User implementation prologue. */ ]b4_user_post_prologue[ diff --git a/data/push.c b/data/push.c index 84c0504a..87a02e78 100644 --- a/data/push.c +++ b/data/push.c @@ -134,7 +134,7 @@ m4_define([b4_rhs_location], # We do want M4 expansion after # for CPP macros. m4_changecom() m4_divert(0)dnl -@output @output_parser_name@ +@output b4_parser_file_name b4_copyright([Skeleton implementation for Bison's Yacc-like parsers in C],dnl ' [1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006])[ @@ -1638,7 +1638,7 @@ yyreturn: b4_epilogue b4_defines_if( -[@output @output_header_name@ +[@output b4_spec_defines_file b4_copyright([Skeleton interface for Bison's Yacc-like parsers in C],dnl ' [1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006]) diff --git a/data/yacc.c b/data/yacc.c index c7146e4b..a1077224 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -134,7 +134,7 @@ m4_define([b4_rhs_location], # We do want M4 expansion after # for CPP macros. m4_changecom() m4_divert(0)dnl -@output @output_parser_name@ +@output b4_parser_file_name b4_copyright([Skeleton implementation for Bison's Yacc-like parsers in C],dnl ' [1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006])[ @@ -1485,7 +1485,7 @@ yyreturn: b4_epilogue b4_defines_if( -[@output @output_header_name@ +[@output b4_spec_defines_file b4_copyright([Skeleton interface for Bison's Yacc-like parsers in C],dnl ' [1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006]) diff --git a/src/files.c b/src/files.c index 05985d8e..eaa97c6b 100644 --- a/src/files.c +++ b/src/files.c @@ -76,7 +76,7 @@ uniqstr current_file = NULL; empty string (meaning the current directory); otherwise it is `dir/'. */ -static char *all_but_ext; +char *all_but_ext; static char *all_but_tab_ext; char *dir_prefix; @@ -328,7 +328,6 @@ compute_output_file_names (void) output_file_name_check (spec_verbose_file); } - free (all_but_ext); free (all_but_tab_ext); free (src_extension); free (header_extension); @@ -350,6 +349,7 @@ output_file_name_check (char const *file_name) void output_file_names_free (void) { + free (all_but_ext); free (spec_verbose_file); free (spec_graph_file); free (spec_defines_file); diff --git a/src/files.h b/src/files.h index 1afcf7a5..a315414c 100644 --- a/src/files.h +++ b/src/files.h @@ -62,6 +62,9 @@ extern uniqstr grammar_file; /* The current file name. Might change with %include, or with #line. */ extern uniqstr current_file; +/* The computed base for output file names. */ +extern char *all_but_ext; + void compute_output_file_names (void); void output_file_names_free (void); void output_file_name_check (char const *file_name); diff --git a/src/muscle_tab.h b/src/muscle_tab.h index 32989bc7..c53bfda1 100644 --- a/src/muscle_tab.h +++ b/src/muscle_tab.h @@ -52,13 +52,20 @@ do { \ muscle_insert (Key, obstack_finish (&muscle_obstack)); \ } while(0) -#define MUSCLE_INSERT_STRING(Key, Value) \ +#define MUSCLE_INSERT_STRING_RAW(Key, Value) \ do { \ obstack_sgrow (&muscle_obstack, Value); \ obstack_1grow (&muscle_obstack, 0); \ muscle_insert (Key, obstack_finish (&muscle_obstack)); \ } while(0) +#define MUSCLE_INSERT_STRING(Key, Value) \ +do { \ + MUSCLE_OBSTACK_SGROW (&muscle_obstack, Value); \ + obstack_1grow (&muscle_obstack, 0); \ + muscle_insert (Key, obstack_finish (&muscle_obstack)); \ +} while(0) + #define MUSCLE_OBSTACK_SGROW(Obstack, Value) \ do { \ char const *p; \ diff --git a/src/output.c b/src/output.c index 6b62ccd6..1e130dfc 100644 --- a/src/output.c +++ b/src/output.c @@ -603,6 +603,8 @@ prepare (void) if (spec_name_prefix) MUSCLE_INSERT_STRING ("prefix", spec_name_prefix); + MUSCLE_INSERT_STRING ("file_name_all_but_ext", all_but_ext); + #define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "") DEFINE (dir_prefix); DEFINE (parser_file_name); @@ -632,7 +634,11 @@ prepare (void) /* About the skeletons. */ { char const *pkgdatadir = getenv ("BISON_PKGDATADIR"); - MUSCLE_INSERT_STRING ("pkgdatadir", pkgdatadir ? pkgdatadir : PKGDATADIR); + /* b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs + would never be expanded. Hopefully no one has M4-special characters in + his Bison installation path. */ + MUSCLE_INSERT_STRING_RAW ("pkgdatadir", + pkgdatadir ? pkgdatadir : PKGDATADIR); MUSCLE_INSERT_C_STRING ("skeleton", skeleton); } } diff --git a/src/scan-skel.l b/src/scan-skel.l index b4661743..4bba4ac4 100644 --- a/src/scan-skel.l +++ b/src/scan-skel.l @@ -47,9 +47,7 @@ int skel_lex (void); #define QPUTS(String) \ fputs (quotearg_style (c_quoting_style, String), yyout) -#define BASE_QPUTS(File) \ - QPUTS (last_component (File)) - +static char *decode_at_digraphs (char *in); %} %% @@ -59,29 +57,15 @@ int skel_lex (void); %} "@output ".*\n { - char const *file_name = yytext + sizeof "@output " - 1; + char *file_name = yytext + sizeof "@output " - 1; yytext[yyleng - 1] = '\0'; - - /* Decode special file names. They include the directory part, - contrary to their "free" occurrences, used for issuing #includes, - which must not include the directory part. */ - - if (*file_name == '@') - { - if (strcmp (file_name, "@output_header_name@") == 0) - file_name = spec_defines_file; - else if (strcmp (file_name, "@output_parser_name@") == 0) - file_name = parser_file_name; - else - fatal ("invalid token in skeleton: %s", yytext); - } if (outname) { free (outname); xfclose (yyout); } - outname = xstrdup (file_name); - output_file_name_check (file_name); + outname = decode_at_digraphs (file_name); + output_file_name_check (outname); yyout = xfopen (outname, "w"); lineno = 1; } @@ -93,8 +77,14 @@ int skel_lex (void); "@oline@" fprintf (yyout, "%d", lineno + 1); "@ofile@" QPUTS (outname); "@dir_prefix@" QPUTS (dir_prefix); -"@output_parser_name@" BASE_QPUTS (parser_file_name); -"@output_header_name@" BASE_QPUTS (spec_defines_file); + +"@basename(".*"@)" { + char *file_name = yytext + sizeof "@basename " - 1; + yytext[yyleng - 2] = '\0'; + file_name = decode_at_digraphs (file_name); + fputs (last_component (file_name), yyout); + free (file_name); +} /* This pattern must not match more than the previous @ patterns. */ @[^{}@\n]* fatal ("invalid @ in skeleton: %s", yytext); @@ -124,3 +114,31 @@ scan_skel (FILE *in) /* Reclaim Flex's buffers. */ yylex_destroy (); } + +static char * +decode_at_digraphs (char *in) +{ + char *out_start = xnmalloc (strlen (in)+1, sizeof *out_start); + char *out; + for (out = out_start; *in != '\0'; ++in, ++out) + { + if (*in == '@') + { + switch (*++in) + { + case '@': *out = '@'; break; + case '{': *out = '['; break; + case '}': *out = ']'; break; + default: + if (*in != '\0') + in[1] = '\0'; + fatal ("invalid @ in skeleton: %s", in-1); + break; + } + } + else + *out = *in; + } + *out = '\0'; + return out_start; +} diff --git a/tests/output.at b/tests/output.at index 6362ef2d..fd3e607e 100644 --- a/tests/output.at +++ b/tests/output.at @@ -23,7 +23,7 @@ AT_BANNER([[Output file names.]]) # [ADDITIONAL-TESTS]) # ----------------------------------------------------------------------------- m4_define([AT_CHECK_OUTPUT], -[AT_SETUP([Output files: $2 $3 $5]) +[AT_SETUP([[Output files: $2 $3 $5]]) case "$1" in */*) mkdir `echo "$1" | sed 's,/.*,,'`;; esac @@ -149,3 +149,52 @@ AT_CHECK_CONFLICTING_OUTPUT([foo.y], [%skeleton "lalr1.cc" %defines], [--graph="location.hh"], [foo.y: warning: conflicting outputs to file `location.hh' ]) + + +# AT_CHECK_OUTPUT_FILE_NAME(FILE-NAME-PREFIX, [ADDITIONAL-TESTS]) +# ----------------------------------------------------------------------------- +m4_define([AT_CHECK_OUTPUT_FILE_NAME], +[AT_SETUP([Output file name: $1]) + +AT_DATA([glr.y], +[[%glr-parser +%code { + int yylex (void); + void yyerror (const char *); +} +%% +start: {}; +]]) +AT_CHECK([bison -o "AS_ESCAPE([$1.c])" --defines="AS_ESCAPE([$1.h])" glr.y]) +AT_CHECK([ls "AS_ESCAPE([$1.c])" "AS_ESCAPE([$1.h])"], [], [ignore]) +AT_COMPILE([glr.o], [-c "AS_ESCAPE([$1.c])"]) +$2 + +AT_DATA([cxx.y], +[[%skeleton "lalr1.cc" +%code { int yylex (yy::parser::semantic_type*); } +%% +start: {}; +]]) +AT_CHECK([bison -o "AS_ESCAPE([$1.c])" --defines="AS_ESCAPE([$1.h])" cxx.y]) +AT_CHECK([ls "AS_ESCAPE([$1.c])" "AS_ESCAPE([$1.h])"], [], [ignore]) +AT_COMPILE_CXX([cxx.o], [-c "AS_ESCAPE([$1.c])"]) +$2 + +AT_CLEANUP +]) + +# Notice that the header file name here cannot contain +# `"' since FILENAME in `#include "FILENAME"' cannot. +AT_CHECK_OUTPUT_FILE_NAME([[`~!@#$%^&*()-=_+{}[]|\:;<>, .']]) +AT_CHECK_OUTPUT_FILE_NAME([[(]]) +AT_CHECK_OUTPUT_FILE_NAME([[)]]) +AT_CHECK_OUTPUT_FILE_NAME([[#]]) +AT_CHECK_OUTPUT_FILE_NAME([[@@]]) +AT_CHECK_OUTPUT_FILE_NAME([[@{]]) +AT_CHECK_OUTPUT_FILE_NAME([[@}]]) + +# Bison isn't M4-quoting file names before inserting them into muscles, so +# these tests currently fail. +AT_CHECK_OUTPUT_FILE_NAME([[@<:@]]) +AT_CHECK_OUTPUT_FILE_NAME([[@:>@]]) diff --git a/tests/testsuite.at b/tests/testsuite.at index 1607c720..043ff7b0 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -24,7 +24,7 @@ m4_pushdef([ORIGINAL_AT_CHECK], m4_defn([AT_CHECK])) m4_pushdef([AT_CHECK], [ORIGINAL_AT_CHECK( - m4_if(m4_quote(m4_substr(m4_quote($1), 0, 5)), [bison], + m4_if(m4_index(m4_quote($1), [bison ]), 0, m4_if(m4_quote($2), [0], [], m4_quote($2), [], [], [[VALGRIND_OPTS="$VALGRIND_OPTS --leak-check=summary --show-reachable=no"; export VALGRIND_OPTS; ]]))$@)]) -- 2.45.2