From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1S6XIU-0008MX-Sv for mharc-grub-devel@gnu.org; Sat, 10 Mar 2012 20:10:06 -0500 Received: from eggs.gnu.org ([208.118.235.92]:43944) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S6XIS-0008Lh-Gv for grub-devel@gnu.org; Sat, 10 Mar 2012 20:10:06 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S6XIQ-0005RT-6K for grub-devel@gnu.org; Sat, 10 Mar 2012 20:10:04 -0500 Received: from mail-we0-f169.google.com ([74.125.82.169]:58012) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S6XIP-0005QL-QD for grub-devel@gnu.org; Sat, 10 Mar 2012 20:10:02 -0500 Received: by werj55 with SMTP id j55so2701369wer.0 for ; Sat, 10 Mar 2012 17:09:59 -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 :x-enigmail-version:content-type; bh=myvrTnBUdB5mDGgeayoZXdrhKcse87VSYVs2ri7YG+M=; b=mgxeehKIgsJ8wbbwxWih0og6leS0Ct8B8tZSlXCJ+CKNmd6e/jvHC8H+PBBPWIQXKX DAa4A3o2qLcfbY8a+uHb+h7EgYjvht9J7myeA1eyw+Lv1e/1PWewix9OMIMmOhEY/kPb Rep9W6sS+ln1A/x3QKmj6vz80TEtOCH/62Am8MC2ubbd7F1HSciByi3mgVaB0ID3UFhz iwAAxmn6aY3nrddraIlPBfZ1z5aXKMMBKoRJ7UCGKtwM/Gub0qUm0Py8FlwStZfownkz UQYBT4J8VsRgyvDF1XX+E9tHrFEG9sTN/A6pJJnULjZ/5R2kA2vuXOuRlnJPWL73sT2B V/PQ== Received: by 10.180.24.4 with SMTP id q4mr16094183wif.7.1331428199788; Sat, 10 Mar 2012 17:09:59 -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 ff2sm34267647wib.9.2012.03.10.17.09.57 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 10 Mar 2012 17:09:58 -0800 (PST) Message-ID: <4F5BFB64.5060101@gmail.com> Date: Sun, 11 Mar 2012 02:09:56 +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: gettext $"..." X-Enigmail-Version: 1.3.5 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enigDADF40536EF1DF682DAC9FFC" X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.125.82.169 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 01:10:06 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigDADF40536EF1DF682DAC9FFC Content-Type: multipart/mixed; boundary="------------000601070405020109070901" This is a multi-part message in MIME format. --------------000601070405020109070901 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Hello, all. Following discussion with Jordan Uggla it was found out that 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 better 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 (basically 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 --------------000601070405020109070901 Content-Type: text/x-diff; name="gettext.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="gettext.diff" =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 00:29:19 +0000 @@ -321,6 +321,187 @@ 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) + { + 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++; + if (hook (optr, ptr - optr)) + return 1; + break; + case '?': + case '#': + if (hook (ptr, 1)) + return 1; + ptr++; + break; + } + } + default: + 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; + + 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 +587,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; --------------000601070405020109070901-- --------------enigDADF40536EF1DF682DAC9FFC 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/ iF4EAREKAAYFAk9b+2QACgkQNak7dOguQgnVKwD+K6s2glM99Heb87rdsXeX/OST UMoosH1qN4y8e8YTAwoA/iG2ukBafgEvNGNLIN9BB9dCQ3EiM7FqnvefNzaGbK3Y =fuYD -----END PGP SIGNATURE----- --------------enigDADF40536EF1DF682DAC9FFC--