]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
xgettext: Provide a way to interpret string literals lazily
authorDaiki Ueno <ueno@gnu.org>
Wed, 7 May 2014 09:48:25 +0000 (18:48 +0900)
committerDaiki Ueno <ueno@gnu.org>
Fri, 9 May 2014 08:32:09 +0000 (17:32 +0900)
* xgettext.c (extract_ty): New field 'literalstring_parser'.
(current_literalstring_parser): New variable.
(extract_from_file): Set 'current_literalstring_parser'.
(savable_comment_convert_encoding): New function.
(arglist_parser_remember_literal): New function.
(arglist_parser_remember): Call 'arglist_parser_remember_literal'.
(arglist_parser_done): Call literalstring_parser on msgctxt,
msgid, and msgid_plural before calling 'remember_a_message';
convert encoding of msgid_comment.
* x-*.h: Register 'literalstring_parser' through SCANNER_*.
* xgettext.h (enum literalstring_escape_type): New enum.
(struct literalstring_parser): New struct.
(struct partial_call): New fields 'msgctxt_escape',
'msgid_escape', and 'msgid_plural_escape'.
(arglist_parser_remember_literal): New function declaration.
(savable_comment_convert_encoding): New function declaration.

28 files changed:
gettext-tools/src/ChangeLog
gettext-tools/src/x-awk.h
gettext-tools/src/x-c.h
gettext-tools/src/x-csharp.h
gettext-tools/src/x-desktop.h
gettext-tools/src/x-elisp.h
gettext-tools/src/x-glade.h
gettext-tools/src/x-gsettings.h
gettext-tools/src/x-java.h
gettext-tools/src/x-javascript.h
gettext-tools/src/x-librep.h
gettext-tools/src/x-lisp.h
gettext-tools/src/x-lua.h
gettext-tools/src/x-perl.h
gettext-tools/src/x-php.h
gettext-tools/src/x-po.h
gettext-tools/src/x-properties.h
gettext-tools/src/x-python.h
gettext-tools/src/x-rst.h
gettext-tools/src/x-scheme.h
gettext-tools/src/x-sh.h
gettext-tools/src/x-smalltalk.h
gettext-tools/src/x-stringtable.h
gettext-tools/src/x-tcl.h
gettext-tools/src/x-vala.h
gettext-tools/src/x-ycp.h
gettext-tools/src/xgettext.c
gettext-tools/src/xgettext.h

index a220e2c4fcf121a699cb956be1f29d3a77131024..26a4b151ab5f8b5c901a5defd19de2d888c9b8f8 100644 (file)
@@ -1,3 +1,23 @@
+2014-05-09  Daiki Ueno  <ueno@gnu.org>
+
+       xgettext: Provide a way to interpret string literals lazily
+       * xgettext.c (extract_ty): New field 'literalstring_parser'.
+       (current_literalstring_parser): New variable.
+       (extract_from_file): Set 'current_literalstring_parser'.
+       (savable_comment_convert_encoding): New function.
+       (arglist_parser_remember_literal): New function.
+       (arglist_parser_remember): Call 'arglist_parser_remember_literal'.
+       (arglist_parser_done): Call literalstring_parser on msgctxt,
+       msgid, and msgid_plural before calling 'remember_a_message';
+       convert encoding of msgid_comment.
+       * x-*.h: Register 'literalstring_parser' through SCANNER_*.
+       * xgettext.h (enum literalstring_escape_type): New enum.
+       (struct literalstring_parser): New struct.
+       (struct partial_call): New fields 'msgctxt_escape',
+       'msgid_escape', and 'msgid_plural_escape'.
+       (arglist_parser_remember_literal): New function declaration.
+       (savable_comment_convert_encoding): New function declaration.
+
 2014-05-03  Daiki Ueno  <ueno@gnu.org>
 
        xgettext: Recognize prefixed comment tag
