Package: gettext
Version: 0.15-2
Severity: important
Hello,
dpkg currently fails to update its POTs which contain strings extracted
from Perl scripts.
The attached Perl script is a minimal example to reproduce this bug.
It also gives some ideas on how to fix the perl scripts to bypass the bug.
xgettext -k_ test.pl
test.pl:10: invalid variable interpolation at "$"
It seems xgettext considers some strings out of _(...) as being part of the
msgid, and thus refuses dollars in the parameters following the format of
printf.
I think the bug is caused by extract_balanced in gettext-tools/src/x-perl.c
This function uses a state and is recusive, but the state is not
propagated back to the caller. I made a test, which uses the following
prototype (state is now a pointer):
static bool extract_balanced (message_list_ty *mlp, int *state,
token_type_ty delim,
flag_context_ty outer_context,
flag_context_list_iterator_ty context_iter,
int arg, struct arglist_parser *argparser);
It works with the attached example, but I did not test it on something
more complicated. Also, I was a little bit lost in the parser, so it may
be completely wrong.
Kind Regards,
--
Nekral
#!/usr/bin/perl
my $a="a";
# These are parsed OK
printf _("%s\n"), $a;
printf (_("%s\n")), "$a";
printf _("%s\n")."", "$a";
# Parsing error
printf _("%s\n"), "$a";
diff -rauN ../orig/gettext-0.15/gettext-tools/src/x-perl.c
./gettext-0.15/gettext-tools/src/x-perl.c
--- ../orig/gettext-0.15/gettext-tools/src/x-perl.c 2006-05-08
15:31:37.000000000 +0200
+++ ./gettext-0.15/gettext-tools/src/x-perl.c 2006-09-11 01:56:16.000000000
+0200
@@ -759,7 +759,7 @@
int lineno);
static token_ty *x_perl_lex (message_list_ty *mlp);
static void x_perl_unlex (token_ty *tp);
-static bool extract_balanced (message_list_ty *mlp, int state,
+static bool extract_balanced (message_list_ty *mlp, int *state,
token_type_ty delim,
flag_context_ty outer_context,
flag_context_list_iterator_ty context_iter,
@@ -1282,6 +1282,7 @@
size_t varbody_length = 0;
bool maybe_hash_deref = false;
bool maybe_hash_value = false;
+ int state = 0;
tp->type = token_type_variable;
@@ -1369,7 +1370,8 @@
real_file_name, line_number);
#endif
- if (extract_balanced (mlp, 0, token_type_rbrace,
+ state = 0;
+ if (extract_balanced (mlp, &state, token_type_rbrace,
null_context, null_context_list_iterator,
1, arglist_parser_alloc (mlp, NULL)))
return;
@@ -1560,7 +1562,8 @@
else
{
x_perl_unlex (t1);
- if (extract_balanced (mlp, 1, token_type_rbrace,
+ state = 1;
+ if (extract_balanced (mlp, &state, token_type_rbrace,
null_context, context_iter,
1, arglist_parser_alloc (mlp,
&shapes)))
return;
@@ -1591,7 +1594,8 @@
fprintf (stderr, "%s:%d: extracting balanced '{' after varname\n",
real_file_name, line_number);
#endif
- extract_balanced (mlp, 0, token_type_rbrace,
+ state = 0;
+ extract_balanced (mlp, &state, token_type_rbrace,
null_context, null_context_list_iterator,
1, arglist_parser_alloc (mlp, NULL));
break;
@@ -1601,7 +1605,8 @@
fprintf (stderr, "%s:%d: extracting balanced '[' after varname\n",
real_file_name, line_number);
#endif
- extract_balanced (mlp, 0, token_type_rbracket,
+ state = 0;
+ extract_balanced (mlp, &state, token_type_rbracket,
null_context, null_context_list_iterator,
1, arglist_parser_alloc (mlp, NULL));
break;
@@ -2821,7 +2826,7 @@
tokens will cause a warning. */
static bool
-extract_balanced (message_list_ty *mlp, int state, token_type_ty delim,
+extract_balanced (message_list_ty *mlp, int *state, token_type_ty delim,
flag_context_ty outer_context,
flag_context_list_iterator_ty context_iter,
int arg, struct arglist_parser *argparser)
@@ -2910,7 +2915,7 @@
last_token = token_type_keyword_symbol;
- state = 2;
+ *state = 2;
}
}
next_is_argument = true;
@@ -3015,7 +3020,7 @@
remember_a_message (mlp, NULL, string, inner_context, &pos,
savable_comment);
xgettext_current_source_encoding =
xgettext_global_source_encoding;
}
- else if (state)
+ else if (*state)
{
char *string = collect_message (mlp, tp, EXIT_FAILURE);
@@ -3033,7 +3038,7 @@
arglist_parser_done (argparser, arg);
xgettext_current_source_encoding =
xgettext_global_source_encoding;
argparser = arglist_parser_alloc (mlp, NULL);
- state = 0;
+ *state = 0;
}
next_is_argument = false;
@@ -3056,7 +3061,8 @@
fprintf (stderr, "%s:%d: type lbrace (%d)\n",
logical_file_name, tp->line_number, nesting_level);
#endif
- if (extract_balanced (mlp, 0, token_type_rbrace,
+ *state = 0;
+ if (extract_balanced (mlp, state, token_type_rbrace,
null_context, null_context_list_iterator,
1, arglist_parser_alloc (mlp, NULL)))
{
@@ -3077,7 +3083,7 @@
#endif
next_is_argument = false;
next_context_iter = null_context_list_iterator;
- state = 0;
+ *state = 0;
break;
case token_type_lbracket:
@@ -3085,7 +3091,8 @@
fprintf (stderr, "%s:%d: type lbracket (%d)\n",
logical_file_name, tp->line_number, nesting_level);
#endif
- if (extract_balanced (mlp, 0, token_type_rbracket,
+ *state = 0;
+ if (extract_balanced (mlp, state, token_type_rbracket,
null_context, null_context_list_iterator,
1, arglist_parser_alloc (mlp, NULL)))
{
@@ -3106,7 +3113,7 @@
#endif
next_is_argument = false;
next_context_iter = null_context_list_iterator;
- state = 0;
+ *state = 0;
break;
case token_type_semicolon:
@@ -3114,7 +3121,7 @@
fprintf (stderr, "%s:%d: type semicolon (%d)\n",
logical_file_name, tp->line_number, nesting_level);
#endif
- state = 0;
+ *state = 0;
/* The ultimate sign. */
xgettext_current_source_encoding = po_charset_utf8;
@@ -3151,7 +3158,7 @@
#endif
next_is_argument = false;
next_context_iter = null_context_list_iterator;
- state = 0;
+ *state = 0;
break;
case token_type_named_op:
@@ -3162,7 +3169,7 @@
#endif
next_is_argument = false;
next_context_iter = null_context_list_iterator;
- state = 0;
+ *state = 0;
break;
case token_type_regex_op:
@@ -3181,7 +3188,7 @@
#endif
next_is_argument = false;
next_context_iter = null_context_list_iterator;
- state = 0;
+ *state = 0;
break;
default:
@@ -3200,6 +3207,7 @@
msgdomain_list_ty *mdlp)
{
message_list_ty *mlp = mdlp->item[0]->messages;
+ int state = 0;
fp = f;
real_file_name = real_filename;
@@ -3223,7 +3231,8 @@
/* Eat tokens until eof is seen. When extract_balanced returns
due to an unbalanced closing brace, just restart it. */
- while (!extract_balanced (mlp, 0, token_type_rbrace,
+ state = 0;
+ while (!extract_balanced (mlp, &state, token_type_rbrace,
null_context, null_context_list_iterator,
1, arglist_parser_alloc (mlp, NULL)))
;