From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1S6YmY-0008IA-LM for mharc-grub-devel@gnu.org; Sat, 10 Mar 2012 21:45:14 -0500 Received: from eggs.gnu.org ([208.118.235.92]:39237) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S6YmV-0008HX-9f for grub-devel@gnu.org; Sat, 10 Mar 2012 21:45:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S6YmS-0002NF-IZ for grub-devel@gnu.org; Sat, 10 Mar 2012 21:45:10 -0500 Received: from mail-wi0-f177.google.com ([209.85.212.177]:62429) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S6YmS-0002MM-38 for grub-devel@gnu.org; Sat, 10 Mar 2012 21:45:08 -0500 Received: by wibhj13 with SMTP id hj13so1750457wib.12 for ; Sat, 10 Mar 2012 18:45:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:x-enigmail-version:content-type; bh=kMiwJcSKMb2Jnyi45PD9Xv6plXaTpjTuFChWxk9RYgM=; b=MUaowWTjl8d6UNryO722V48XuASYVCUMpmk3WrWwJx10Cb3Oqtijh/QBYHEI6vaJVJ YvJjca3z/4wLYAOkx0qAC25PU84bWmKas0nc0ZrSTR2gh4ovy+VNzIlTzobMkEbuEcxH USm5wZBEem2fk1ZBM5oN/A0QX1GihrCRtpr6CS5ZtDdBMomf5W6eazVUYtDzBA2lwY+m OLOkBi/dYF1rb1KR193VaB4zmDAnZ2g2MuN7vHcypluHPuYG/HBENCJRghcV/rDFxsVW H895Pv0k+EDAOuLMFBS1yS/FQrq/uxHTwTNbFLEHVdm08nosHCnHcZNQuRwBWa6bmSF1 tW6A== Received: by 10.180.87.100 with SMTP id w4mr16294180wiz.22.1331433905754; Sat, 10 Mar 2012 18:45:05 -0800 (PST) Received: from fedora.x201.phnet (207-116.62-81.cust.bluewin.ch. [81.62.116.207]) by mx.google.com with ESMTPS id ep17sm20036415wid.2.2012.03.10.18.45.03 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 10 Mar 2012 18:45:04 -0800 (PST) Message-ID: <4F5C11AD.6080100@gmail.com> Date: Sun, 11 Mar 2012 03:45:01 +0100 From: =?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20120131 Thunderbird/10.0 MIME-Version: 1.0 To: The development of GRUB 2 Subject: Re: gettext $"..." References: <4F5BFB64.5060101@gmail.com> <4F5BFE6A.90301@gmail.com> <4F5C0430.90500@gmail.com> In-Reply-To: <4F5C0430.90500@gmail.com> X-Enigmail-Version: 1.3.5 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enig3AB0ACEC9E24701EE85DF015" X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.212.177 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 Mar 2012 02:45:13 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig3AB0ACEC9E24701EE85DF015 Content-Type: multipart/mixed; boundary="------------070601080101030008040306" This is a multi-part message in MIME format. --------------070601080101030008040306 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 11.03.2012 02:47, Vladimir '=CF=86-coder/phcoder' Serbinenko wrote: > Underscore handling. > On 11.03.2012 02:22, Vladimir '=CF=86-coder/phcoder' Serbinenko wrote: >> Update to fix escaping. >> $"" as long as doesn't contain $* or $@ in absence of= >> gettext should behave the same as "" >> On 11.03.2012 02:09, Vladimir '=CF=86-coder/phcoder' Serbinenko wrote:= >>> Hello, all. Following discussion with Jordan Uggla it was found out t= hat >>> current syntax of $"..." without variable expansion isn't enough for = a >>> meaningful i18n and committing ourselves to it by releasing a version= >>> with it would be counter-productive as later we'll need something bet= ter >>> but won't be able to remove something mostly useless. Since the bash >>> behaviour is unsafe due to variable expansion in translated strings. = But >>> it's the very feature that is interesting for translation. There is >>> however a compromise by allowing in translated string only same >>> variables as in the original.This allows translator to rearrange >>> variables as he sees fit but in the same time makes it safe (basicall= y >>> it's printf with reduced syntax and named tokens and without ability = to >>> run over the end). Fortunately only betas were released with $"..." >>> feature and no project has used it for i18n yet. Attached patch >>> implements the described behaviour. >>> Variables $* and $@ can't be used inside $"...". >>> Can someone have a look, comment on approach and/or provide tests? >>> > --=20 Regards Vladimir '=CF=86-coder/phcoder' Serbinenko --------------070601080101030008040306 Content-Type: text/x-diff; name="gettext.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="gettext.diff" =3D=3D=3D modified file 'Makefile.util.def' --- Makefile.util.def 2012-03-10 20:30:37 +0000 +++ Makefile.util.def 2012-03-11 02:31:15 +0000 @@ -666,6 +666,12 @@ common =3D tests/grub_cmd_echo.in; }; =20 +script =3D { + testcase; + name =3D grub_script_gettext; + common =3D tests/grub_script_gettext.in; +}; + program =3D { testcase; name =3D example_unit_test; =3D=3D=3D modified file 'grub-core/script/execute.c' --- grub-core/script/execute.c 2012-03-10 12:19:46 +0000 +++ grub-core/script/execute.c 2012-03-11 02:29:54 +0000 @@ -321,6 +321,211 @@ return grub_env_set (name, val); } =20 +static int +parse_string (const char *str, + int (*hook) (const char *var, grub_size_t varlen), + char **put) +{ + const char *ptr; + int escaped =3D 0; + const char *optr; + + for (ptr =3D str; ptr && *ptr; ) + switch (*ptr) + { + case '\\': + escaped =3D !escaped; + if (!escaped && put) + *((*put)++) =3D '\\'; + ptr++; + break; + case '$': + if (escaped) + { + escaped =3D 0; + if (put) + *((*put)++) =3D *ptr; + ptr++; + break; + } + + ptr++; + switch (*ptr) + { + case '{': + { + optr =3D ptr + 1; + ptr =3D grub_strchr (optr, '}'); + if (!ptr) + break; + if (hook (optr, ptr - optr)) + return 1; + ptr++; + break; + } + case '0' ... '9': + optr =3D ptr; + while (*ptr >=3D '0' && *ptr <=3D '9') + ptr++; + if (hook (optr, ptr - optr)) + return 1; + break; + case 'a' ... 'z': + case 'A' ... 'Z': + case '_': + optr =3D ptr; + while ((*ptr >=3D '0' && *ptr <=3D '9') + || (*ptr >=3D 'a' && *ptr <=3D 'z') + || (*ptr >=3D 'A' && *ptr <=3D 'Z') + || *ptr =3D=3D '_') + ptr++; + if (hook (optr, ptr - optr)) + return 1; + break; + case '?': + case '#': + if (hook (ptr, 1)) + return 1; + ptr++; + break; + } + break; + default: + if (escaped && put) + *((*put)++) =3D '\\'; + escaped =3D 0; + if (put) + *((*put)++) =3D *ptr; + ptr++; + break; + } + return 0; +} + +static int +gettext_append (struct grub_script_argv *result, const char *orig_str) +{ + const char *template; + char *res =3D 0, *ptr; + char **allowed_strings; + grub_size_t nallowed_strings =3D 0; + grub_size_t additional_len =3D 1; + int rval =3D 1; + const char *iptr; + + auto int save_allow (const char *str, grub_size_t len); + int save_allow (const char *str, grub_size_t len) + { + allowed_strings[nallowed_strings++] =3D grub_strndup (str, len); + if (!allowed_strings[nallowed_strings - 1]) + return 1; + return 0; + } + + auto int getlen (const char *str, grub_size_t len); + int getlen (const char *str, grub_size_t len) + { + const char *var; + grub_size_t i; + + for (i =3D 0; i < nallowed_strings; i++) + if (grub_strncmp (allowed_strings[i], str, len) =3D=3D 0 + && allowed_strings[i][len] =3D=3D 0) + break; + if (i =3D=3D nallowed_strings) + return 0; + + /* Enough for any number. */ + if (len =3D=3D 1 && str[0] =3D=3D '#') + { + additional_len +=3D 30; + return 0; + } + var =3D grub_env_get (allowed_strings[i]); + if (var) + additional_len +=3D grub_strlen (var); + return 0; + } + + auto int putvar (const char *str, grub_size_t len); + int putvar (const char *str, grub_size_t len) + { + const char *var; + grub_size_t i; + + for (i =3D 0; i < nallowed_strings; i++) + if (grub_strncmp (allowed_strings[i], str, len) =3D=3D 0 + && allowed_strings[i][len] =3D=3D 0) + { + break; + } + if (i =3D=3D nallowed_strings) + return 0; + + /* Enough for any number. */ + if (len =3D=3D 1 && str[0] =3D=3D '#') + { + grub_snprintf (ptr, 30, "%u", scope->argv.argc); + ptr +=3D grub_strlen (ptr); + return 0; + } + var =3D grub_env_get (allowed_strings[i]); + if (var) + ptr =3D grub_stpcpy (ptr, var); + return 0; + } + + grub_size_t dollar_cnt =3D 0; + + for (iptr =3D orig_str; *iptr; iptr++) + if (*iptr =3D=3D '$') + dollar_cnt++; + allowed_strings =3D grub_malloc (sizeof (allowed_strings[0]) * dollar_= cnt); + + if (parse_string (orig_str, save_allow, 0)) + goto fail; + + template =3D _(orig_str); + + if (parse_string (template, getlen, 0)) + goto fail; + + res =3D grub_malloc (grub_strlen (template) + additional_len); + if (!res) + goto fail; + ptr =3D res; + + if (parse_string (template, putvar, &ptr)) + goto fail; + + *ptr =3D 0; + if (grub_wildcard_translator) + { + char *escaped =3D 0; + escaped =3D grub_wildcard_translator->escape (res); + if (grub_script_argv_append (result, escaped, grub_strlen (escaped= ))) + { + grub_free (escaped); + goto fail; + } + grub_free (escaped); + } + else + if (grub_script_argv_append (result, res, ptr - res)) + goto fail; + + rval =3D 0; + fail: + grub_free (res); + { + grub_size_t i; + for (i =3D 0; i < nallowed_strings; i++) + grub_free (allowed_strings[i]); + } + grub_free (allowed_strings); + return rval; +} + /* Convert arguments in ARGLIST into ARGV form. */ static int grub_script_arglist_to_argv (struct grub_script_arglist *arglist, @@ -406,8 +611,7 @@ =20 case GRUB_SCRIPT_ARG_TYPE_GETTEXT: { - const char *t =3D _(arg->str); - if (grub_script_argv_append (&result, t, grub_strlen (t))) + if (gettext_append (&result, arg->str)) goto fail; } break; =3D=3D=3D modified file 'grub-core/script/yylex.l' --- grub-core/script/yylex.l 2012-02-26 18:02:46 +0000 +++ grub-core/script/yylex.l 2012-03-11 01:16:17 +0000 @@ -289,7 +289,7 @@ } =20 { - \\\\ { COPY ("\\", 1); } + \\\\ { COPY ("\\\\", 2); } \\\" { COPY ("\"", 1); } \\\n { /* ignore */ } [^\"\\\n]+ { COPY (yytext, yyleng); } @@ -297,6 +297,7 @@ yy_pop_state (yyscanner); ARG (GRUB_SCRIPT_ARG_TYPE_GETTEXT); } + \\ { COPY ("\\", 1); } (.|\n) { COPY (yytext, yyleng); } } =20 =3D=3D=3D added file 'tests/grub_script_gettext.in' --- tests/grub_script_gettext.in 1970-01-01 00:00:00 +0000 +++ tests/grub_script_gettext.in 2012-03-11 02:25:41 +0000 @@ -0,0 +1,36 @@ +#! @builddir@/grub-shell-tester +# +# Copyright (C) 2010,2012 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +echo $"foo" +echo $"foo bar" + +echo -n $"foo" + +echo -e $"foo\nbar" + +echo -n -e $"foo\nbar" + +x=3D5 +echo $"$x" +echo $"\x\\y\$x$x\\$xx${x}x\"$x\"" + +if test -n "$grubshell"; then insmod regexp; fi + +echo $"*" + +foo=3D"*" +echo $"$foo" --------------070601080101030008040306-- --------------enig3AB0ACEC9E24701EE85DF015 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iF4EAREKAAYFAk9cEa4ACgkQNak7dOguQgkhkgD+MZKRytV2YPFcXBBZWqN8YN4Z A3ydnqNcd5+q6JmuCoEA/jWSA93iIbhewuMrU+NKRKiztDNxoWLn+sep3La+iAhK =eZzw -----END PGP SIGNATURE----- --------------enig3AB0ACEC9E24701EE85DF015--