index 6cfd33b7f7edd3a0e4006417d8485fa732d8d7d1..642c0e27cf7b0200a3c7252d2750bb18d6eeed7c 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_AWK \
   { "awk",              extract_awk,                                    \
-                        &flag_table_awk, &formatstring_awk, NULL },     \
+                        &flag_table_awk, &formatstring_awk, NULL, NULL }, \
 
 /* Scan an awk file and add its translatable strings to mdlp.  */
 extern void extract_awk (FILE *fp, const char *real_filename,
index 643345fa01b2fb05d8556625ec870ab6a429ad78..28c5b9282e04f6233fa20b879392951ad29e92f7 100644 (file)
@@ -43,16 +43,16 @@ extern "C" {
 #define SCANNERS_C \
   { "C",                extract_c,                                      \
                         &flag_table_c,                                  \
-                        &formatstring_c, NULL },                        \
+                        &formatstring_c, NULL, NULL },                        \
   { "C++",              extract_c,                                      \
                         &flag_table_c,                                  \
-                        &formatstring_c, NULL },                        \
+                        &formatstring_c, NULL, NULL },                        \
   { "ObjectiveC",       extract_objc,                                   \
                         &flag_table_objc,                               \
-                        &formatstring_c, &formatstring_objc },          \
+                        &formatstring_c, &formatstring_objc, NULL },          \
   { "GCC-source",       extract_c,                                      \
                         &flag_table_gcc_internal,                       \
-                        &formatstring_gcc_internal, &formatstring_gfc_internal }, \
+                        &formatstring_gcc_internal, &formatstring_gfc_internal, NULL }, \
 
 /* Scan a C/C++ file and add its translatable strings to mdlp.  */
 extern void extract_c (FILE *fp, const char *real_filename,
index 9cfb1d8d83462e157a1eb7d4e421a606ed2e847e..de37789ffade123fe638ead2a353628df6ab4f8f 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_CSHARP \
   { "C#",               extract_csharp,                                   \
-                        &flag_table_csharp, &formatstring_csharp, NULL }, \
+                        &flag_table_csharp, &formatstring_csharp, NULL, NULL }, \
 
 extern void extract_csharp (FILE *fp, const char *real_filename,
                             const char *logical_filename,
index d9f1ff44d58f2b504c783a36187012d40728c92c..d24f1741e2718bb591ccf25f74df15f6a8b99252 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
   { "desktop", "Desktop" }, \
 
 #define SCANNERS_DESKTOP \
-  { "Desktop", extract_desktop, NULL, NULL, NULL }, \
+  { "Desktop", extract_desktop, NULL, NULL, NULL, NULL }, \
 
 /* Scan a Desktop Entry file and add its translatable strings to mdlp.  */
 extern void extract_desktop (FILE *fp, const char *real_filename,
index b0f7123abe5d29667e700d7e4023aaf003403112..f93995794880fb193c5d7a3f50fc6bc892c5003e 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_ELISP \
   { "EmacsLisp",        extract_elisp,                                  \
-                        &flag_table_elisp, &formatstring_elisp, NULL }, \
+                        &flag_table_elisp, &formatstring_elisp, NULL, NULL }, \
 
 /* Scan an Emacs Lisp file and add its translatable strings to mdlp.  */
 extern void extract_elisp (FILE *fp, const char *real_filename,
index e3cc2535f299c40dfb48fd4f0e92c5bf9e8d5e6e..f212d2b0b3912d959325e28fdad7c7e80f5f08c0 100644 (file)
@@ -33,7 +33,7 @@ extern "C" {
   { "ui",        "glade"    },                                          \
 
 #define SCANNERS_GLADE \
-  { "glade",            extract_glade, NULL, NULL, NULL },              \
+  { "glade",            extract_glade, NULL, NULL, NULL, NULL },              \
 
 /* Scan a glade XML file and add its translatable strings to mdlp.  */
 extern void extract_glade (FILE *fp, const char *real_filename,
index 073b4183c6b1248e23c1c3c2820ea7d966b466ce..b06016debb380bb2d78ba25e1fe46d70ed596bea 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
   { "gschema.xml", "gsettings" }, \
 
 #define SCANNERS_GSETTINGS \
-  { "gsettings", extract_gsettings, NULL, NULL, NULL }, \
+  { "gsettings", extract_gsettings, NULL, NULL, NULL, NULL }, \
 
 /* Scan a gsettings XML file and add its translatable strings to mdlp.  */
 extern void extract_gsettings (FILE *fp, const char *real_filename,
index 31436c5e336bf4144c6d12b3a6dabe35a3fba006..49f2af9a3b1bb93828fec0ab1ec8d26886974b8d 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_JAVA \
   { "Java",             extract_java,                                   \
-                        &flag_table_java, &formatstring_java, NULL },   \
+                        &flag_table_java, &formatstring_java, NULL, NULL },   \
 
 extern void extract_java (FILE *fp, const char *real_filename,
                           const char *logical_filename,
index da40f71c1a985cbcee26d3af21ad4f5fbc090b18..a2f64187bfd664b021738ce5afb8e51e5e71bbb8 100644 (file)
@@ -33,7 +33,7 @@ extern "C" {
 
 #define SCANNERS_JAVASCRIPT \
   { "JavaScript",       extract_javascript,                               \
-                        &flag_table_javascript, &formatstring_javascript, NULL }, \
+                        &flag_table_javascript, &formatstring_javascript, NULL, NULL }, \
 
 /* Scan a Python file and add its translatable strings to mdlp.  */
 extern void extract_javascript (FILE *fp, const char *real_filename,
index 8937d517792975e2315279e100eb6642071c3bff..5747db166104f34adba054d575ece385b65ff64c 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_LIBREP \
   { "librep",           extract_librep,                                   \
-                        &flag_table_librep, &formatstring_librep, NULL }, \
+                        &flag_table_librep, &formatstring_librep, NULL, NULL }, \
 
 /* Scan a librep file and add its translatable strings to mdlp.  */
 extern void extract_librep (FILE *fp, const char *real_filename,
index 9988f62869a5c4ebb2616caf5fb45373756ca695..97b593d097afa4af6da0047fbf0e38c3c397ea17 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_LISP \
   { "Lisp",             extract_lisp,                                   \
-                        &flag_table_lisp, &formatstring_lisp, NULL },   \
+                        &flag_table_lisp, &formatstring_lisp, NULL, NULL },   \
 
 /* Scan a Lisp file and add its translatable strings to mdlp.  */
 extern void extract_lisp (FILE *fp, const char *real_filename,
index bca030491311b5f75e79b7a49e1dfddec451c5eb..31616381647b75d60251b56cac1a34f11e942d72 100644 (file)
@@ -30,7 +30,7 @@ extern "C"
 
 #define SCANNERS_LUA \
   { "Lua",             extract_lua,                                     \
-                       &flag_table_lua, &formatstring_lua, NULL },      \
+                       &flag_table_lua, &formatstring_lua, NULL, NULL },      \
 
   /* Scan a Lua file and add its translatable strings to mdlp.  */
   extern void extract_lua (FILE * fp, const char *real_filename,
index 0ee1703b2fb6b6bca40ffaa7622460352d1e7e50..8e140e9fd33d3ef3dfadf63bc9ddd323da371e20 100644 (file)
@@ -36,7 +36,7 @@ extern "C" {
 
 #define SCANNERS_PERL \
   { "perl",             extract_perl,                                   \
-            &flag_table_perl, &formatstring_perl, &formatstring_perl_brace }, \
+            &flag_table_perl, &formatstring_perl, &formatstring_perl_brace, NULL }, \
 
 /* Scan a Perl file and add its translatable strings to mdlp.  */
 extern void extract_perl (FILE *fp, const char *real_filename,
index 765f3f093ed3c9d13b6890f54bfc1daf7b826790..79442b44769bb28c31cbb87c9f6a44dfdc8cf920 100644 (file)
@@ -34,7 +34,7 @@ extern "C" {
 
 #define SCANNERS_PHP \
   { "PHP",              extract_php,                                    \
-                        &flag_table_php, &formatstring_php, NULL },     \
+                        &flag_table_php, &formatstring_php, NULL, NULL },     \
 
 /* Scan a PHP file and add its translatable strings to mdlp.  */
 extern void extract_php (FILE *fp, const char *real_filename,
index eda1669a1e69ce645b78afb9f832c2504cf931a3..0d350d85f987c33a186353df863c3cdaa99b43ba 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
   { "pot",    "PO"    },                                                \
 
 #define SCANNERS_PO \
-  { "PO",               extract_po, NULL, NULL, NULL },                 \
+  { "PO",               extract_po, NULL, NULL, NULL, NULL },                 \
 
 /* Scan a PO file and add its translatable strings to mdlp.  */
 extern void extract_po (FILE *fp, const char *real_filename,
index b877ae4f7e62d9e4520218e11844fd4db7d7e059..fd16ab378e2dab21f90dfd9e91520073e478bec0 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
   { "properties", "JavaProperties" },                                   \
 
 #define SCANNERS_PROPERTIES \
-  { "JavaProperties",   extract_properties, NULL, NULL, NULL },         \
+  { "JavaProperties",   extract_properties, NULL, NULL, NULL, NULL },         \
 
 /* Scan a JavaProperties file and add its translatable strings to mdlp.  */
 extern void extract_properties (FILE *fp, const char *real_filename,
index b70b048d7979707d19756b0a52aa894c51641282..f7861fb615b2d506c6f3bbdfa61293f3aa49de5e 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_PYTHON \
   { "Python",           extract_python,                                   \
-                        &flag_table_python, &formatstring_python, &formatstring_python_brace }, \
+                        &flag_table_python, &formatstring_python, &formatstring_python_brace, NULL }, \
 
 /* Scan a Python file and add its translatable strings to mdlp.  */
 extern void extract_python (FILE *fp, const char *real_filename,
index dd214fc00fbe5bd17a3642c7f51152a10cb9c8aa..6507d0dda27ac9f73bf53d7be759b7328851ba4d 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_RST \
   { "RST",              extract_rst,                                    \
-                        NULL, &formatstring_pascal, NULL },             \
+                        NULL, &formatstring_pascal, NULL, NULL },             \
 
 /* Scan an RST file and add its translatable strings to mdlp.  */
 extern void extract_rst (FILE *fp, const char *real_filename,
index 3eb100cc15f70039309e4ca0d303e8cd4e7109f2..a159ab16a705eac20af6fdd9a77e120840d9d911 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_SCHEME \
   { "Scheme",           extract_scheme,                                   \
-                        &flag_table_scheme, &formatstring_scheme, NULL }, \
+                        &flag_table_scheme, &formatstring_scheme, NULL, NULL }, \
 
 /* Scan a Scheme file and add its translatable strings to mdlp.  */
 extern void extract_scheme (FILE *fp, const char *real_filename,
index a07954e4dcc1547a5a205fe7f0309a92aa16ba3f..d235751f416e2e163c0d9db9acc3483f2222397b 100644 (file)
@@ -33,7 +33,7 @@ extern "C" {
 
 #define SCANNERS_SH \
   { "Shell",            extract_sh,                                     \
-                        &flag_table_sh, &formatstring_sh, NULL },       \
+                        &flag_table_sh, &formatstring_sh, NULL, NULL },       \
 
 /* Scan a shell script file and add its translatable strings to mdlp.  */
 extern void extract_sh (FILE *fp, const char *real_filename,
index def25ffedac98b9d30d6be934cb736d86867e79d..10767d9eb9ee97d440ebd105f2766a5f78422123 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_SMALLTALK \
   { "Smalltalk",        extract_smalltalk,                              \
-                        NULL, &formatstring_smalltalk, NULL },          \
+                        NULL, &formatstring_smalltalk, NULL, NULL },          \
 
 /* Scan a Smalltalk file and add its translatable strings to mdlp.  */
 extern void extract_smalltalk (FILE *fp, const char *real_filename,
index c405c0cb395bcb875d103c18f47fb985e7386409..57df745051495639c93ef4b47e7ebc3d1ca53798 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
   { "strings", "NXStringTable" },                                       \
 
 #define SCANNERS_STRINGTABLE \
-  { "NXStringTable",    extract_stringtable, NULL, NULL, NULL },        \
+  { "NXStringTable",    extract_stringtable, NULL, NULL, NULL, NULL },        \
 
 /* Scan a JavaProperties file and add its translatable strings to mdlp.  */
 extern void extract_stringtable (FILE *fp, const char *real_filename,
index aafe6a0f52b3c0a91e44709f3742ec100b26289b..1dc5412cdba564eab8d8b459f290beccf589055b 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_TCL \
   { "Tcl",              extract_tcl,                                    \
-                        &flag_table_tcl, &formatstring_tcl, NULL },     \
+                        &flag_table_tcl, &formatstring_tcl, NULL, NULL },     \
 
 /* Scan a Tcl file and add its translatable strings to mdlp.  */
 extern void extract_tcl (FILE *fp, const char *real_filename,
index db9a66de659563baad8844a38ce9a08fa721c3bf..249709f5671e7d11ebf9d857aa272c9015a33e42 100644 (file)
@@ -31,7 +31,7 @@ extern "C" {
 
 #define SCANNERS_VALA \
   { "Vala",       extract_vala,                               \
-                        &flag_table_vala, &formatstring_c, NULL }, \
+                        &flag_table_vala, &formatstring_c, NULL, NULL }, \
 
 /* Scan a Vala file and add its translatable strings to mdlp.  */
 extern void extract_vala (FILE *fp, const char *real_filename,
index 01eaf6205dd01cd2fd5853d41efd51035937332c..78cc8530550fba683bfbc1e9643ca6ac16bcc72c 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 
 #define SCANNERS_YCP \
   { "YCP",              extract_ycp,                                    \
-                        &flag_table_ycp, &formatstring_ycp, NULL },     \
+                        &flag_table_ycp, &formatstring_ycp, NULL, NULL },     \
 
 /* Scan an YCP file and add its translatable strings to mdlp.  */
 extern void extract_ycp (FILE *fp, const char *real_filename,
index 7481d3aa4febc916b4271e908034102ae72c5e1a..891613efa17cbf4d7bb377f3827f54b96b635e57 100644 (file)
@@ -265,6 +265,7 @@ struct extractor_ty
   struct formatstring_parser *formatstring_parser1;
   struct formatstring_parser *formatstring_parser2;
   struct formatstring_parser *formatstring_parser3;
+  struct literalstring_parser *literalstring_parser;
 };
 
 
@@ -1923,6 +1924,32 @@ savable_comment_to_xgettext_comment (refcounted_string_list_ty *rslp)
     }
 }
 
+refcounted_string_list_ty *
+savable_comment_convert_encoding (refcounted_string_list_ty *comment,
+                                  lex_pos_ty *pos)
+{
+  refcounted_string_list_ty *result;
+  size_t i;
+
+  result = XMALLOC (refcounted_string_list_ty);
+  result->refcount = 1;
+  string_list_init (&result->contents);
+
+  for (i = 0; i < comment->contents.nitems; i++)
+    {
+      const char *old_string = comment->contents.item[i];
+      char *string = from_current_source_encoding (old_string,
+                                                   lc_comment,
+                                                   pos->file_name,
+                                                   pos->line_number);
+      string_list_append (&result->contents, string);
+      if (string != old_string)
+        free (string);
+    }
+
+  return result;
+}
+
 
 
 static FILE *
@@ -1992,6 +2019,7 @@ static struct formatstring_parser *current_formatstring_parser1;
 static struct formatstring_parser *current_formatstring_parser2;
 static struct formatstring_parser *current_formatstring_parser3;
 
+static struct literalstring_parser *current_literalstring_parser;
 
 static void
 extract_from_file (const char *file_name, extractor_ty extractor,
@@ -2011,6 +2039,7 @@ extract_from_file (const char *file_name, extractor_ty extractor,
   current_formatstring_parser1 = extractor.formatstring_parser1;
   current_formatstring_parser2 = extractor.formatstring_parser2;
   current_formatstring_parser3 = extractor.formatstring_parser3;
+  current_literalstring_parser = extractor.literalstring_parser;
   extractor.func (fp, real_file_name, logical_file_name, extractor.flag_table,
                   mdlp);
 
@@ -2655,14 +2684,17 @@ arglist_parser_alloc (message_list_ty *mlp, const struct callshapes *shapes)
           ap->alternative[i].argtotal = shapes->shapes[i].argtotal;
           ap->alternative[i].xcomments = shapes->shapes[i].xcomments;
           ap->alternative[i].msgctxt = NULL;
+          ap->alternative[i].msgctxt_escape = 0;
           ap->alternative[i].msgctxt_pos.file_name = NULL;
           ap->alternative[i].msgctxt_pos.line_number = (size_t)(-1);
           ap->alternative[i].msgid = NULL;
+          ap->alternative[i].msgid_escape = 0;
           ap->alternative[i].msgid_context = null_context;
           ap->alternative[i].msgid_pos.file_name = NULL;
           ap->alternative[i].msgid_pos.line_number = (size_t)(-1);
           ap->alternative[i].msgid_comment = NULL;
           ap->alternative[i].msgid_plural = NULL;
+          ap->alternative[i].msgid_plural_escape = 0;
           ap->alternative[i].msgid_plural_context = null_context;
           ap->alternative[i].msgid_plural_pos.file_name = NULL;
           ap->alternative[i].msgid_plural_pos.line_number = (size_t)(-1);
@@ -2699,13 +2731,16 @@ arglist_parser_clone (struct arglist_parser *ap)
       ccp->argtotal = cp->argtotal;
       ccp->xcomments = cp->xcomments;
       ccp->msgctxt = (cp->msgctxt != NULL ? xstrdup (cp->msgctxt) : NULL);
+      ccp->msgctxt_escape = cp->msgctxt_escape;
       ccp->msgctxt_pos = cp->msgctxt_pos;
       ccp->msgid = (cp->msgid != NULL ? xstrdup (cp->msgid) : NULL);
+      ccp->msgid_escape = cp->msgid_escape;
       ccp->msgid_context = cp->msgid_context;
       ccp->msgid_pos = cp->msgctxt_pos;
       ccp->msgid_comment = add_reference (cp->msgid_comment);
       ccp->msgid_plural =
         (cp->msgid_plural != NULL ? xstrdup (cp->msgid_plural) : NULL);
+      ccp->msgid_plural_escape = cp->msgid_plural_escape;
       ccp->msgid_plural_context = cp->msgid_plural_context;
       ccp->msgid_plural_pos = cp->msgid_plural_pos;
     }
@@ -2715,11 +2750,12 @@ arglist_parser_clone (struct arglist_parser *ap)
 
 
 void
-arglist_parser_remember (struct arglist_parser *ap,
-                         int argnum, char *string,
-                         flag_context_ty context,
-                         char *file_name, size_t line_number,
-                         refcounted_string_list_ty *comment)
+arglist_parser_remember_literal (struct arglist_parser *ap,
+                                 int argnum, char *string,
+                                 flag_context_ty context,
+                                 char *file_name, size_t line_number,
+                                 refcounted_string_list_ty *comment,
+                                 enum literalstring_escape_type type)
 {
   bool stored_string = false;
   size_t nalternatives = ap->nalternatives;
@@ -2734,6 +2770,7 @@ arglist_parser_remember (struct arglist_parser *ap,
       if (argnum == cp->argnumc)
         {
           cp->msgctxt = string;
+          cp->msgctxt_escape = type;
           cp->msgctxt_pos.file_name = file_name;
           cp->msgctxt_pos.line_number = line_number;
           stored_string = true;
@@ -2745,6 +2782,7 @@ arglist_parser_remember (struct arglist_parser *ap,
           if (argnum == cp->argnum1)
             {
               cp->msgid = string;
+              cp->msgid_escape = type;
               cp->msgid_context = context;
               cp->msgid_pos.file_name = file_name;
               cp->msgid_pos.line_number = line_number;
@@ -2756,6 +2794,7 @@ arglist_parser_remember (struct arglist_parser *ap,
           if (argnum == cp->argnum2)
             {
               cp->msgid_plural = string;
+              cp->msgid_plural_escape = type;
               cp->msgid_plural_context = context;
               cp->msgid_plural_pos.file_name = file_name;
               cp->msgid_plural_pos.line_number = line_number;
@@ -2771,6 +2810,17 @@ arglist_parser_remember (struct arglist_parser *ap,
     free (string);
 }
 
+void
+arglist_parser_remember (struct arglist_parser *ap,
+                         int argnum, char *string,
+                         flag_context_ty context,
+                         char *file_name, size_t line_number,
+                         refcounted_string_list_ty *comment)
+{
+  arglist_parser_remember_literal (ap, argnum, string, context,
+                                   file_name, line_number,
+                                   comment, 0);
+}
 
 bool
 arglist_parser_decidedp (struct arglist_parser *ap, int argnum)
@@ -3011,6 +3061,8 @@ arglist_parser_done (struct arglist_parser *ap, int argnum)
           {
             flag_context_ty msgid_context = best_cp->msgid_context;
             flag_context_ty msgid_plural_context = best_cp->msgid_plural_context;
+            struct literalstring_parser *parser = current_literalstring_parser;
+            const char *encoding;
 
             /* Special support for the 3-argument tr operator in Qt:
                When --qt and --keyword=tr:1,1,2c,3t are specified, add to the
@@ -3024,15 +3076,90 @@ arglist_parser_done (struct arglist_parser *ap, int argnum)
                 msgid_plural_context.is_format3 = yes_according_to_context;
               }
 
+            if (best_cp->msgctxt != NULL)
+              {
+                if (parser != NULL && best_cp->msgctxt_escape != 0)
+                  {
+                    char *msgctxt =
+                      parser->parse (best_cp->msgctxt,
+                                     &best_cp->msgctxt_pos,
+                                     best_cp->msgctxt_escape);
+                    free (best_cp->msgctxt);
+                    best_cp->msgctxt = msgctxt;
+                  }
+                else
+                  {
+                    lex_pos_ty *pos = &best_cp->msgctxt_pos;
+                    CONVERT_STRING (best_cp->msgctxt, lc_string);
+                  }
+              }
+
+            if (parser != NULL && best_cp->msgid_escape != 0)
+              {
+                char *msgid = parser->parse (best_cp->msgid,
+                                             &best_cp->msgid_pos,
+                                             best_cp->msgid_escape);
+                free (best_cp->msgid);
+                if (best_cp->msgid_plural == best_cp->msgid)
+                  best_cp->msgid_plural = msgid;
+                best_cp->msgid = msgid;
+              }
+            else
+              {
+                lex_pos_ty *pos = &best_cp->msgid_pos;
+                CONVERT_STRING (best_cp->msgid, lc_string);
+              }
+
+            if (best_cp->msgid_comment != NULL)
+              {
+                refcounted_string_list_ty *msgid_comment =
+                  savable_comment_convert_encoding (best_cp->msgid_comment,
+                                                    &best_cp->msgid_pos);
+                drop_reference (best_cp->msgid_comment);
+                best_cp->msgid_comment = msgid_comment;
+              }
+
+            /* best_cp->msgctxt and best_cp->msgid are already in
+               UTF-8.  Prevent further conversion in remember_a_message.  */
+            encoding = xgettext_current_source_encoding;
+            xgettext_current_source_encoding = po_charset_utf8;
             mp = remember_a_message (ap->mlp, best_cp->msgctxt, best_cp->msgid,
                                      msgid_context,
                                      &best_cp->msgid_pos,
                                      NULL, best_cp->msgid_comment);
+            xgettext_current_source_encoding = encoding;
+
             if (mp != NULL && best_cp->msgid_plural != NULL)
-              remember_a_message_plural (mp, best_cp->msgid_plural,
-                                         msgid_plural_context,
+              {
+                /* best_cp->msgid_plural may point to best_cp->msgid.
+                   In that case, it is already interpreted and converted.  */
+                if (best_cp->msgid_plural != best_cp->msgid)
+                  {
+                    if (parser != NULL
+                        && best_cp->msgid_plural_escape != 0)
+                      {
+                        char *msgid_plural =
+                          parser->parse (best_cp->msgid_plural,
                                          &best_cp->msgid_plural_pos,
-                                         NULL);
+                                         best_cp->msgid_plural_escape);
+                        free (best_cp->msgid_plural);
+                        best_cp->msgid_plural = msgid_plural;
+                      }
+                    else
+                      {
+                        lex_pos_ty *pos = &best_cp->msgid_plural_pos;
+                        CONVERT_STRING (best_cp->msgid_plural, lc_string);
+                      }
+                  }
+
+                encoding = xgettext_current_source_encoding;
+                xgettext_current_source_encoding = po_charset_utf8;
+                remember_a_message_plural (mp, best_cp->msgid_plural,
+                                           msgid_plural_context,
+                                           &best_cp->msgid_plural_pos,
+                                           NULL);
+                xgettext_current_source_encoding = encoding;
+              }
           }
 
           if (best_cp->xcomments.nitems > 0)
@@ -3434,6 +3561,7 @@ language_to_extractor (const char *name)
     flag_context_list_table_ty *flag_table;
     struct formatstring_parser *formatstring_parser1;
     struct formatstring_parser *formatstring_parser2;
+    struct literalstring_parser *literalstring_parser;
   };
   typedef struct table_ty table_ty;
 
@@ -3480,6 +3608,7 @@ language_to_extractor (const char *name)
         result.formatstring_parser1 = tp->formatstring_parser1;
         result.formatstring_parser2 = tp->formatstring_parser2;
         result.formatstring_parser3 = NULL;
+        result.literalstring_parser = tp->literalstring_parser;
 
         /* Handle --qt.  It's preferrable to handle this facility here rather
            than through an option --language=C++/Qt because the latter would
index 059a419d341d84cec3ed8926c0df338e1573d6f4..baba1de27b58a0f1dbf3b45b858268aa5dc83d1d 100644 (file)
@@ -242,6 +242,24 @@ extern refcounted_string_list_ty *savable_comment;
 extern void savable_comment_add (const char *str);
 extern void savable_comment_reset (void);
 
+/* Convert character encoding of COMMENT according to the current
+   source encoding.  Returns a new refcounted_string_list_ty.  */
+extern refcounted_string_list_ty *
+       savable_comment_convert_encoding (refcounted_string_list_ty *comment,
+                                         lex_pos_ty *pos);
+
+
+enum literalstring_escape_type
+{
+  LET_ANSI_C = 1 << 0,
+  LET_UNICODE = 1 << 1
+};
+
+struct literalstring_parser
+{
+  char * (*parse) (const char *string, lex_pos_ty *pos,
+                   enum literalstring_escape_type type);
+};
 
 /* Add a message to the list of extracted messages.
    msgctxt must be either NULL or a malloc()ed string; its ownership is passed
@@ -275,7 +293,6 @@ extern void remember_a_message_plural (message_ty *mp,
                                        lex_pos_ty *pos,
                                        refcounted_string_list_ty *comment);
 
-
 /* Represents the progressive parsing of an argument list w.r.t. a single
    'struct callshape'.  */
 struct partial_call
@@ -288,12 +305,15 @@ struct partial_call
   int argtotal;                 /* total number of arguments, 0 if unspecified */
   string_list_ty xcomments;     /* auto-extracted comments */
   char *msgctxt;                /* context - owned string, or NULL */
+  enum literalstring_escape_type msgctxt_escape;
   lex_pos_ty msgctxt_pos;
   char *msgid;                  /* msgid - owned string, or NULL */
+  enum literalstring_escape_type msgid_escape;
   flag_context_ty msgid_context;
   lex_pos_ty msgid_pos;
   refcounted_string_list_ty *msgid_comment;
   char *msgid_plural;           /* msgid_plural - owned string, or NULL */
+  enum literalstring_escape_type msgid_plural_escape;
   flag_context_ty msgid_plural_context;
   lex_pos_ty msgid_plural_pos;
 };
@@ -326,6 +346,19 @@ extern void arglist_parser_remember (struct arglist_parser *ap,
                                      flag_context_ty context,
                                      char *file_name, size_t line_number,
                                      refcounted_string_list_ty *comment);
+/* Adds an uninterpreted string argument to an arglist_parser.  ARGNUM
+   must be > 0.
+   STRING is must be malloc()ed string; its ownership is passed to the callee.
+   FILE_NAME must be allocated with indefinite extent.
+   COMMENT may be savable_comment, or it may be a saved copy of savable_comment
+   (then add_reference must be used when saving it, and drop_reference while
+   dropping it).  Clear savable_comment.  */
+extern void arglist_parser_remember_literal (struct arglist_parser *ap,
+                                             int argnum, char *string,
+                                             flag_context_ty context,
+                                             char *file_name, size_t line_number,
+                                             refcounted_string_list_ty *comment,
+                                             enum literalstring_escape_type type);
 /* Tests whether an arglist_parser has is not waiting for more arguments after
    argument ARGNUM.  */
 extern bool arglist_parser_decidedp (struct arglist_parser *ap, int argnum);