From: Joel E. Denny Date: Thu, 18 Jan 2007 05:14:59 +0000 (+0000) Subject: Implement @gettext<...@> directive to call gettext from skeletons. It X-Git-Tag: v2.3b~173 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/d4bdb9167769a7247ac7c93c03fbe9ff7c238d34 Implement @gettext<...@> directive to call gettext from skeletons. It can be used anywhere including inside arguments of directives of the form @foo(...@). Eventually, it should be possible to write an xgettext-like utility to extract @gettext<...@> text from skeletons. * data/bison.m4 (b4_check_user_names): Use @gettext<...@> when invoking b4_warn_at since b4_warn_at doesn't invoke gettext anymore. * data/glr.cc, data/lalr1.cc: Likewise but for b4_fatal and b4_complain reporting a push-parsing request or a missing %defines. * src/scan-skel.l (INITIAL): Recognize `@gettext<' to start... (SC_AT_GETTEXT_ARG): ... this new start condition where gettext is invoked. (SC_AT_DIRECTIVE_ARG): Rename to... (SC_AT_DIRECTIVE_ARGS): ... this, and recognize `@gettext<' to start SC_AT_GETTEXT_ARG. (at_directive_perform): Don't invoke gettext for @warn(...@), @warn_at(...@), etc. Instead, let the skeletons decide what should be passed to @gettext<...@>. * tests/skeletons.at (@gettext<...@>): New test case. * tests/skeletons.at (installed skeleton file name): Rename to... (installed skeleton file names): ... this. --- diff --git a/ChangeLog b/ChangeLog index 873f2ace..c78d9446 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2007-01-18 Joel E. Denny + + Implement @gettext<...@> directive to call gettext from skeletons. It + can be used anywhere including inside arguments of directives of the + form @foo(...@). Eventually, it should be possible to write an + xgettext-like utility to extract @gettext<...@> text from skeletons. + * data/bison.m4 (b4_check_user_names): Use @gettext<...@> when invoking + b4_warn_at since b4_warn_at doesn't invoke gettext anymore. + * data/glr.cc, data/lalr1.cc: Likewise but for b4_fatal and + b4_complain reporting a push-parsing request or a missing %defines. + * src/scan-skel.l (INITIAL): Recognize `@gettext<' to start... + (SC_AT_GETTEXT_ARG): ... this new start condition where gettext is + invoked. + (SC_AT_DIRECTIVE_ARG): Rename to... + (SC_AT_DIRECTIVE_ARGS): ... this, and recognize `@gettext<' to start + SC_AT_GETTEXT_ARG. + (at_directive_perform): Don't invoke gettext for @warn(...@), + @warn_at(...@), etc. Instead, let the skeletons decide what should be + passed to @gettext<...@>. + * tests/skeletons.at (@gettext<...@>): New test case. + + * tests/skeletons.at (installed skeleton file name): Rename to... + (installed skeleton file names): ... this. + 2007-01-17 Joel E. Denny Implement support for relative and absolute skeleton file names. diff --git a/data/bison.m4 b/data/bison.m4 index 6d37e980..adc8d996 100644 --- a/data/bison.m4 +++ b/data/bison.m4 @@ -328,7 +328,7 @@ m4_pushdef([b4_start], m4_car(m4_shift(b4_occurrence)))dnl m4_pushdef([b4_end], m4_shift(m4_shift(b4_occurrence)))dnl m4_ifndef($3[(]m4_quote(b4_user_name)[)], [b4_warn_at([b4_start], [b4_end], - [[%s `%s' is not used]], + [[@gettext<%s `%s' is not used@>]], [$1], [b4_user_name])])[]dnl m4_popdef([b4_occurrence])dnl m4_popdef([b4_user_name])dnl diff --git a/data/c++-skel.m4 b/data/c++-skel.m4 index 5d6120d1..920e5b56 100644 --- a/data/c++-skel.m4 +++ b/data/c++-skel.m4 @@ -21,7 +21,7 @@ b4_glr_if( [m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.cc]])]) b4_nondeterministic_if([m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.cc]])]) -b4_push_if([b4_complain([[C++ push parsers are not supported]])]) +b4_push_if([b4_complain([[@gettext]])]) m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[lalr1.cc]]) m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"]) diff --git a/data/glr.c b/data/glr.c index 5a40a313..0fed3938 100644 --- a/data/glr.c +++ b/data/glr.c @@ -23,7 +23,7 @@ m4_include(b4_pkgdatadir/[c.m4]) b4_push_if([ -b4_complain([[non-deterministic push parsers are not yet supported]])]) +b4_complain([[@gettext]])]) ## ---------------- ## ## Default values. ## diff --git a/data/glr.cc b/data/glr.cc index d33d23e5..16150b74 100644 --- a/data/glr.cc +++ b/data/glr.cc @@ -53,7 +53,7 @@ m4_define([b4_pure_flag], [1]) # The header is mandatory. b4_defines_if([], - [b4_fatal([b4_skeleton[: using %%defines is mandatory]])]) + [b4_fatal([b4_skeleton[: @gettext]])]) m4_include(b4_pkgdatadir/[c++.m4]) m4_include(b4_pkgdatadir/[location.cc]) diff --git a/data/lalr1.cc b/data/lalr1.cc index 2d53bf9c..5246e0df 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -27,7 +27,7 @@ m4_define([b4_namespace], # The header is mandatory. b4_defines_if([], - [b4_fatal([b4_skeleton[: using %%defines is mandatory]])]) + [b4_fatal([b4_skeleton[: @gettext]])]) # Backward compatibility. m4_define([b4_location_constructors]) diff --git a/src/scan-skel.l b/src/scan-skel.l index d9ca8e28..aab570c6 100644 --- a/src/scan-skel.l +++ b/src/scan-skel.l @@ -53,7 +53,7 @@ static void fail_for_at_directive_too_few_args (void); static void fail_for_invalid_at (char const *at); /* In SC_AT_DIRECTIVE_ARG context, the name of the directive. */ -static char *at_directive_name; +static char *at_directive_name = NULL; /* Currently, only the @warn, @complain, @fatal, @warn_at, @complain_at, and @fatal_at directives take multiple arguments, and the last three already @@ -63,7 +63,8 @@ static int at_directive_argc = 0; static char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX]; %} -%x SC_AT_DIRECTIVE_ARG +%x SC_AT_GETTEXT_ARG +%x SC_AT_DIRECTIVE_ARGS %x SC_AT_DIRECTIVE_SKIP_WS %% @@ -81,14 +82,16 @@ static char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX]; "@ofile@" QPUTS (outname); "@dir_prefix@" QPUTS (dir_prefix); +"@gettext<" BEGIN SC_AT_GETTEXT_ARG; + @[a-z_]+"(" { yytext[yyleng-1] = '\0'; at_directive_name = xstrdup (yytext); - BEGIN SC_AT_DIRECTIVE_ARG; + BEGIN SC_AT_DIRECTIVE_ARGS; } /* This pattern must not match more than the previous @ patterns. */ -@[^@{}(\n]* fail_for_invalid_at (yytext); +@[^<@{}(\n]* fail_for_invalid_at (yytext); \n out_lineno++; ECHO; [^@\n]+ ECHO; @@ -101,15 +104,48 @@ static char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX]; return EOF; } -{ - [^@]+ { STRING_GROW; } +{ + "@>" { + char *arg; + obstack_1grow (&obstack_for_string, '\0'); + arg = obstack_finish (&obstack_for_string); + if (!at_directive_name) + { + fprintf (yyout, "%s", _(arg)); + obstack_free (&obstack_for_string, arg); + BEGIN INITIAL; + } + else + { + char const *translated = _(arg); + size_t parent_size = strlen (at_directive_argv[at_directive_argc]); + size_t translated_size = strlen (translated); + char *copy = xmalloc (parent_size + translated_size + 1); + strcpy (copy, at_directive_argv[at_directive_argc]); + strcpy (copy + parent_size, translated); + obstack_free (&obstack_for_string, + at_directive_argv[at_directive_argc]); + obstack_grow (&obstack_for_string, copy, + parent_size + translated_size); + free (copy); + BEGIN SC_AT_DIRECTIVE_ARGS; + } + } +} - "@@" { obstack_1grow (&obstack_for_string, '@'); } - "@{" { obstack_1grow (&obstack_for_string, '['); } - "@}" { obstack_1grow (&obstack_for_string, ']'); } +{ "@`" /* Emtpy. Useful for starting an argument that begins with whitespace. */ + "@gettext<" { + if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX) + fail_for_at_directive_too_many_args (); + obstack_1grow (&obstack_for_string, '\0'); + at_directive_argv[at_directive_argc] = + obstack_finish (&obstack_for_string); + BEGIN SC_AT_GETTEXT_ARG; + } + @[,)] { if (at_directive_argc >= AT_DIRECTIVE_ARGC_MAX) fail_for_at_directive_too_many_args (); @@ -127,21 +163,29 @@ static char *at_directive_argv[AT_DIRECTIVE_ARGC_MAX]; obstack_free (&obstack_for_string, at_directive_argv[0]); at_directive_argc = 0; free (at_directive_name); + at_directive_name = NULL; BEGIN INITIAL; } } +} +{ + [^@]+ { STRING_GROW; } + "@@" { obstack_1grow (&obstack_for_string, '@'); } + "@{" { obstack_1grow (&obstack_for_string, '['); } + "@}" { obstack_1grow (&obstack_for_string, ']'); } @.? { fail_for_invalid_at (yytext); } } { [ \t\r\n] - . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARG; } + . { yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; } } -{ +{ <> { - fatal (_("unclosed %s directive in skeleton"), at_directive_name); + fatal (_("unclosed %s directive in skeleton"), + at_directive_name ? at_directive_name : "@gettext"); } } @@ -197,21 +241,21 @@ void at_directive_perform (char **outnamep, int *out_linenop) switch (at_directive_argc) { case 1: - func (_(at_directive_argv[0])); + func (at_directive_argv[0]); break; case 2: - func (_(at_directive_argv[0]), at_directive_argv[1]); + func (at_directive_argv[0], at_directive_argv[1]); break; case 3: - func (_(at_directive_argv[0]), at_directive_argv[1], + func (at_directive_argv[0], at_directive_argv[1], at_directive_argv[2]); break; case 4: - func (_(at_directive_argv[0]), at_directive_argv[1], + func (at_directive_argv[0], at_directive_argv[1], at_directive_argv[2], at_directive_argv[3]); break; case 5: - func (_(at_directive_argv[0]), at_directive_argv[1], + func (at_directive_argv[0], at_directive_argv[1], at_directive_argv[2], at_directive_argv[3], at_directive_argv[4]); break; @@ -240,21 +284,21 @@ void at_directive_perform (char **outnamep, int *out_linenop) switch (at_directive_argc) { case 3: - func (loc, _(at_directive_argv[2])); + func (loc, at_directive_argv[2]); break; case 4: - func (loc, _(at_directive_argv[2]), at_directive_argv[3]); + func (loc, at_directive_argv[2], at_directive_argv[3]); break; case 5: - func (loc, _(at_directive_argv[2]), at_directive_argv[3], + func (loc, at_directive_argv[2], at_directive_argv[3], at_directive_argv[4]); break; case 6: - func (loc, _(at_directive_argv[2]), at_directive_argv[3], + func (loc, at_directive_argv[2], at_directive_argv[3], at_directive_argv[4], at_directive_argv[5]); break; case 7: - func (loc, _(at_directive_argv[2]), at_directive_argv[3], + func (loc, at_directive_argv[2], at_directive_argv[3], at_directive_argv[4], at_directive_argv[5], at_directive_argv[6]); break; diff --git a/tests/skeletons.at b/tests/skeletons.at index 79f903ee..0a9c3677 100644 --- a/tests/skeletons.at +++ b/tests/skeletons.at @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. -AT_BANNER([[Skeletons Support.]]) +AT_BANNER([[Skeleton Support.]]) ## ------------------------------ ## ## relative skeleton file names. ## @@ -78,11 +78,11 @@ AT_CHECK([[cat input-cmd-line.tab.c]], [[0]], AT_CLEANUP -## ------------------------------ ## -## installed skeleton file name. ## -## ------------------------------ ## +## ------------------------------- ## +## installed skeleton file names. ## +## ------------------------------- ## -AT_SETUP([[installed skeleton file name]]) +AT_SETUP([[installed skeleton file names]]) m4_pushdef([AT_GRAM], [[%{ @@ -141,3 +141,35 @@ AT_PARSER_CHECK([[./input-gram]], [[1]], [], m4_popdef([AT_GRAM]) AT_CLEANUP + + +## ---------------- ## +## @gettext<...@>. ## +## ---------------- ## + +AT_SETUP([[@gettext<...@>]]) + +AT_DATA([[skel.c]], +[[m4@&t@_divert_push(0)d@&t@nl +@output(b4_parser_file_name@)d@&t@nl +b4_warn([[@gettext]])d@&t@nl +`@gettext' +m4@&t@_divert_pop(0) +]]) + +AT_DATA([[input.y]], +[[%skeleton "./skel.c" +%% +start: ; +]]) + +AT_CHECK([[LC_ALL= LC_MESSAGES= LANGUAGE=fr LANG=fr_FR bison input.y]], [[0]], +[], +[[input.y: AVERTISSEMENT: ne peut fermer le fichier +]]) + +AT_CHECK([[cat input.tab.c]], [[0]], +[[`ne peut fermer le fichier' +]]) + +AT_CLEANUP