Home | History | Annotate | Line # | Download | only in src
      1 /* Extracts strings from C source file to Uniforum style .po file.
      2    Copyright (C) 1995-1998, 2000-2006 Free Software Foundation, Inc.
      3    Written by Ulrich Drepper <drepper (at) gnu.ai.mit.edu>, April 1995.
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 2, or (at your option)
      8    any later version.
      9 
     10    This program is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
     18 
     19 #ifdef HAVE_CONFIG_H
     20 # include <config.h>
     21 #endif
     22 #include <alloca.h>
     23 
     24 #include <ctype.h>
     25 #include <errno.h>
     26 #include <getopt.h>
     27 #include <stdio.h>
     28 #include <time.h>
     29 #include <stdlib.h>
     30 #include <stdbool.h>
     31 #include <string.h>
     32 #include <locale.h>
     33 #include <limits.h>
     34 
     35 #include "xgettext.h"
     36 #include "closeout.h"
     37 #include "dir-list.h"
     38 #include "file-list.h"
     39 #include "str-list.h"
     40 #include "error.h"
     41 #include "error-progname.h"
     42 #include "progname.h"
     43 #include "relocatable.h"
     44 #include "basename.h"
     45 #include "xerror.h"
     46 #include "xvasprintf.h"
     47 #include "xalloc.h"
     48 #include "xallocsa.h"
     49 #include "c-strstr.h"
     50 #include "xerror.h"
     51 #include "exit.h"
     52 #include "pathname.h"
     53 #include "c-strcase.h"
     54 #include "open-catalog.h"
     55 #include "read-catalog-abstract.h"
     56 #include "read-po.h"
     57 #include "message.h"
     58 #include "po-charset.h"
     59 #include "msgl-iconv.h"
     60 #include "msgl-ascii.h"
     61 #include "po-time.h"
     62 #include "write-catalog.h"
     63 #include "write-po.h"
     64 #include "write-properties.h"
     65 #include "write-stringtable.h"
     66 #include "format.h"
     67 #include "propername.h"
     68 #include "gettext.h"
     69 
     70 /* A convenience macro.  I don't like writing gettext() every time.  */
     71 #define _(str) gettext (str)
     72 
     73 
     74 #ifdef __cplusplus
     75 extern "C" {
     76 #endif
     77 
     78 #include "x-c.h"
     79 #include "x-po.h"
     80 #include "x-sh.h"
     81 #include "x-python.h"
     82 #include "x-lisp.h"
     83 #include "x-elisp.h"
     84 #include "x-librep.h"
     85 #include "x-scheme.h"
     86 #include "x-smalltalk.h"
     87 #include "x-java.h"
     88 #include "x-properties.h"
     89 #include "x-csharp.h"
     90 #include "x-awk.h"
     91 #include "x-ycp.h"
     92 #include "x-tcl.h"
     93 #include "x-perl.h"
     94 #include "x-php.h"
     95 #include "x-stringtable.h"
     96 #include "x-rst.h"
     97 #include "x-glade.h"
     98 
     99 #ifdef __cplusplus
    100 }
    101 #endif
    102 
    103 
    104 /* If nonzero add all comments immediately preceding one of the keywords. */
    105 static bool add_all_comments = false;
    106 
    107 /* Tag used in comment of prevailing domain.  */
    108 static char *comment_tag;
    109 
    110 /* Name of default domain file.  If not set defaults to messages.po.  */
    111 static const char *default_domain;
    112 
    113 /* If called with --debug option the output reflects whether format
    114    string recognition is done automatically or forced by the user.  */
    115 static int do_debug;
    116 
    117 /* Content of .po files with symbols to be excluded.  */
    118 message_list_ty *exclude;
    119 
    120 /* Force output of PO file even if empty.  */
    121 static int force_po;
    122 
    123 /* Copyright holder of the output file and the translations.  */
    124 static const char *copyright_holder = "THE PACKAGE'S COPYRIGHT HOLDER";
    125 
    126 /* Email address or URL for reports of bugs in msgids.  */
    127 static const char *msgid_bugs_address = NULL;
    128 
    129 /* String used as prefix for msgstr.  */
    130 static const char *msgstr_prefix;
    131 
    132 /* String used as suffix for msgstr.  */
    133 static const char *msgstr_suffix;
    134 
    135 /* Directory in which output files are created.  */
    136 static char *output_dir;
    137 
    138 /* The output syntax: .pot or .properties or .strings.  */
    139 static catalog_output_format_ty output_syntax = &output_format_po;
    140 
    141 /* If nonzero omit header with information about this run.  */
    142 int xgettext_omit_header;
    143 
    144 /* Table of flag_context_list_ty tables.  */
    145 static flag_context_list_table_ty flag_table_c;
    146 static flag_context_list_table_ty flag_table_cxx_qt;
    147 static flag_context_list_table_ty flag_table_cxx_boost;
    148 static flag_context_list_table_ty flag_table_objc;
    149 static flag_context_list_table_ty flag_table_gcc_internal;
    150 static flag_context_list_table_ty flag_table_sh;
    151 static flag_context_list_table_ty flag_table_python;
    152 static flag_context_list_table_ty flag_table_lisp;
    153 static flag_context_list_table_ty flag_table_elisp;
    154 static flag_context_list_table_ty flag_table_librep;
    155 static flag_context_list_table_ty flag_table_scheme;
    156 static flag_context_list_table_ty flag_table_java;
    157 static flag_context_list_table_ty flag_table_csharp;
    158 static flag_context_list_table_ty flag_table_awk;
    159 static flag_context_list_table_ty flag_table_ycp;
    160 static flag_context_list_table_ty flag_table_tcl;
    161 static flag_context_list_table_ty flag_table_perl;
    162 static flag_context_list_table_ty flag_table_php;
    163 
    164 /* If true, recognize Qt format strings.  */
    165 static bool recognize_format_qt;
    166 
    167 /* If true, recognize Boost format strings.  */
    168 static bool recognize_format_boost;
    169 
    170 /* Canonicalized encoding name for all input files.  */
    171 const char *xgettext_global_source_encoding;
    172 
    173 #if HAVE_ICONV
    174 /* Converter from xgettext_global_source_encoding to UTF-8 (except from
    175    ASCII or UTF-8, when this conversion is a no-op).  */
    176 iconv_t xgettext_global_source_iconv;
    177 #endif
    178 
    179 /* Canonicalized encoding name for the current input file.  */
    180 const char *xgettext_current_source_encoding;
    181 
    182 #if HAVE_ICONV
    183 /* Converter from xgettext_current_source_encoding to UTF-8 (except from
    184    ASCII or UTF-8, when this conversion is a no-op).  */
    185 iconv_t xgettext_current_source_iconv;
    186 #endif
    187 
    188 /* Long options.  */
    189 static const struct option long_options[] =
    190 {
    191   { "add-comments", optional_argument, NULL, 'c' },
    192   { "add-location", no_argument, &line_comment, 1 },
    193   { "boost", no_argument, NULL, CHAR_MAX + 10 },
    194   { "c++", no_argument, NULL, 'C' },
    195   { "copyright-holder", required_argument, NULL, CHAR_MAX + 1 },
    196   { "debug", no_argument, &do_debug, 1 },
    197   { "default-domain", required_argument, NULL, 'd' },
    198   { "directory", required_argument, NULL, 'D' },
    199   { "escape", no_argument, NULL, 'E' },
    200   { "exclude-file", required_argument, NULL, 'x' },
    201   { "extract-all", no_argument, NULL, 'a' },
    202   { "files-from", required_argument, NULL, 'f' },
    203   { "flag", required_argument, NULL, CHAR_MAX + 8 },
    204   { "force-po", no_argument, &force_po, 1 },
    205   { "foreign-user", no_argument, NULL, CHAR_MAX + 2 },
    206   { "from-code", required_argument, NULL, CHAR_MAX + 3 },
    207   { "help", no_argument, NULL, 'h' },
    208   { "indent", no_argument, NULL, 'i' },
    209   { "join-existing", no_argument, NULL, 'j' },
    210   { "keyword", optional_argument, NULL, 'k' },
    211   { "language", required_argument, NULL, 'L' },
    212   { "msgid-bugs-address", required_argument, NULL, CHAR_MAX + 5 },
    213   { "msgstr-prefix", optional_argument, NULL, 'm' },
    214   { "msgstr-suffix", optional_argument, NULL, 'M' },
    215   { "no-escape", no_argument, NULL, 'e' },
    216   { "no-location", no_argument, &line_comment, 0 },
    217   { "no-wrap", no_argument, NULL, CHAR_MAX + 4 },
    218   { "omit-header", no_argument, &xgettext_omit_header, 1 },
    219   { "output", required_argument, NULL, 'o' },
    220   { "output-dir", required_argument, NULL, 'p' },
    221   { "properties-output", no_argument, NULL, CHAR_MAX + 6 },
    222   { "qt", no_argument, NULL, CHAR_MAX + 9 },
    223   { "sort-by-file", no_argument, NULL, 'F' },
    224   { "sort-output", no_argument, NULL, 's' },
    225   { "strict", no_argument, NULL, 'S' },
    226   { "string-limit", required_argument, NULL, 'l' },
    227   { "stringtable-output", no_argument, NULL, CHAR_MAX + 7 },
    228   { "trigraphs", no_argument, NULL, 'T' },
    229   { "version", no_argument, NULL, 'V' },
    230   { "width", required_argument, NULL, 'w', },
    231   { NULL, 0, NULL, 0 }
    232 };
    233 
    234 
    235 /* The extractors must all be functions returning void and taking three
    236    arguments designating the input stream and one message domain list argument
    237    in which to add the messages.  */
    238 typedef void (*extractor_func) (FILE *fp, const char *real_filename,
    239 				const char *logical_filename,
    240 				flag_context_list_table_ty *flag_table,
    241 				msgdomain_list_ty *mdlp);
    242 
    243 typedef struct extractor_ty extractor_ty;
    244 struct extractor_ty
    245 {
    246   extractor_func func;
    247   flag_context_list_table_ty *flag_table;
    248   struct formatstring_parser *formatstring_parser1;
    249   struct formatstring_parser *formatstring_parser2;
    250 };
    251 
    252 
    253 /* Forward declaration of local functions.  */
    254 static void usage (int status)
    255 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ > 4) || __GNUC__ > 2)
    256 	__attribute__ ((noreturn))
    257 #endif
    258 ;
    259 static void read_exclusion_file (char *file_name);
    260 static void extract_from_file (const char *file_name, extractor_ty extractor,
    261 			       msgdomain_list_ty *mdlp);
    262 static message_ty *construct_header (void);
    263 static void finalize_header (msgdomain_list_ty *mdlp);
    264 static extractor_ty language_to_extractor (const char *name);
    265 static const char *extension_to_language (const char *extension);
    266 
    267 
    268 int
    269 main (int argc, char *argv[])
    270 {
    271   int optchar;
    272   bool do_help = false;
    273   bool do_version = false;
    274   msgdomain_list_ty *mdlp;
    275   bool join_existing = false;
    276   bool no_default_keywords = false;
    277   bool some_additional_keywords = false;
    278   bool sort_by_msgid = false;
    279   bool sort_by_filepos = false;
    280   const char *file_name;
    281   const char *files_from = NULL;
    282   string_list_ty *file_list;
    283   char *output_file = NULL;
    284   const char *language = NULL;
    285   extractor_ty extractor = { NULL, NULL, NULL, NULL };
    286   int cnt;
    287   size_t i;
    288 
    289   /* Set program name for messages.  */
    290   set_program_name (argv[0]);
    291   error_print_progname = maybe_print_progname;
    292 
    293 #ifdef HAVE_SETLOCALE
    294   /* Set locale via LC_ALL.  */
    295   setlocale (LC_ALL, "");
    296 #endif
    297 
    298   /* Set the text message domain.  */
    299   bindtextdomain (PACKAGE, relocate (LOCALEDIR));
    300   bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
    301   textdomain (PACKAGE);
    302 
    303   /* Ensure that write errors on stdout are detected.  */
    304   atexit (close_stdout);
    305 
    306   /* Set initial value of variables.  */
    307   default_domain = MESSAGE_DOMAIN_DEFAULT;
    308   xgettext_global_source_encoding = po_charset_ascii;
    309   init_flag_table_c ();
    310   init_flag_table_objc ();
    311   init_flag_table_gcc_internal ();
    312   init_flag_table_sh ();
    313   init_flag_table_python ();
    314   init_flag_table_lisp ();
    315   init_flag_table_elisp ();
    316   init_flag_table_librep ();
    317   init_flag_table_scheme ();
    318   init_flag_table_java ();
    319   init_flag_table_csharp ();
    320   init_flag_table_awk ();
    321   init_flag_table_ycp ();
    322   init_flag_table_tcl ();
    323   init_flag_table_perl ();
    324   init_flag_table_php ();
    325 
    326   while ((optchar = getopt_long (argc, argv,
    327 				 "ac::Cd:D:eEf:Fhijk::l:L:m::M::no:p:sTVw:x:",
    328 				 long_options, NULL)) != EOF)
    329     switch (optchar)
    330       {
    331       case '\0':		/* Long option.  */
    332 	break;
    333       case 'a':
    334 	x_c_extract_all ();
    335 	x_sh_extract_all ();
    336 	x_python_extract_all ();
    337 	x_lisp_extract_all ();
    338 	x_elisp_extract_all ();
    339 	x_librep_extract_all ();
    340 	x_scheme_extract_all ();
    341 	x_java_extract_all ();
    342 	x_csharp_extract_all ();
    343 	x_awk_extract_all ();
    344 	x_tcl_extract_all ();
    345 	x_perl_extract_all ();
    346 	x_php_extract_all ();
    347 	x_glade_extract_all ();
    348 	break;
    349       case 'c':
    350 	if (optarg == NULL)
    351 	  {
    352 	    add_all_comments = true;
    353 	    comment_tag = NULL;
    354 	  }
    355 	else
    356 	  {
    357 	    add_all_comments = false;
    358 	    comment_tag = optarg;
    359 	    /* We ignore leading white space.  */
    360 	    while (isspace ((unsigned char) *comment_tag))
    361 	      ++comment_tag;
    362 	  }
    363 	break;
    364       case 'C':
    365 	language = "C++";
    366 	break;
    367       case 'd':
    368 	default_domain = optarg;
    369 	break;
    370       case 'D':
    371 	dir_list_append (optarg);
    372 	break;
    373       case 'e':
    374 	message_print_style_escape (false);
    375 	break;
    376       case 'E':
    377 	message_print_style_escape (true);
    378 	break;
    379       case 'f':
    380 	files_from = optarg;
    381 	break;
    382       case 'F':
    383 	sort_by_filepos = true;
    384 	break;
    385       case 'h':
    386 	do_help = true;
    387 	break;
    388       case 'i':
    389 	message_print_style_indent ();
    390 	break;
    391       case 'j':
    392 	join_existing = true;
    393 	break;
    394       case 'k':
    395 	if (optarg != NULL && *optarg == '\0')
    396 	  /* Make "--keyword=" work like "--keyword" and "-k".  */
    397 	  optarg = NULL;
    398 	x_c_keyword (optarg);
    399 	x_objc_keyword (optarg);
    400 	x_sh_keyword (optarg);
    401 	x_python_keyword (optarg);
    402 	x_lisp_keyword (optarg);
    403 	x_elisp_keyword (optarg);
    404 	x_librep_keyword (optarg);
    405 	x_scheme_keyword (optarg);
    406 	x_java_keyword (optarg);
    407 	x_csharp_keyword (optarg);
    408 	x_awk_keyword (optarg);
    409 	x_tcl_keyword (optarg);
    410 	x_perl_keyword (optarg);
    411 	x_php_keyword (optarg);
    412 	x_glade_keyword (optarg);
    413 	if (optarg == NULL)
    414 	  no_default_keywords = true;
    415 	else
    416 	  some_additional_keywords = true;
    417 	break;
    418       case 'l':
    419 	/* Accepted for backward compatibility with 0.10.35.  */
    420 	break;
    421       case 'L':
    422 	language = optarg;
    423 	break;
    424       case 'm':
    425 	/* -m takes an optional argument.  If none is given "" is assumed. */
    426 	msgstr_prefix = optarg == NULL ? "" : optarg;
    427 	break;
    428       case 'M':
    429 	/* -M takes an optional argument.  If none is given "" is assumed. */
    430 	msgstr_suffix = optarg == NULL ? "" : optarg;
    431 	break;
    432       case 'n':
    433 	line_comment = 1;
    434 	break;
    435       case 'o':
    436 	output_file = optarg;
    437 	break;
    438       case 'p':
    439 	{
    440 	  size_t len = strlen (optarg);
    441 
    442 	  if (output_dir != NULL)
    443 	    free (output_dir);
    444 
    445 	  if (optarg[len - 1] == '/')
    446 	    output_dir = xstrdup (optarg);
    447 	  else
    448 	    output_dir = xasprintf ("%s/", optarg);
    449 	}
    450 	break;
    451       case 's':
    452 	sort_by_msgid = true;
    453 	break;
    454       case 'S':
    455 	message_print_style_uniforum ();
    456 	break;
    457       case 'T':
    458 	x_c_trigraphs ();
    459 	break;
    460       case 'V':
    461 	do_version = true;
    462 	break;
    463       case 'w':
    464 	{
    465 	  int value;
    466 	  char *endp;
    467 	  value = strtol (optarg, &endp, 10);
    468 	  if (endp != optarg)
    469 	    message_page_width_set (value);
    470 	}
    471 	break;
    472       case 'x':
    473 	read_exclusion_file (optarg);
    474 	break;
    475       case CHAR_MAX + 1:	/* --copyright-holder */
    476 	copyright_holder = optarg;
    477 	break;
    478       case CHAR_MAX + 2:	/* --foreign-user */
    479 	copyright_holder = "";
    480 	break;
    481       case CHAR_MAX + 3:	/* --from-code */
    482 	xgettext_global_source_encoding = po_charset_canonicalize (optarg);
    483 	if (xgettext_global_source_encoding == NULL)
    484 	  xgettext_global_source_encoding = po_charset_ascii;
    485 	break;
    486       case CHAR_MAX + 4:	/* --no-wrap */
    487 	message_page_width_ignore ();
    488 	break;
    489       case CHAR_MAX + 5:	/* --msgid-bugs-address */
    490 	msgid_bugs_address = optarg;
    491 	break;
    492       case CHAR_MAX + 6:	/* --properties-output */
    493 	output_syntax = &output_format_properties;
    494 	break;
    495       case CHAR_MAX + 7:	/* --stringtable-output */
    496 	output_syntax = &output_format_stringtable;
    497 	break;
    498       case CHAR_MAX + 8:	/* --flag */
    499 	xgettext_record_flag (optarg);
    500 	break;
    501       case CHAR_MAX + 9:	/* --qt */
    502 	recognize_format_qt = true;
    503 	break;
    504       case CHAR_MAX + 10:	/* --boost */
    505 	recognize_format_boost = true;
    506 	break;
    507       default:
    508 	usage (EXIT_FAILURE);
    509 	/* NOTREACHED */
    510       }
    511 
    512   /* Version information requested.  */
    513   if (do_version)
    514     {
    515       printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
    516       /* xgettext: no-wrap */
    517       printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
    518 This is free software; see the source for copying conditions.  There is NO\n\
    519 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    520 "),
    521 	      "1995-1998, 2000-2006");
    522       printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
    523       exit (EXIT_SUCCESS);
    524     }
    525 
    526   /* Help is requested.  */
    527   if (do_help)
    528     usage (EXIT_SUCCESS);
    529 
    530   /* Verify selected options.  */
    531   if (!line_comment && sort_by_filepos)
    532     error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
    533 	   "--no-location", "--sort-by-file");
    534 
    535   if (sort_by_msgid && sort_by_filepos)
    536     error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
    537 	   "--sort-output", "--sort-by-file");
    538 
    539   if (recognize_format_qt && recognize_format_boost)
    540     /* We cannot support both Qt and Boost format strings, because there are
    541        only two formatstring parsers per language, and formatstring_c is the
    542        first one for C++.  */
    543     error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
    544 	   "--qt", "--boost");
    545 
    546   if (join_existing && strcmp (default_domain, "-") == 0)
    547     error (EXIT_FAILURE, 0, _("\
    548 --join-existing cannot be used when output is written to stdout"));
    549 
    550   if (no_default_keywords && !some_additional_keywords)
    551     {
    552       error (0, 0, _("\
    553 xgettext cannot work without keywords to look for"));
    554       usage (EXIT_FAILURE);
    555     }
    556 
    557   /* Test whether we have some input files given.  */
    558   if (files_from == NULL && optind >= argc)
    559     {
    560       error (EXIT_SUCCESS, 0, _("no input file given"));
    561       usage (EXIT_FAILURE);
    562     }
    563 
    564   /* Determine extractor from language.  */
    565   if (language != NULL)
    566     extractor = language_to_extractor (language);
    567 
    568   /* Canonize msgstr prefix/suffix.  */
    569   if (msgstr_prefix != NULL && msgstr_suffix == NULL)
    570     msgstr_suffix = "";
    571   else if (msgstr_prefix == NULL && msgstr_suffix != NULL)
    572     msgstr_prefix = "";
    573 
    574   /* Default output directory is the current directory.  */
    575   if (output_dir == NULL)
    576     output_dir = ".";
    577 
    578   /* Construct the name of the output file.  If the default domain has
    579      the special name "-" we write to stdout.  */
    580   if (output_file)
    581     {
    582       if (IS_ABSOLUTE_PATH (output_file) || strcmp (output_file, "-") == 0)
    583 	file_name = xstrdup (output_file);
    584       else
    585 	/* Please do NOT add a .po suffix! */
    586 	file_name = concatenated_pathname (output_dir, output_file, NULL);
    587     }
    588   else if (strcmp (default_domain, "-") == 0)
    589     file_name = "-";
    590   else
    591     file_name = concatenated_pathname (output_dir, default_domain, ".po");
    592 
    593   /* Determine list of files we have to process.  */
    594   if (files_from != NULL)
    595     file_list = read_names_from_file (files_from);
    596   else
    597     file_list = string_list_alloc ();
    598   /* Append names from command line.  */
    599   for (cnt = optind; cnt < argc; ++cnt)
    600     string_list_append_unique (file_list, argv[cnt]);
    601 
    602   /* Allocate converter from xgettext_global_source_encoding to UTF-8 (except
    603      from ASCII or UTF-8, when this conversion is a no-op).  */
    604   if (xgettext_global_source_encoding != po_charset_ascii
    605       && xgettext_global_source_encoding != po_charset_utf8)
    606     {
    607 #if HAVE_ICONV
    608       iconv_t cd;
    609 
    610       /* Avoid glibc-2.1 bug with EUC-KR.  */
    611 # if (__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) && !defined _LIBICONV_VERSION
    612       if (strcmp (xgettext_global_source_encoding, "EUC-KR") == 0)
    613 	cd = (iconv_t)(-1);
    614       else
    615 # endif
    616       cd = iconv_open (po_charset_utf8, xgettext_global_source_encoding);
    617       if (cd == (iconv_t)(-1))
    618 	error (EXIT_FAILURE, 0, _("\
    619 Cannot convert from \"%s\" to \"%s\". %s relies on iconv(), \
    620 and iconv() does not support this conversion."),
    621 	       xgettext_global_source_encoding, po_charset_utf8,
    622 	       basename (program_name));
    623       xgettext_global_source_iconv = cd;
    624 #else
    625       error (EXIT_FAILURE, 0, _("\
    626 Cannot convert from \"%s\" to \"%s\". %s relies on iconv(). \
    627 This version was built without iconv()."),
    628 	     xgettext_global_source_encoding, po_charset_utf8,
    629 	     basename (program_name));
    630 #endif
    631     }
    632 
    633   /* Allocate a message list to remember all the messages.  */
    634   mdlp = msgdomain_list_alloc (true);
    635 
    636   /* Generate a header, so that we know how and when this PO file was
    637      created.  */
    638   if (!xgettext_omit_header)
    639     message_list_append (mdlp->item[0]->messages, construct_header ());
    640 
    641   /* Read in the old messages, so that we can add to them.  */
    642   if (join_existing)
    643     {
    644       /* Temporarily reset the directory list to empty, because file_name
    645 	 is an output file and therefore should not be searched for.  */
    646       void *saved_directory_list = dir_list_save_reset ();
    647       extractor_ty po_extractor = { extract_po, NULL, NULL, NULL };
    648 
    649       extract_from_file (file_name, po_extractor, mdlp);
    650       if (!is_ascii_msgdomain_list (mdlp))
    651 	mdlp = iconv_msgdomain_list (mdlp, "UTF-8", file_name);
    652 
    653       dir_list_restore (saved_directory_list);
    654     }
    655 
    656   /* Process all input files.  */
    657   for (i = 0; i < file_list->nitems; i++)
    658     {
    659       const char *filename;
    660       extractor_ty this_file_extractor;
    661 
    662       filename = file_list->item[i];
    663 
    664       if (extractor.func)
    665 	this_file_extractor = extractor;
    666       else
    667 	{
    668 	  const char *base;
    669 	  char *reduced;
    670 	  const char *extension;
    671 	  const char *language;
    672 
    673 	  base = strrchr (filename, '/');
    674 	  if (!base)
    675 	    base = filename;
    676 
    677 	  reduced = xstrdup (base);
    678 	  /* Remove a trailing ".in" - it's a generic suffix.  */
    679 	  if (strlen (reduced) >= 3
    680 	      && memcmp (reduced + strlen (reduced) - 3, ".in", 3) == 0)
    681 	    reduced[strlen (reduced) - 3] = '\0';
    682 
    683 	  /* Work out what the file extension is.  */
    684 	  extension = strrchr (reduced, '.');
    685 	  if (extension)
    686 	    ++extension;
    687 	  else
    688 	    extension = "";
    689 
    690 	  /* Derive the language from the extension, and the extractor
    691 	     function from the language.  */
    692 	  language = extension_to_language (extension);
    693 	  if (language == NULL)
    694 	    {
    695 	      error (0, 0, _("\
    696 warning: file `%s' extension `%s' is unknown; will try C"), filename, extension);
    697 	      language = "C";
    698 	    }
    699 	  this_file_extractor = language_to_extractor (language);
    700 
    701 	  free (reduced);
    702 	}
    703 
    704       /* Extract the strings from the file.  */
    705       extract_from_file (filename, this_file_extractor, mdlp);
    706     }
    707   string_list_free (file_list);
    708 
    709   /* Finalize the constructed header.  */
    710   if (!xgettext_omit_header)
    711     finalize_header (mdlp);
    712 
    713   /* Free the allocated converter.  */
    714 #if HAVE_ICONV
    715   if (xgettext_global_source_encoding != po_charset_ascii
    716       && xgettext_global_source_encoding != po_charset_utf8)
    717     iconv_close (xgettext_global_source_iconv);
    718 #endif
    719 
    720   /* Sorting the list of messages.  */
    721   if (sort_by_filepos)
    722     msgdomain_list_sort_by_filepos (mdlp);
    723   else if (sort_by_msgid)
    724     msgdomain_list_sort_by_msgid (mdlp);
    725 
    726   /* Write the PO file.  */
    727   msgdomain_list_print (mdlp, file_name, output_syntax, force_po, do_debug);
    728 
    729   exit (EXIT_SUCCESS);
    730 }
    731 
    732 
    733 /* Display usage information and exit.  */
    734 static void
    735 usage (int status)
    736 {
    737   if (status != EXIT_SUCCESS)
    738     fprintf (stderr, _("Try `%s --help' for more information.\n"),
    739 	     program_name);
    740   else
    741     {
    742       printf (_("\
    743 Usage: %s [OPTION] [INPUTFILE]...\n\
    744 "), program_name);
    745       printf ("\n");
    746       printf (_("\
    747 Extract translatable strings from given input files.\n\
    748 "));
    749       printf ("\n");
    750       /* xgettext: no-wrap */
    751       printf (_("\
    752 Mandatory arguments to long options are mandatory for short options too.\n\
    753 Similarly for optional arguments.\n\
    754 "));
    755       printf ("\n");
    756       printf (_("\
    757 Input file location:\n"));
    758       printf (_("\
    759   INPUTFILE ...               input files\n"));
    760       printf (_("\
    761   -f, --files-from=FILE       get list of input files from FILE\n"));
    762       printf (_("\
    763   -D, --directory=DIRECTORY   add DIRECTORY to list for input files search\n"));
    764       printf (_("\
    765 If input file is -, standard input is read.\n"));
    766       printf ("\n");
    767       printf (_("\
    768 Output file location:\n"));
    769       printf (_("\
    770   -d, --default-domain=NAME   use NAME.po for output (instead of messages.po)\n"));
    771       printf (_("\
    772   -o, --output=FILE           write output to specified file\n"));
    773       printf (_("\
    774   -p, --output-dir=DIR        output files will be placed in directory DIR\n"));
    775       printf (_("\
    776 If output file is -, output is written to standard output.\n"));
    777       printf ("\n");
    778       printf (_("\
    779 Choice of input file language:\n"));
    780       printf (_("\
    781   -L, --language=NAME         recognise the specified language\n\
    782                                 (C, C++, ObjectiveC, PO, Shell, Python, Lisp,\n\
    783                                 EmacsLisp, librep, Scheme, Smalltalk, Java,\n\
    784                                 JavaProperties, C#, awk, YCP, Tcl, Perl, PHP,\n\
    785                                 GCC-source, NXStringTable, RST, Glade)\n"));
    786       printf (_("\
    787   -C, --c++                   shorthand for --language=C++\n"));
    788       printf (_("\
    789 By default the language is guessed depending on the input file name extension.\n"));
    790       printf ("\n");
    791       printf (_("\
    792 Input file interpretation:\n"));
    793       printf (_("\
    794       --from-code=NAME        encoding of input files\n\
    795                                 (except for Python, Tcl, Glade)\n"));
    796       printf (_("\
    797 By default the input files are assumed to be in ASCII.\n"));
    798       printf ("\n");
    799       printf (_("\
    800 Operation mode:\n"));
    801       printf (_("\
    802   -j, --join-existing         join messages with existing file\n"));
    803       printf (_("\
    804   -x, --exclude-file=FILE.po  entries from FILE.po are not extracted\n"));
    805       printf (_("\
    806   -c, --add-comments[=TAG]    place comment block with TAG (or those\n\
    807                               preceding keyword lines) in output file\n"));
    808       printf ("\n");
    809       printf (_("\
    810 Language specific options:\n"));
    811       printf (_("\
    812   -a, --extract-all           extract all strings\n"));
    813       printf (_("\
    814                                 (only languages C, C++, ObjectiveC, Shell,\n\
    815                                 Python, Lisp, EmacsLisp, librep, Scheme, Java,\n\
    816                                 C#, awk, Tcl, Perl, PHP, GCC-source, Glade)\n"));
    817       printf (_("\
    818   -k, --keyword[=WORD]        additional keyword to be looked for (without\n\
    819                               WORD means not to use default keywords)\n"));
    820       printf (_("\
    821                                 (only languages C, C++, ObjectiveC, Shell,\n\
    822                                 Python, Lisp, EmacsLisp, librep, Scheme, Java,\n\
    823                                 C#, awk, Tcl, Perl, PHP, GCC-source, Glade)\n"));
    824       printf (_("\
    825       --flag=WORD:ARG:FLAG    additional flag for strings inside the argument\n\
    826                               number ARG of keyword WORD\n"));
    827       printf (_("\
    828                                 (only languages C, C++, ObjectiveC, Shell,\n\
    829                                 Python, Lisp, EmacsLisp, librep, Scheme, Java,\n\
    830                                 C#, awk, YCP, Tcl, Perl, PHP, GCC-source)\n"));
    831       printf (_("\
    832   -T, --trigraphs             understand ANSI C trigraphs for input\n"));
    833       printf (_("\
    834                                 (only languages C, C++, ObjectiveC)\n"));
    835       printf (_("\
    836       --qt                    recognize Qt format strings\n"));
    837       printf (_("\
    838                                 (only language C++)\n"));
    839       printf (_("\
    840       --boost                 recognize Boost format strings\n"));
    841       printf (_("\
    842                                 (only language C++)\n"));
    843       printf (_("\
    844       --debug                 more detailed formatstring recognition result\n"));
    845       printf ("\n");
    846       printf (_("\
    847 Output details:\n"));
    848       printf (_("\
    849   -e, --no-escape             do not use C escapes in output (default)\n"));
    850       printf (_("\
    851   -E, --escape                use C escapes in output, no extended chars\n"));
    852       printf (_("\
    853       --force-po              write PO file even if empty\n"));
    854       printf (_("\
    855   -i, --indent                write the .po file using indented style\n"));
    856       printf (_("\
    857       --no-location           do not write '#: filename:line' lines\n"));
    858       printf (_("\
    859   -n, --add-location          generate '#: filename:line' lines (default)\n"));
    860       printf (_("\
    861       --strict                write out strict Uniforum conforming .po file\n"));
    862       printf (_("\
    863       --properties-output     write out a Java .properties file\n"));
    864       printf (_("\
    865       --stringtable-output    write out a NeXTstep/GNUstep .strings file\n"));
    866       printf (_("\
    867   -w, --width=NUMBER          set output page width\n"));
    868       printf (_("\
    869       --no-wrap               do not break long message lines, longer than\n\
    870                               the output page width, into several lines\n"));
    871       printf (_("\
    872   -s, --sort-output           generate sorted output\n"));
    873       printf (_("\
    874   -F, --sort-by-file          sort output by file location\n"));
    875       printf (_("\
    876       --omit-header           don't write header with `msgid \"\"' entry\n"));
    877       printf (_("\
    878       --copyright-holder=STRING  set copyright holder in output\n"));
    879       printf (_("\
    880       --foreign-user          omit FSF copyright in output for foreign user\n"));
    881       printf (_("\
    882       --msgid-bugs-address=EMAIL@ADDRESS  set report address for msgid bugs\n"));
    883       printf (_("\
    884   -m, --msgstr-prefix[=STRING]  use STRING or \"\" as prefix for msgstr entries\n"));
    885       printf (_("\
    886   -M, --msgstr-suffix[=STRING]  use STRING or \"\" as suffix for msgstr entries\n"));
    887       printf ("\n");
    888       printf (_("\
    889 Informative output:\n"));
    890       printf (_("\
    891   -h, --help                  display this help and exit\n"));
    892       printf (_("\
    893   -V, --version               output version information and exit\n"));
    894       printf ("\n");
    895       fputs (_("Report bugs to <bug-gnu-gettext (at) gnu.org>.\n"),
    896 	     stdout);
    897     }
    898 
    899   exit (status);
    900 }
    901 
    902 
    903 static void
    904 exclude_directive_domain (abstract_catalog_reader_ty *pop, char *name)
    905 {
    906   po_gram_error_at_line (&gram_pos,
    907 			 _("this file may not contain domain directives"));
    908 }
    909 
    910 
    911 static void
    912 exclude_directive_message (abstract_catalog_reader_ty *pop,
    913 			   char *msgctxt,
    914 			   char *msgid,
    915 			   lex_pos_ty *msgid_pos,
    916 			   char *msgid_plural,
    917 			   char *msgstr, size_t msgstr_len,
    918 			   lex_pos_ty *msgstr_pos,
    919 			   char *prev_msgctxt,
    920 			   char *prev_msgid,
    921 			   char *prev_msgid_plural,
    922 			   bool force_fuzzy, bool obsolete)
    923 {
    924   message_ty *mp;
    925 
    926   /* See if this message ID has been seen before.  */
    927   if (exclude == NULL)
    928     exclude = message_list_alloc (true);
    929   mp = message_list_search (exclude, msgctxt, msgid);
    930   if (mp != NULL)
    931     free (msgid);
    932   else
    933     {
    934       mp = message_alloc (msgctxt, msgid, msgid_plural, "", 1, msgstr_pos);
    935       /* Do not free msgid.  */
    936       message_list_append (exclude, mp);
    937     }
    938 
    939   /* All we care about is the msgid.  Throw the msgstr away.
    940      Don't even check for duplicate msgids.  */
    941   free (msgstr);
    942 }
    943 
    944 
    945 /* So that the one parser can be used for multiple programs, and also
    946    use good data hiding and encapsulation practices, an object
    947    oriented approach has been taken.  An object instance is allocated,
    948    and all actions resulting from the parse will be through
    949    invocations of method functions of that object.  */
    950 
    951 static abstract_catalog_reader_class_ty exclude_methods =
    952 {
    953   sizeof (abstract_catalog_reader_ty),
    954   NULL, /* constructor */
    955   NULL, /* destructor */
    956   NULL, /* parse_brief */
    957   NULL, /* parse_debrief */
    958   exclude_directive_domain,
    959   exclude_directive_message,
    960   NULL, /* comment */
    961   NULL, /* comment_dot */
    962   NULL, /* comment_filepos */
    963   NULL, /* comment_special */
    964 };
    965 
    966 
    967 static void
    968 read_exclusion_file (char *filename)
    969 {
    970   char *real_filename;
    971   FILE *fp = open_catalog_file (filename, &real_filename, true);
    972   abstract_catalog_reader_ty *pop;
    973 
    974   pop = catalog_reader_alloc (&exclude_methods);
    975   catalog_reader_parse (pop, fp, real_filename, filename, &input_format_po);
    976   catalog_reader_free (pop);
    977 
    978   if (fp != stdin)
    979     fclose (fp);
    980 }
    981 
    982 
    983 void
    984 split_keywordspec (const char *spec,
    985 		   const char **endp, struct callshape *shapep)
    986 {
    987   const char *p;
    988   int argnum1 = 0;
    989   int argnum2 = 0;
    990   int argnumc = 0;
    991   bool argnum1_glib_context = false;
    992   bool argnum2_glib_context = false;
    993   int argtotal = 0;
    994   string_list_ty xcomments;
    995 
    996   string_list_init (&xcomments);
    997 
    998   /* Start parsing from the end.  */
    999   p = spec + strlen (spec);
   1000   while (p > spec)
   1001     {
   1002       if (isdigit ((unsigned char) p[-1])
   1003 	  || ((p[-1] == 'c' || p[-1] == 'g' || p[-1] == 't')
   1004 	      && p - 1 > spec && isdigit ((unsigned char) p[-2])))
   1005 	{
   1006 	  bool contextp = (p[-1] == 'c');
   1007 	  bool glibp = (p[-1] == 'g');
   1008 	  bool totalp = (p[-1] == 't');
   1009 
   1010 	  do
   1011 	    p--;
   1012 	  while (p > spec && isdigit ((unsigned char) p[-1]));
   1013 
   1014 	  if (p > spec && (p[-1] == ',' || p[-1] == ':'))
   1015 	    {
   1016 	      char *dummy;
   1017 	      int arg = strtol (p, &dummy, 10);
   1018 
   1019 	      if (contextp)
   1020 		{
   1021 		  if (argnumc != 0)
   1022 		    /* Only one context argument can be given.  */
   1023 		    break;
   1024 		  argnumc = arg;
   1025 		}
   1026 	      else if (totalp)
   1027 		{
   1028 		  if (argtotal != 0)
   1029 		    /* Only one total number of arguments can be given.  */
   1030 		    break;
   1031 		  argtotal = arg;
   1032 		}
   1033 	      else
   1034 		{
   1035 		  if (argnum2 != 0)
   1036 		    /* At most two normal arguments can be given.  */
   1037 		    break;
   1038 		  argnum2 = argnum1;
   1039 		  argnum2_glib_context = argnum1_glib_context;
   1040 		  argnum1 = arg;
   1041 		  argnum1_glib_context = glibp;
   1042 		}
   1043 	    }
   1044 	  else
   1045 	    break;
   1046 	}
   1047       else if (p[-1] == '"')
   1048 	{
   1049 	  const char *xcomment_end;
   1050 
   1051 	  p--;
   1052 	  xcomment_end = p;
   1053 
   1054 	  while (p > spec && p[-1] != '"')
   1055 	    p--;
   1056 
   1057 	  if (p > spec /* && p[-1] == '"' */)
   1058 	    {
   1059 	      const char *xcomment_start;
   1060 
   1061 	      xcomment_start = p;
   1062 	      p--;
   1063 	      if (p > spec && (p[-1] == ',' || p[-1] == ':'))
   1064 		{
   1065 		  size_t xcomment_len = xcomment_end - xcomment_start;
   1066 		  char *xcomment = (char *) xmalloc (xcomment_len + 1);
   1067 
   1068 		  memcpy (xcomment, xcomment_start, xcomment_len);
   1069 		  xcomment[xcomment_len] = '\0';
   1070 		  string_list_append (&xcomments, xcomment);
   1071 		}
   1072 	      else
   1073 		break;
   1074 	    }
   1075 	  else
   1076 	    break;
   1077 	}
   1078       else
   1079 	break;
   1080 
   1081       /* Here an element of the comma-separated list has been parsed.  */
   1082       if (!(p > spec && (p[-1] == ',' || p[-1] == ':')))
   1083 	abort ();
   1084       p--;
   1085       if (*p == ':')
   1086 	{
   1087 	  size_t i;
   1088 
   1089 	  if (argnum1 == 0 && argnum2 == 0)
   1090 	    /* At least one non-context argument must be given.  */
   1091 	    break;
   1092 	  if (argnumc != 0
   1093 	      && (argnum1_glib_context || argnum2_glib_context))
   1094 	    /* Incompatible ways to specify the context.  */
   1095 	    break;
   1096 	  *endp = p;
   1097 	  shapep->argnum1 = (argnum1 > 0 ? argnum1 : 1);
   1098 	  shapep->argnum2 = argnum2;
   1099 	  shapep->argnumc = argnumc;
   1100 	  shapep->argnum1_glib_context = argnum1_glib_context;
   1101 	  shapep->argnum2_glib_context = argnum2_glib_context;
   1102 	  shapep->argtotal = argtotal;
   1103 	  /* Reverse the order of the xcomments.  */
   1104 	  string_list_init (&shapep->xcomments);
   1105 	  for (i = xcomments.nitems; i > 0; )
   1106 	    string_list_append (&shapep->xcomments, xcomments.item[--i]);
   1107 	  string_list_destroy (&xcomments);
   1108 	  return;
   1109 	}
   1110     }
   1111 
   1112   /* Couldn't parse the desired syntax.  */
   1113   *endp = spec + strlen (spec);
   1114   shapep->argnum1 = 1;
   1115   shapep->argnum2 = 0;
   1116   shapep->argnumc = 0;
   1117   shapep->argnum1_glib_context = false;
   1118   shapep->argnum2_glib_context = false;
   1119   shapep->argtotal = 0;
   1120   string_list_init (&shapep->xcomments);
   1121   string_list_destroy (&xcomments);
   1122 }
   1123 
   1124 
   1125 void
   1126 insert_keyword_callshape (hash_table *table,
   1127 			  const char *keyword, size_t keyword_len,
   1128 			  const struct callshape *shape)
   1129 {
   1130   void *old_value;
   1131 
   1132   if (hash_find_entry (table, keyword, keyword_len, &old_value))
   1133     {
   1134       /* Create a one-element 'struct callshapes'.  */
   1135       struct callshapes *shapes =
   1136 	(struct callshapes *) xmalloc (sizeof (struct callshapes));
   1137       shapes->nshapes = 1;
   1138       shapes->shapes[0] = *shape;
   1139       keyword =
   1140 	(const char *) hash_insert_entry (table, keyword, keyword_len, shapes);
   1141       if (keyword == NULL)
   1142 	abort ();
   1143       shapes->keyword = keyword;
   1144       shapes->keyword_len = keyword_len;
   1145     }
   1146   else
   1147     {
   1148       /* Found a 'struct callshapes'.  See whether it already contains the
   1149 	 desired shape.  */
   1150       struct callshapes *old_shapes = (struct callshapes *) old_value;
   1151       bool found;
   1152       size_t i;
   1153 
   1154       found = false;
   1155       for (i = 0; i < old_shapes->nshapes; i++)
   1156 	if (old_shapes->shapes[i].argnum1 == shape->argnum1
   1157 	    && old_shapes->shapes[i].argnum2 == shape->argnum2
   1158 	    && old_shapes->shapes[i].argnumc == shape->argnumc
   1159 	    && old_shapes->shapes[i].argnum1_glib_context
   1160 	       == shape->argnum1_glib_context
   1161 	    && old_shapes->shapes[i].argnum2_glib_context
   1162 	       == shape->argnum2_glib_context
   1163 	    && old_shapes->shapes[i].argtotal == shape->argtotal)
   1164 	  {
   1165 	    old_shapes->shapes[i].xcomments = shape->xcomments;
   1166 	    found = true;
   1167 	    break;
   1168 	  }
   1169 
   1170       if (!found)
   1171 	{
   1172 	  /* Replace the existing 'struct callshapes' with a new one.  */
   1173 	  struct callshapes *shapes =
   1174 	    (struct callshapes *)
   1175 	    xmalloc (sizeof (struct callshapes)
   1176 		     + old_shapes->nshapes * sizeof (struct callshape));
   1177 
   1178 	  shapes->keyword = old_shapes->keyword;
   1179 	  shapes->keyword_len = old_shapes->keyword_len;
   1180 	  shapes->nshapes = old_shapes->nshapes + 1;
   1181 	  for (i = 0; i < old_shapes->nshapes; i++)
   1182 	    shapes->shapes[i] = old_shapes->shapes[i];
   1183 	  shapes->shapes[i] = *shape;
   1184 	  if (hash_set_value (table, keyword, keyword_len, shapes))
   1185 	    abort ();
   1186 	  free (old_shapes);
   1187 	}
   1188     }
   1189 }
   1190 
   1191 
   1192 /* Null context.  */
   1193 flag_context_ty null_context = { undecided, false, undecided, false };
   1194 
   1195 /* Transparent context.  */
   1196 flag_context_ty passthrough_context = { undecided, true, undecided, true };
   1197 
   1198 
   1199 flag_context_ty
   1200 inherited_context (flag_context_ty outer_context,
   1201 		   flag_context_ty modifier_context)
   1202 {
   1203   flag_context_ty result = modifier_context;
   1204 
   1205   if (result.pass_format1)
   1206     {
   1207       result.is_format1 = outer_context.is_format1;
   1208       result.pass_format1 = false;
   1209     }
   1210   if (result.pass_format2)
   1211     {
   1212       result.is_format2 = outer_context.is_format2;
   1213       result.pass_format2 = false;
   1214     }
   1215   return result;
   1216 }
   1217 
   1218 
   1219 /* Null context list iterator.  */
   1220 flag_context_list_iterator_ty null_context_list_iterator = { 1, NULL };
   1221 
   1222 /* Transparent context list iterator.  */
   1223 static flag_context_list_ty passthrough_context_circular_list =
   1224   {
   1225     1,
   1226     { undecided, true, undecided, true },
   1227     &passthrough_context_circular_list
   1228   };
   1229 flag_context_list_iterator_ty passthrough_context_list_iterator =
   1230   {
   1231     1,
   1232     &passthrough_context_circular_list
   1233   };
   1234 
   1235 
   1236 flag_context_list_iterator_ty
   1237 flag_context_list_iterator (flag_context_list_ty *list)
   1238 {
   1239   flag_context_list_iterator_ty result;
   1240 
   1241   result.argnum = 1;
   1242   result.head = list;
   1243   return result;
   1244 }
   1245 
   1246 
   1247 flag_context_ty
   1248 flag_context_list_iterator_advance (flag_context_list_iterator_ty *iter)
   1249 {
   1250   if (iter->head == NULL)
   1251     return null_context;
   1252   if (iter->argnum == iter->head->argnum)
   1253     {
   1254       flag_context_ty result = iter->head->flags;
   1255 
   1256       /* Special casing of circular list.  */
   1257       if (iter->head != iter->head->next)
   1258 	{
   1259 	  iter->head = iter->head->next;
   1260 	  iter->argnum++;
   1261 	}
   1262 
   1263       return result;
   1264     }
   1265   else
   1266     {
   1267       iter->argnum++;
   1268       return null_context;
   1269     }
   1270 }
   1271 
   1272 
   1273 flag_context_list_ty *
   1274 flag_context_list_table_lookup (flag_context_list_table_ty *flag_table,
   1275 				const void *key, size_t keylen)
   1276 {
   1277   void *entry;
   1278 
   1279   if (flag_table->table != NULL
   1280       && hash_find_entry (flag_table, key, keylen, &entry) == 0)
   1281     return (flag_context_list_ty *) entry;
   1282   else
   1283     return NULL;
   1284 }
   1285 
   1286 
   1287 static void
   1288 flag_context_list_table_insert (flag_context_list_table_ty *table,
   1289 				unsigned int index,
   1290 				const char *name_start, const char *name_end,
   1291 				int argnum, enum is_format value, bool pass)
   1292 {
   1293   char *allocated_name = NULL;
   1294 
   1295   if (table == &flag_table_lisp)
   1296     {
   1297       /* Convert NAME to upper case.  */
   1298       size_t name_len = name_end - name_start;
   1299       char *name = allocated_name = (char *) xallocsa (name_len);
   1300       size_t i;
   1301 
   1302       for (i = 0; i < name_len; i++)
   1303 	name[i] = (name_start[i] >= 'a' && name_start[i] <= 'z'
   1304 		   ? name_start[i] - 'a' + 'A'
   1305 		   : name_start[i]);
   1306       name_start = name;
   1307       name_end = name + name_len;
   1308     }
   1309   else if (table == &flag_table_tcl)
   1310     {
   1311       /* Remove redundant "::" prefix.  */
   1312       if (name_end - name_start > 2
   1313 	  && name_start[0] == ':' && name_start[1] == ':')
   1314 	name_start += 2;
   1315     }
   1316 
   1317   /* Insert the pair (VALUE, PASS) at INDEX in the element numbered ARGNUM
   1318      of the list corresponding to NAME in the TABLE.  */
   1319   if (table->table == NULL)
   1320     hash_init (table, 100);
   1321   {
   1322     void *entry;
   1323 
   1324     if (hash_find_entry (table, name_start, name_end - name_start, &entry) != 0)
   1325       {
   1326 	/* Create new hash table entry.  */
   1327 	flag_context_list_ty *list =
   1328 	  (flag_context_list_ty *) xmalloc (sizeof (flag_context_list_ty));
   1329 	list->argnum = argnum;
   1330 	memset (&list->flags, '\0', sizeof (list->flags));
   1331 	switch (index)
   1332 	  {
   1333 	  case 0:
   1334 	    list->flags.is_format1 = value;
   1335 	    list->flags.pass_format1 = pass;
   1336 	    break;
   1337 	  case 1:
   1338 	    list->flags.is_format2 = value;
   1339 	    list->flags.pass_format2 = pass;
   1340 	    break;
   1341 	  default:
   1342 	    abort ();
   1343 	  }
   1344 	list->next = NULL;
   1345 	hash_insert_entry (table, name_start, name_end - name_start, list);
   1346       }
   1347     else
   1348       {
   1349 	flag_context_list_ty *list = (flag_context_list_ty *)entry;
   1350 	flag_context_list_ty **lastp = NULL;
   1351 
   1352 	while (list != NULL && list->argnum < argnum)
   1353 	  {
   1354 	    lastp = &list->next;
   1355 	    list = *lastp;
   1356 	  }
   1357 	if (list != NULL && list->argnum == argnum)
   1358 	  {
   1359 	    /* Add this flag to the current argument number.  */
   1360 	    switch (index)
   1361 	      {
   1362 	      case 0:
   1363 		list->flags.is_format1 = value;
   1364 		list->flags.pass_format1 = pass;
   1365 		break;
   1366 	      case 1:
   1367 		list->flags.is_format2 = value;
   1368 		list->flags.pass_format2 = pass;
   1369 		break;
   1370 	      default:
   1371 		abort ();
   1372 	      }
   1373 	  }
   1374 	else if (lastp != NULL)
   1375 	  {
   1376 	    /* Add a new list entry for this argument number.  */
   1377 	    list =
   1378 	      (flag_context_list_ty *) xmalloc (sizeof (flag_context_list_ty));
   1379 	    list->argnum = argnum;
   1380 	    memset (&list->flags, '\0', sizeof (list->flags));
   1381 	    switch (index)
   1382 	      {
   1383 	      case 0:
   1384 		list->flags.is_format1 = value;
   1385 		list->flags.pass_format1 = pass;
   1386 		break;
   1387 	      case 1:
   1388 		list->flags.is_format2 = value;
   1389 		list->flags.pass_format2 = pass;
   1390 		break;
   1391 	      default:
   1392 		abort ();
   1393 	      }
   1394 	    list->next = *lastp;
   1395 	    *lastp = list;
   1396 	  }
   1397 	else
   1398 	  {
   1399 	    /* Add a new list entry for this argument number, at the beginning
   1400 	       of the list.  Since we don't have an API for replacing the
   1401 	       value of a key in the hash table, we have to copy the first
   1402 	       list element.  */
   1403 	    flag_context_list_ty *copy =
   1404 	      (flag_context_list_ty *) xmalloc (sizeof (flag_context_list_ty));
   1405 	    *copy = *list;
   1406 
   1407 	    list->argnum = argnum;
   1408 	    memset (&list->flags, '\0', sizeof (list->flags));
   1409 	    switch (index)
   1410 	      {
   1411 	      case 0:
   1412 		list->flags.is_format1 = value;
   1413 		list->flags.pass_format1 = pass;
   1414 		break;
   1415 	      case 1:
   1416 		list->flags.is_format2 = value;
   1417 		list->flags.pass_format2 = pass;
   1418 		break;
   1419 	      default:
   1420 		abort ();
   1421 	      }
   1422 	    list->next = copy;
   1423 	  }
   1424       }
   1425   }
   1426 
   1427   if (allocated_name != NULL)
   1428     freesa (allocated_name);
   1429 }
   1430 
   1431 
   1432 void
   1433 xgettext_record_flag (const char *optionstring)
   1434 {
   1435   /* Check the string has at least two colons.  (Colons in the name are
   1436      allowed, needed for the Lisp and the Tcl backends.)  */
   1437   const char *colon1;
   1438   const char *colon2;
   1439 
   1440   for (colon2 = optionstring + strlen (optionstring); ; )
   1441     {
   1442       if (colon2 == optionstring)
   1443 	goto err;
   1444       colon2--;
   1445       if (*colon2 == ':')
   1446 	break;
   1447     }
   1448   for (colon1 = colon2; ; )
   1449     {
   1450       if (colon1 == optionstring)
   1451 	goto err;
   1452       colon1--;
   1453       if (*colon1 == ':')
   1454 	break;
   1455     }
   1456   {
   1457     const char *name_start = optionstring;
   1458     const char *name_end = colon1;
   1459     const char *argnum_start = colon1 + 1;
   1460     const char *argnum_end = colon2;
   1461     const char *flag = colon2 + 1;
   1462     int argnum;
   1463 
   1464     /* Check the parts' syntax.  */
   1465     if (name_end == name_start)
   1466       goto err;
   1467     if (argnum_end == argnum_start)
   1468       goto err;
   1469     {
   1470       char *endp;
   1471       argnum = strtol (argnum_start, &endp, 10);
   1472       if (endp != argnum_end)
   1473 	goto err;
   1474     }
   1475     if (argnum <= 0)
   1476       goto err;
   1477 
   1478     /* Analyze the flag part.  */
   1479     {
   1480       bool pass;
   1481 
   1482       pass = false;
   1483       if (strlen (flag) >= 5 && memcmp (flag, "pass-", 5) == 0)
   1484 	{
   1485 	  pass = true;
   1486 	  flag += 5;
   1487 	}
   1488 
   1489       /* Unlike po_parse_comment_special(), we don't accept "fuzzy" or "wrap"
   1490 	 here - it has no sense.  */
   1491       if (strlen (flag) >= 7
   1492 	  && memcmp (flag + strlen (flag) - 7, "-format", 7) == 0)
   1493 	{
   1494 	  const char *p;
   1495 	  size_t n;
   1496 	  enum is_format value;
   1497 	  size_t type;
   1498 
   1499 	  p = flag;
   1500 	  n = strlen (flag) - 7;
   1501 
   1502 	  if (n >= 3 && memcmp (p, "no-", 3) == 0)
   1503 	    {
   1504 	      p += 3;
   1505 	      n -= 3;
   1506 	      value = no;
   1507 	    }
   1508 	  else if (n >= 9 && memcmp (p, "possible-", 9) == 0)
   1509 	    {
   1510 	      p += 9;
   1511 	      n -= 9;
   1512 	      value = possible;
   1513 	    }
   1514 	  else if (n >= 11 && memcmp (p, "impossible-", 11) == 0)
   1515 	    {
   1516 	      p += 11;
   1517 	      n -= 11;
   1518 	      value = impossible;
   1519 	    }
   1520 	  else
   1521 	    value = yes_according_to_context;
   1522 
   1523 	  for (type = 0; type < NFORMATS; type++)
   1524 	    if (strlen (format_language[type]) == n
   1525 		&& memcmp (format_language[type], p, n) == 0)
   1526 	      {
   1527 		switch (type)
   1528 		  {
   1529 		  case format_c:
   1530 		    flag_context_list_table_insert (&flag_table_c, 0,
   1531 						    name_start, name_end,
   1532 						    argnum, value, pass);
   1533 		    flag_context_list_table_insert (&flag_table_cxx_qt, 0,
   1534 						    name_start, name_end,
   1535 						    argnum, value, pass);
   1536 		    flag_context_list_table_insert (&flag_table_cxx_boost, 0,
   1537 						    name_start, name_end,
   1538 						    argnum, value, pass);
   1539 		    flag_context_list_table_insert (&flag_table_objc, 0,
   1540 						    name_start, name_end,
   1541 						    argnum, value, pass);
   1542 		    break;
   1543 		  case format_objc:
   1544 		    flag_context_list_table_insert (&flag_table_objc, 1,
   1545 						    name_start, name_end,
   1546 						    argnum, value, pass);
   1547 		    break;
   1548 		  case format_sh:
   1549 		    flag_context_list_table_insert (&flag_table_sh, 0,
   1550 						    name_start, name_end,
   1551 						    argnum, value, pass);
   1552 		    break;
   1553 		  case format_python:
   1554 		    flag_context_list_table_insert (&flag_table_python, 0,
   1555 						    name_start, name_end,
   1556 						    argnum, value, pass);
   1557 		    break;
   1558 		  case format_lisp:
   1559 		    flag_context_list_table_insert (&flag_table_lisp, 0,
   1560 						    name_start, name_end,
   1561 						    argnum, value, pass);
   1562 		    break;
   1563 		  case format_elisp:
   1564 		    flag_context_list_table_insert (&flag_table_elisp, 0,
   1565 						    name_start, name_end,
   1566 						    argnum, value, pass);
   1567 		    break;
   1568 		  case format_librep:
   1569 		    flag_context_list_table_insert (&flag_table_librep, 0,
   1570 						    name_start, name_end,
   1571 						    argnum, value, pass);
   1572 		    break;
   1573 		  case format_scheme:
   1574 		    flag_context_list_table_insert (&flag_table_scheme, 0,
   1575 						    name_start, name_end,
   1576 						    argnum, value, pass);
   1577 		    break;
   1578 		  case format_smalltalk:
   1579 		    break;
   1580 		  case format_java:
   1581 		    flag_context_list_table_insert (&flag_table_java, 0,
   1582 						    name_start, name_end,
   1583 						    argnum, value, pass);
   1584 		    break;
   1585 		  case format_csharp:
   1586 		    flag_context_list_table_insert (&flag_table_csharp, 0,
   1587 						    name_start, name_end,
   1588 						    argnum, value, pass);
   1589 		    break;
   1590 		  case format_awk:
   1591 		    flag_context_list_table_insert (&flag_table_awk, 0,
   1592 						    name_start, name_end,
   1593 						    argnum, value, pass);
   1594 		    break;
   1595 		  case format_pascal:
   1596 		    break;
   1597 		  case format_ycp:
   1598 		    flag_context_list_table_insert (&flag_table_ycp, 0,
   1599 						    name_start, name_end,
   1600 						    argnum, value, pass);
   1601 		    break;
   1602 		  case format_tcl:
   1603 		    flag_context_list_table_insert (&flag_table_tcl, 0,
   1604 						    name_start, name_end,
   1605 						    argnum, value, pass);
   1606 		    break;
   1607 		  case format_perl:
   1608 		    flag_context_list_table_insert (&flag_table_perl, 0,
   1609 						    name_start, name_end,
   1610 						    argnum, value, pass);
   1611 		    break;
   1612 		  case format_perl_brace:
   1613 		    flag_context_list_table_insert (&flag_table_perl, 1,
   1614 						    name_start, name_end,
   1615 						    argnum, value, pass);
   1616 		    break;
   1617 		  case format_php:
   1618 		    flag_context_list_table_insert (&flag_table_php, 0,
   1619 						    name_start, name_end,
   1620 						    argnum, value, pass);
   1621 		    break;
   1622 		  case format_gcc_internal:
   1623 		    flag_context_list_table_insert (&flag_table_gcc_internal, 0,
   1624 						    name_start, name_end,
   1625 						    argnum, value, pass);
   1626 		    break;
   1627 		  case format_qt:
   1628 		    flag_context_list_table_insert (&flag_table_cxx_qt, 1,
   1629 						    name_start, name_end,
   1630 						    argnum, value, pass);
   1631 		    break;
   1632 		  case format_boost:
   1633 		    flag_context_list_table_insert (&flag_table_cxx_boost, 1,
   1634 						    name_start, name_end,
   1635 						    argnum, value, pass);
   1636 		    break;
   1637 		  default:
   1638 		    abort ();
   1639 		  }
   1640 		return;
   1641 	      }
   1642 	  /* If the flag is not among the valid values, the optionstring is
   1643 	     invalid.  */
   1644 	}
   1645     }
   1646   }
   1647 
   1648 err:
   1649   error (EXIT_FAILURE, 0, _("\
   1650 A --flag argument doesn't have the <keyword>:<argnum>:[pass-]<flag> syntax: %s"),
   1651 	 optionstring);
   1652 }
   1653 
   1654 
   1655 /* Comment handling: There is a list of automatic comments that may be appended
   1656    to the next message.  Used by remember_a_message().  */
   1657 
   1658 static string_list_ty *comment;
   1659 
   1660 static void
   1661 xgettext_comment_add (const char *str)
   1662 {
   1663   if (comment == NULL)
   1664     comment = string_list_alloc ();
   1665   string_list_append (comment, str);
   1666 }
   1667 
   1668 static const char *
   1669 xgettext_comment (size_t n)
   1670 {
   1671   if (comment == NULL || n >= comment->nitems)
   1672     return NULL;
   1673   return comment->item[n];
   1674 }
   1675 
   1676 static void
   1677 xgettext_comment_reset ()
   1678 {
   1679   if (comment != NULL)
   1680     {
   1681       string_list_free (comment);
   1682       comment = NULL;
   1683     }
   1684 }
   1685 
   1686 
   1687 refcounted_string_list_ty *savable_comment;
   1688 
   1689 void
   1690 savable_comment_add (const char *str)
   1691 {
   1692   if (savable_comment == NULL)
   1693     {
   1694       savable_comment =
   1695 	(refcounted_string_list_ty *) xmalloc (sizeof (*savable_comment));
   1696       savable_comment->refcount = 1;
   1697       string_list_init (&savable_comment->contents);
   1698     }
   1699   else if (savable_comment->refcount > 1)
   1700     {
   1701       /* Unshare the list by making copies.  */
   1702       struct string_list_ty *oldcontents;
   1703       size_t i;
   1704 
   1705       savable_comment->refcount--;
   1706       oldcontents = &savable_comment->contents;
   1707 
   1708       savable_comment =
   1709 	(refcounted_string_list_ty *) xmalloc (sizeof (*savable_comment));
   1710       savable_comment->refcount = 1;
   1711       string_list_init (&savable_comment->contents);
   1712       for (i = 0; i < oldcontents->nitems; i++)
   1713 	string_list_append (&savable_comment->contents, oldcontents->item[i]);
   1714     }
   1715   string_list_append (&savable_comment->contents, str);
   1716 }
   1717 
   1718 void
   1719 savable_comment_reset ()
   1720 {
   1721   drop_reference (savable_comment);
   1722   savable_comment = NULL;
   1723 }
   1724 
   1725 static void
   1726 savable_comment_to_xgettext_comment (refcounted_string_list_ty *rslp)
   1727 {
   1728   xgettext_comment_reset ();
   1729   if (rslp != NULL)
   1730     {
   1731       size_t i;
   1732 
   1733       for (i = 0; i < rslp->contents.nitems; i++)
   1734 	xgettext_comment_add (rslp->contents.item[i]);
   1735     }
   1736 }
   1737 
   1738 
   1739 
   1740 static FILE *
   1741 xgettext_open (const char *fn,
   1742 	       char **logical_file_name_p, char **real_file_name_p)
   1743 {
   1744   FILE *fp;
   1745   char *new_name;
   1746   char *logical_file_name;
   1747 
   1748   if (strcmp (fn, "-") == 0)
   1749     {
   1750       new_name = xstrdup (_("standard input"));
   1751       logical_file_name = xstrdup (new_name);
   1752       fp = stdin;
   1753     }
   1754   else if (IS_ABSOLUTE_PATH (fn))
   1755     {
   1756       new_name = xstrdup (fn);
   1757       fp = fopen (fn, "r");
   1758       if (fp == NULL)
   1759 	error (EXIT_FAILURE, errno, _("\
   1760 error while opening \"%s\" for reading"), fn);
   1761       logical_file_name = xstrdup (new_name);
   1762     }
   1763   else
   1764     {
   1765       int j;
   1766 
   1767       for (j = 0; ; ++j)
   1768 	{
   1769 	  const char *dir = dir_list_nth (j);
   1770 
   1771 	  if (dir == NULL)
   1772 	    error (EXIT_FAILURE, ENOENT, _("\
   1773 error while opening \"%s\" for reading"), fn);
   1774 
   1775 	  new_name = concatenated_pathname (dir, fn, NULL);
   1776 
   1777 	  fp = fopen (new_name, "r");
   1778 	  if (fp != NULL)
   1779 	    break;
   1780 
   1781 	  if (errno != ENOENT)
   1782 	    error (EXIT_FAILURE, errno, _("\
   1783 error while opening \"%s\" for reading"), new_name);
   1784 	  free (new_name);
   1785 	}
   1786 
   1787       /* Note that the NEW_NAME variable contains the actual file name
   1788 	 and the logical file name is what is reported by xgettext.  In
   1789 	 this case NEW_NAME is set to the file which was found along the
   1790 	 directory search path, and LOGICAL_FILE_NAME is is set to the
   1791 	 file name which was searched for.  */
   1792       logical_file_name = xstrdup (fn);
   1793     }
   1794 
   1795   *logical_file_name_p = logical_file_name;
   1796   *real_file_name_p = new_name;
   1797   return fp;
   1798 }
   1799 
   1800 
   1801 /* Language dependent format string parser.
   1802    NULL if the language has no notion of format strings.  */
   1803 static struct formatstring_parser *current_formatstring_parser1;
   1804 static struct formatstring_parser *current_formatstring_parser2;
   1805 
   1806 
   1807 static void
   1808 extract_from_file (const char *file_name, extractor_ty extractor,
   1809 		   msgdomain_list_ty *mdlp)
   1810 {
   1811   char *logical_file_name;
   1812   char *real_file_name;
   1813   FILE *fp = xgettext_open (file_name, &logical_file_name, &real_file_name);
   1814 
   1815   /* Set the default for the source file encoding.  May be overridden by
   1816      the extractor function.  */
   1817   xgettext_current_source_encoding = xgettext_global_source_encoding;
   1818 #if HAVE_ICONV
   1819   xgettext_current_source_iconv = xgettext_global_source_iconv;
   1820 #endif
   1821 
   1822   current_formatstring_parser1 = extractor.formatstring_parser1;
   1823   current_formatstring_parser2 = extractor.formatstring_parser2;
   1824   extractor.func (fp, real_file_name, logical_file_name, extractor.flag_table,
   1825 		  mdlp);
   1826 
   1827   if (fp != stdin)
   1828     fclose (fp);
   1829   free (logical_file_name);
   1830   free (real_file_name);
   1831 }
   1832 
   1833 
   1834 
   1835 /* Convert the given string from xgettext_current_source_encoding to
   1836    the output file encoding (i.e. ASCII or UTF-8).
   1837    The resulting string is either the argument string, or freshly allocated.
   1838    The file_name and line_number are only used for error message purposes.  */
   1839 char *
   1840 from_current_source_encoding (const char *string,
   1841 			      const char *file_name, size_t line_number)
   1842 {
   1843   if (xgettext_current_source_encoding == po_charset_ascii)
   1844     {
   1845       if (!is_ascii_string (string))
   1846 	{
   1847 	  char buffer[21];
   1848 
   1849 	  if (line_number == (size_t)(-1))
   1850 	    buffer[0] = '\0';
   1851 	  else
   1852 	    sprintf (buffer, ":%ld", (long) line_number);
   1853 	  multiline_error (xstrdup (""),
   1854 			   xasprintf (_("\
   1855 Non-ASCII string at %s%s.\n\
   1856 Please specify the source encoding through --from-code.\n"),
   1857 				      file_name, buffer));
   1858 	  exit (EXIT_FAILURE);
   1859 	}
   1860     }
   1861   else if (xgettext_current_source_encoding != po_charset_utf8)
   1862     {
   1863 #if HAVE_ICONV
   1864       struct conversion_context context;
   1865 
   1866       context.from_code = xgettext_current_source_encoding;
   1867       context.to_code = po_charset_utf8;
   1868       context.from_filename = file_name;
   1869       context.message = NULL;
   1870 
   1871       string = convert_string (xgettext_current_source_iconv, string, &context);
   1872 #else
   1873       /* If we don't have iconv(), the only supported values for
   1874 	 xgettext_global_source_encoding and thus also for
   1875 	 xgettext_current_source_encoding are ASCII and UTF-8.
   1876 	 convert_string() should not be called in this case.  */
   1877       abort ();
   1878 #endif
   1879     }
   1880 
   1881   return (char *) string;
   1882 }
   1883 
   1884 #define CONVERT_STRING(string) \
   1885   string = from_current_source_encoding (string, pos->file_name, \
   1886 					 pos->line_number);
   1887 
   1888 
   1889 /* Update the is_format[] flags depending on the information given in the
   1890    context.  */
   1891 static void
   1892 set_format_flags_from_context (enum is_format is_format[NFORMATS],
   1893 			       flag_context_ty context, const char *string,
   1894 			       lex_pos_ty *pos, const char *pretty_msgstr)
   1895 {
   1896   size_t i;
   1897 
   1898   if (context.is_format1 != undecided || context.is_format2 != undecided)
   1899     for (i = 0; i < NFORMATS; i++)
   1900       {
   1901 	if (is_format[i] == undecided)
   1902 	  {
   1903 	    if (formatstring_parsers[i] == current_formatstring_parser1
   1904 		&& context.is_format1 != undecided)
   1905 	      is_format[i] = (enum is_format) context.is_format1;
   1906 	    if (formatstring_parsers[i] == current_formatstring_parser2
   1907 		&& context.is_format2 != undecided)
   1908 	      is_format[i] = (enum is_format) context.is_format2;
   1909 	  }
   1910 	if (possible_format_p (is_format[i]))
   1911 	  {
   1912 	    struct formatstring_parser *parser = formatstring_parsers[i];
   1913 	    char *invalid_reason = NULL;
   1914 	    void *descr = parser->parse (string, false, &invalid_reason);
   1915 
   1916 	    if (descr != NULL)
   1917 	      parser->free (descr);
   1918 	    else
   1919 	      {
   1920 		/* The string is not a valid format string.  */
   1921 		if (is_format[i] != possible)
   1922 		  {
   1923 		    char buffer[21];
   1924 
   1925 		    error_with_progname = false;
   1926 		    if (pos->line_number == (size_t)(-1))
   1927 		      buffer[0] = '\0';
   1928 		    else
   1929 		      sprintf (buffer, ":%ld", (long) pos->line_number);
   1930 		    multiline_warning (xasprintf (_("%s%s: warning: "),
   1931 						  pos->file_name, buffer),
   1932 				       xasprintf (is_format[i] == yes_according_to_context
   1933 						  ? _("Although being used in a format string position, the %s is not a valid %s format string. Reason: %s\n")
   1934 						  : _("Although declared as such, the %s is not a valid %s format string. Reason: %s\n"),
   1935 						  pretty_msgstr,
   1936 						  format_language_pretty[i],
   1937 						  invalid_reason));
   1938 		    error_with_progname = true;
   1939 		  }
   1940 
   1941 		is_format[i] = impossible;
   1942 		free (invalid_reason);
   1943 	      }
   1944 	  }
   1945       }
   1946 }
   1947 
   1948 
   1949 static void
   1950 warn_format_string (enum is_format is_format[NFORMATS], const char *string,
   1951 		    lex_pos_ty *pos, const char *pretty_msgstr)
   1952 {
   1953   if (possible_format_p (is_format[format_python])
   1954       && get_python_format_unnamed_arg_count (string) > 1)
   1955     {
   1956       char buffer[21];
   1957 
   1958       error_with_progname = false;
   1959       if (pos->line_number == (size_t)(-1))
   1960         buffer[0] = '\0';
   1961       else
   1962         sprintf (buffer, ":%ld", (long) pos->line_number);
   1963       multiline_warning (xasprintf (_("%s%s: warning: "),
   1964 				    pos->file_name, buffer),
   1965 		         xasprintf (_("\
   1966 '%s' format string with unnamed arguments cannot be properly localized:\n\
   1967 The translator cannot reorder the arguments.\n\
   1968 Please consider using a format string with named arguments,\n\
   1969 and a mapping instead of a tuple for the arguments.\n"),
   1970                                     pretty_msgstr));
   1971       error_with_progname = true;
   1972     }
   1973 }
   1974 
   1975 
   1976 message_ty *
   1977 remember_a_message (message_list_ty *mlp, char *msgctxt, char *msgid,
   1978 		    flag_context_ty context, lex_pos_ty *pos,
   1979 		    refcounted_string_list_ty *comment)
   1980 {
   1981   enum is_format is_format[NFORMATS];
   1982   enum is_wrap do_wrap;
   1983   message_ty *mp;
   1984   char *msgstr;
   1985   size_t i;
   1986 
   1987   /* See whether we shall exclude this message.  */
   1988   if (exclude != NULL && message_list_search (exclude, msgctxt, msgid) != NULL)
   1989     {
   1990       /* Tell the lexer to reset its comment buffer, so that the next
   1991 	 message gets the correct comments.  */
   1992       xgettext_comment_reset ();
   1993       savable_comment_reset ();
   1994 
   1995       if (msgctxt != NULL)
   1996 	free (msgctxt);
   1997       free (msgid);
   1998 
   1999       return NULL;
   2000     }
   2001 
   2002   savable_comment_to_xgettext_comment (comment);
   2003 
   2004   for (i = 0; i < NFORMATS; i++)
   2005     is_format[i] = undecided;
   2006   do_wrap = undecided;
   2007 
   2008   if (msgctxt != NULL)
   2009     CONVERT_STRING (msgctxt);
   2010   CONVERT_STRING (msgid);
   2011 
   2012   if (msgctxt == NULL && msgid[0] == '\0' && !xgettext_omit_header)
   2013     {
   2014       char buffer[21];
   2015 
   2016       error_with_progname = false;
   2017       if (pos->line_number == (size_t)(-1))
   2018 	buffer[0] = '\0';
   2019       else
   2020 	sprintf (buffer, ":%ld", (long) pos->line_number);
   2021       multiline_warning (xasprintf (_("%s%s: warning: "), pos->file_name,
   2022 				    buffer),
   2023 			 xstrdup (_("\
   2024 Empty msgid.  It is reserved by GNU gettext:\n\
   2025 gettext(\"\") returns the header entry with\n\
   2026 meta information, not the empty string.\n")));
   2027       error_with_progname = true;
   2028     }
   2029 
   2030   /* See if we have seen this message before.  */
   2031   mp = message_list_search (mlp, msgctxt, msgid);
   2032   if (mp != NULL)
   2033     {
   2034       if (msgctxt != NULL)
   2035 	free (msgctxt);
   2036       free (msgid);
   2037       for (i = 0; i < NFORMATS; i++)
   2038 	is_format[i] = mp->is_format[i];
   2039       do_wrap = mp->do_wrap;
   2040     }
   2041   else
   2042     {
   2043       /* Construct the msgstr from the prefix and suffix, otherwise use the
   2044 	 empty string.  */
   2045       if (msgstr_prefix)
   2046 	msgstr = xasprintf ("%s%s%s", msgstr_prefix, msgid, msgstr_suffix);
   2047       else
   2048 	msgstr = "";
   2049 
   2050       /* Allocate a new message and append the message to the list.  */
   2051       mp = message_alloc (msgctxt, msgid, NULL, msgstr, strlen (msgstr) + 1,
   2052 			  pos);
   2053       /* Do not free msgctxt and msgid.  */
   2054       message_list_append (mlp, mp);
   2055     }
   2056 
   2057   /* Determine whether the context specifies that the msgid is a format
   2058      string.  */
   2059   set_format_flags_from_context (is_format, context, mp->msgid, pos, "msgid");
   2060 
   2061   /* Ask the lexer for the comments it has seen.  */
   2062   {
   2063     size_t nitems_before;
   2064     size_t nitems_after;
   2065     int j;
   2066     bool add_all_remaining_comments;
   2067 
   2068     nitems_before = (mp->comment_dot != NULL ? mp->comment_dot->nitems : 0);
   2069 
   2070     add_all_remaining_comments = add_all_comments;
   2071     for (j = 0; ; ++j)
   2072       {
   2073 	const char *s = xgettext_comment (j);
   2074 	const char *t;
   2075 	if (s == NULL)
   2076 	  break;
   2077 
   2078 	CONVERT_STRING (s);
   2079 
   2080 	/* To reduce the possibility of unwanted matches we do a two
   2081 	   step match: the line must contain `xgettext:' and one of
   2082 	   the possible format description strings.  */
   2083 	if ((t = c_strstr (s, "xgettext:")) != NULL)
   2084 	  {
   2085 	    bool tmp_fuzzy;
   2086 	    enum is_format tmp_format[NFORMATS];
   2087 	    enum is_wrap tmp_wrap;
   2088 	    bool interesting;
   2089 
   2090 	    t += strlen ("xgettext:");
   2091 
   2092 	    po_parse_comment_special (t, &tmp_fuzzy, tmp_format, &tmp_wrap);
   2093 
   2094 	    interesting = false;
   2095 	    for (i = 0; i < NFORMATS; i++)
   2096 	      if (tmp_format[i] != undecided)
   2097 		{
   2098 		  is_format[i] = tmp_format[i];
   2099 		  interesting = true;
   2100 		}
   2101 	    if (tmp_wrap != undecided)
   2102 	      {
   2103 		do_wrap = tmp_wrap;
   2104 		interesting = true;
   2105 	      }
   2106 
   2107 	    /* If the "xgettext:" marker was followed by an interesting
   2108 	       keyword, and we updated our is_format/do_wrap variables,
   2109 	       we don't print the comment as a #. comment.  */
   2110 	    if (interesting)
   2111 	      continue;
   2112 	  }
   2113 	/* When the comment tag is seen, it drags in not only the line
   2114 	   which it starts, but all remaining comment lines.  */
   2115 	if (add_all_remaining_comments
   2116 	    || (add_all_remaining_comments =
   2117 		  (comment_tag != NULL
   2118 		   && strncmp (s, comment_tag, strlen (comment_tag)) == 0)))
   2119 	  message_comment_dot_append (mp, s);
   2120       }
   2121 
   2122     nitems_after = (mp->comment_dot != NULL ? mp->comment_dot->nitems : 0);
   2123 
   2124     /* Don't add the comments if they are a repetition of the tail of the
   2125        already present comments.  This avoids unneeded duplication if the
   2126        same message appears several times, each time with the same comment.  */
   2127     if (nitems_before < nitems_after)
   2128       {
   2129 	size_t added = nitems_after - nitems_before;
   2130 
   2131 	if (added <= nitems_before)
   2132 	  {
   2133 	    bool repeated = true;
   2134 
   2135 	    for (i = 0; i < added; i++)
   2136 	      if (strcmp (mp->comment_dot->item[nitems_before - added + i],
   2137 			  mp->comment_dot->item[nitems_before + i]) != 0)
   2138 		{
   2139 		  repeated = false;
   2140 		  break;
   2141 		}
   2142 
   2143 	    if (repeated)
   2144 	      {
   2145 		for (i = 0; i < added; i++)
   2146 		  free ((char *) mp->comment_dot->item[nitems_before + i]);
   2147 		mp->comment_dot->nitems = nitems_before;
   2148 	      }
   2149 	  }
   2150       }
   2151   }
   2152 
   2153   /* If it is not already decided, through programmer comments, whether the
   2154      msgid is a format string, examine the msgid.  This is a heuristic.  */
   2155   for (i = 0; i < NFORMATS; i++)
   2156     {
   2157       if (is_format[i] == undecided
   2158 	  && (formatstring_parsers[i] == current_formatstring_parser1
   2159 	      || formatstring_parsers[i] == current_formatstring_parser2)
   2160 	  /* But avoid redundancy: objc-format is stronger than c-format.  */
   2161 	  && !(i == format_c && possible_format_p (is_format[format_objc]))
   2162 	  && !(i == format_objc && possible_format_p (is_format[format_c]))
   2163 	  /* Avoid flagging a string as c-format when it's known to be a
   2164 	     qt-format or boost-format string.  */
   2165 	  && !(i == format_c
   2166 	       && (possible_format_p (is_format[format_qt])
   2167 		   || possible_format_p (is_format[format_boost]))))
   2168 	{
   2169 	  struct formatstring_parser *parser = formatstring_parsers[i];
   2170 	  char *invalid_reason = NULL;
   2171 	  void *descr = parser->parse (mp->msgid, false, &invalid_reason);
   2172 
   2173 	  if (descr != NULL)
   2174 	    {
   2175 	      /* msgid is a valid format string.  We mark only those msgids
   2176 		 as format strings which contain at least one format directive
   2177 		 and thus are format strings with a high probability.  We
   2178 		 don't mark strings without directives as format strings,
   2179 		 because that would force the programmer to add
   2180 		 "xgettext: no-c-format" anywhere where a translator wishes
   2181 		 to use a percent sign.  So, the msgfmt checking will not be
   2182 		 perfect.  Oh well.  */
   2183 	      if (parser->get_number_of_directives (descr) > 0
   2184 		  && !(parser->is_unlikely_intentional != NULL
   2185 		       && parser->is_unlikely_intentional (descr)))
   2186 		is_format[i] = possible;
   2187 
   2188 	      parser->free (descr);
   2189 	    }
   2190 	  else
   2191 	    {
   2192 	      /* msgid is not a valid format string.  */
   2193 	      is_format[i] = impossible;
   2194 	      free (invalid_reason);
   2195 	    }
   2196 	}
   2197       mp->is_format[i] = is_format[i];
   2198     }
   2199 
   2200   mp->do_wrap = do_wrap == no ? no : yes;	/* By default we wrap.  */
   2201 
   2202   /* Warn about the use of non-reorderable format strings when the programming
   2203      language also provides reorderable format strings.  */
   2204   warn_format_string (is_format, mp->msgid, pos, "msgid");
   2205 
   2206   /* Remember where we saw this msgid.  */
   2207   if (line_comment)
   2208     message_comment_filepos (mp, pos->file_name, pos->line_number);
   2209 
   2210   /* Tell the lexer to reset its comment buffer, so that the next
   2211      message gets the correct comments.  */
   2212   xgettext_comment_reset ();
   2213   savable_comment_reset ();
   2214 
   2215   return mp;
   2216 }
   2217 
   2218 
   2219 void
   2220 remember_a_message_plural (message_ty *mp, char *string,
   2221 			   flag_context_ty context, lex_pos_ty *pos,
   2222 			   refcounted_string_list_ty *comment)
   2223 {
   2224   char *msgid_plural;
   2225   char *msgstr1;
   2226   size_t msgstr1_len;
   2227   char *msgstr;
   2228   size_t i;
   2229 
   2230   msgid_plural = string;
   2231 
   2232   savable_comment_to_xgettext_comment (comment);
   2233 
   2234   CONVERT_STRING (msgid_plural);
   2235 
   2236   /* See if the message is already a plural message.  */
   2237   if (mp->msgid_plural == NULL)
   2238     {
   2239       mp->msgid_plural = msgid_plural;
   2240 
   2241       /* Construct the first plural form from the prefix and suffix,
   2242 	 otherwise use the empty string.  The translator will have to
   2243 	 provide additional plural forms.  */
   2244       if (msgstr_prefix)
   2245 	msgstr1 =
   2246 	  xasprintf ("%s%s%s", msgstr_prefix, msgid_plural, msgstr_suffix);
   2247       else
   2248 	msgstr1 = "";
   2249       msgstr1_len = strlen (msgstr1) + 1;
   2250       msgstr = (char *) xmalloc (mp->msgstr_len + msgstr1_len);
   2251       memcpy (msgstr, mp->msgstr, mp->msgstr_len);
   2252       memcpy (msgstr + mp->msgstr_len, msgstr1, msgstr1_len);
   2253       mp->msgstr = msgstr;
   2254       mp->msgstr_len = mp->msgstr_len + msgstr1_len;
   2255       if (msgstr_prefix)
   2256 	free (msgstr1);
   2257 
   2258       /* Determine whether the context specifies that the msgid_plural is a
   2259 	 format string.  */
   2260       set_format_flags_from_context (mp->is_format, context, mp->msgid_plural,
   2261 				     pos, "msgid_plural");
   2262 
   2263       /* If it is not already decided, through programmer comments or
   2264 	 the msgid, whether the msgid is a format string, examine the
   2265 	 msgid_plural.  This is a heuristic.  */
   2266       for (i = 0; i < NFORMATS; i++)
   2267 	if ((formatstring_parsers[i] == current_formatstring_parser1
   2268 	     || formatstring_parsers[i] == current_formatstring_parser2)
   2269 	    && (mp->is_format[i] == undecided || mp->is_format[i] == possible)
   2270 	    /* But avoid redundancy: objc-format is stronger than c-format.  */
   2271 	    && !(i == format_c
   2272 		 && possible_format_p (mp->is_format[format_objc]))
   2273 	    && !(i == format_objc
   2274 		 && possible_format_p (mp->is_format[format_c]))
   2275 	    /* Avoid flagging a string as c-format when it's known to be a
   2276 	       qt-format or boost-format string.  */
   2277 	    && !(i == format_c
   2278 		 && (possible_format_p (mp->is_format[format_qt])
   2279 		     || possible_format_p (mp->is_format[format_boost]))))
   2280 	  {
   2281 	    struct formatstring_parser *parser = formatstring_parsers[i];
   2282 	    char *invalid_reason = NULL;
   2283 	    void *descr =
   2284 	      parser->parse (mp->msgid_plural, false, &invalid_reason);
   2285 
   2286 	    if (descr != NULL)
   2287 	      {
   2288 		/* Same heuristic as in remember_a_message.  */
   2289 		if (parser->get_number_of_directives (descr) > 0
   2290 		    && !(parser->is_unlikely_intentional != NULL
   2291 			 && parser->is_unlikely_intentional (descr)))
   2292 		  mp->is_format[i] = possible;
   2293 
   2294 		parser->free (descr);
   2295 	      }
   2296 	    else
   2297 	      {
   2298 		/* msgid_plural is not a valid format string.  */
   2299 		mp->is_format[i] = impossible;
   2300 		free (invalid_reason);
   2301 	      }
   2302 	  }
   2303 
   2304       /* Warn about the use of non-reorderable format strings when the programming
   2305          language also provides reorderable format strings.  */
   2306       warn_format_string (mp->is_format, mp->msgid_plural, pos, "msgid_plural");
   2307     }
   2308   else
   2309     free (msgid_plural);
   2310 
   2311   /* Tell the lexer to reset its comment buffer, so that the next
   2312      message gets the correct comments.  */
   2313   xgettext_comment_reset ();
   2314   savable_comment_reset ();
   2315 }
   2316 
   2317 
   2318 struct arglist_parser *
   2319 arglist_parser_alloc (message_list_ty *mlp, const struct callshapes *shapes)
   2320 {
   2321   if (shapes == NULL || shapes->nshapes == 0)
   2322     {
   2323       struct arglist_parser *ap =
   2324 	(struct arglist_parser *)
   2325 	xmalloc (offsetof (struct arglist_parser, alternative[0]));
   2326 
   2327       ap->mlp = mlp;
   2328       ap->keyword = NULL;
   2329       ap->keyword_len = 0;
   2330       ap->nalternatives = 0;
   2331 
   2332       return ap;
   2333     }
   2334   else
   2335     {
   2336       struct arglist_parser *ap =
   2337 	(struct arglist_parser *)
   2338 	xmalloc (sizeof (struct arglist_parser)
   2339 		 + (shapes->nshapes - 1) * sizeof (struct partial_call));
   2340       size_t i;
   2341 
   2342       ap->mlp = mlp;
   2343       ap->keyword = shapes->keyword;
   2344       ap->keyword_len = shapes->keyword_len;
   2345       ap->nalternatives = shapes->nshapes;
   2346       for (i = 0; i < shapes->nshapes; i++)
   2347 	{
   2348 	  ap->alternative[i].argnumc = shapes->shapes[i].argnumc;
   2349 	  ap->alternative[i].argnum1 = shapes->shapes[i].argnum1;
   2350 	  ap->alternative[i].argnum2 = shapes->shapes[i].argnum2;
   2351 	  ap->alternative[i].argnum1_glib_context =
   2352 	    shapes->shapes[i].argnum1_glib_context;
   2353 	  ap->alternative[i].argnum2_glib_context =
   2354 	    shapes->shapes[i].argnum2_glib_context;
   2355 	  ap->alternative[i].argtotal = shapes->shapes[i].argtotal;
   2356 	  ap->alternative[i].xcomments = shapes->shapes[i].xcomments;
   2357 	  ap->alternative[i].msgctxt = NULL;
   2358 	  ap->alternative[i].msgctxt_pos.file_name = NULL;
   2359 	  ap->alternative[i].msgctxt_pos.line_number = (size_t)(-1);
   2360 	  ap->alternative[i].msgid = NULL;
   2361 	  ap->alternative[i].msgid_context = null_context;
   2362 	  ap->alternative[i].msgid_pos.file_name = NULL;
   2363 	  ap->alternative[i].msgid_pos.line_number = (size_t)(-1);
   2364 	  ap->alternative[i].msgid_comment = NULL;
   2365 	  ap->alternative[i].msgid_plural = NULL;
   2366 	  ap->alternative[i].msgid_plural_context = null_context;
   2367 	  ap->alternative[i].msgid_plural_pos.file_name = NULL;
   2368 	  ap->alternative[i].msgid_plural_pos.line_number = (size_t)(-1);
   2369 	}
   2370 
   2371       return ap;
   2372     }
   2373 }
   2374 
   2375 
   2376 struct arglist_parser *
   2377 arglist_parser_clone (struct arglist_parser *ap)
   2378 {
   2379   struct arglist_parser *copy =
   2380     (struct arglist_parser *)
   2381     xmalloc (sizeof (struct arglist_parser) - sizeof (struct partial_call)
   2382 	     + ap->nalternatives * sizeof (struct partial_call));
   2383   size_t i;
   2384 
   2385   copy->mlp = ap->mlp;
   2386   copy->keyword = ap->keyword;
   2387   copy->keyword_len = ap->keyword_len;
   2388   copy->nalternatives = ap->nalternatives;
   2389   for (i = 0; i < ap->nalternatives; i++)
   2390     {
   2391       const struct partial_call *cp = &ap->alternative[i];
   2392       struct partial_call *ccp = &copy->alternative[i];
   2393 
   2394       ccp->argnumc = cp->argnumc;
   2395       ccp->argnum1 = cp->argnum1;
   2396       ccp->argnum2 = cp->argnum2;
   2397       ccp->argnum1_glib_context = cp->argnum1_glib_context;
   2398       ccp->argnum2_glib_context = cp->argnum2_glib_context;
   2399       ccp->argtotal = cp->argtotal;
   2400       ccp->xcomments = cp->xcomments;
   2401       ccp->msgctxt = (cp->msgctxt != NULL ? xstrdup (cp->msgctxt) : NULL);
   2402       ccp->msgctxt_pos = cp->msgctxt_pos;
   2403       ccp->msgid = (cp->msgid != NULL ? xstrdup (cp->msgid) : NULL);
   2404       ccp->msgid_context = cp->msgid_context;
   2405       ccp->msgid_pos = cp->msgctxt_pos;
   2406       ccp->msgid_comment = add_reference (cp->msgid_comment);
   2407       ccp->msgid_plural =
   2408 	(cp->msgid_plural != NULL ? xstrdup (cp->msgid_plural) : NULL);
   2409       ccp->msgid_plural_context = cp->msgid_plural_context;
   2410       ccp->msgid_plural_pos = cp->msgid_plural_pos;
   2411     }
   2412 
   2413   return copy;
   2414 }
   2415 
   2416 
   2417 void
   2418 arglist_parser_remember (struct arglist_parser *ap,
   2419 			 int argnum, char *string,
   2420 			 flag_context_ty context,
   2421 			 char *file_name, size_t line_number,
   2422 			 refcounted_string_list_ty *comment)
   2423 {
   2424   bool stored_string = false;
   2425   size_t nalternatives = ap->nalternatives;
   2426   size_t i;
   2427 
   2428   if (!(argnum > 0))
   2429     abort ();
   2430   for (i = 0; i < nalternatives; i++)
   2431     {
   2432       struct partial_call *cp = &ap->alternative[i];
   2433 
   2434       if (argnum == cp->argnumc)
   2435 	{
   2436 	  cp->msgctxt = string;
   2437 	  cp->msgctxt_pos.file_name = file_name;
   2438 	  cp->msgctxt_pos.line_number = line_number;
   2439 	  stored_string = true;
   2440 	  /* Mark msgctxt as done.  */
   2441 	  cp->argnumc = 0;
   2442 	}
   2443       else if (argnum == cp->argnum1)
   2444 	{
   2445 	  cp->msgid = string;
   2446 	  cp->msgid_context = context;
   2447 	  cp->msgid_pos.file_name = file_name;
   2448 	  cp->msgid_pos.line_number = line_number;
   2449 	  cp->msgid_comment = add_reference (comment);
   2450 	  stored_string = true;
   2451 	  /* Mark msgid as done.  */
   2452 	  cp->argnum1 = 0;
   2453 	}
   2454       else if (argnum == cp->argnum2)
   2455 	{
   2456 	  cp->msgid_plural = string;
   2457 	  cp->msgid_plural_context = context;
   2458 	  cp->msgid_plural_pos.file_name = file_name;
   2459 	  cp->msgid_plural_pos.line_number = line_number;
   2460 	  stored_string = true;
   2461 	  /* Mark msgid_plural as done.  */
   2462 	  cp->argnum2 = 0;
   2463 	}
   2464     }
   2465   /* Note: There is a memory leak here: When string was stored but is later
   2466      not used by arglist_parser_done, we don't free it.  */
   2467   if (!stored_string)
   2468     free (string);
   2469 }
   2470 
   2471 
   2472 bool
   2473 arglist_parser_decidedp (struct arglist_parser *ap, int argnum)
   2474 {
   2475   size_t i;
   2476 
   2477   /* Test whether all alternatives are decided.
   2478      Note: A decided alternative can be complete
   2479        cp->argnumc == 0 && cp->argnum1 == 0 && cp->argnum2 == 0
   2480        && cp->argtotal == 0
   2481      or it can be failed if no literal strings were found at the specified
   2482      argument positions:
   2483        cp->argnumc <= argnum && cp->argnum1 <= argnum && cp->argnum2 <= argnum
   2484      or it can be failed if the number of arguments is exceeded:
   2485        cp->argtotal > 0 && cp->argtotal < argnum
   2486    */
   2487   for (i = 0; i < ap->nalternatives; i++)
   2488     {
   2489       struct partial_call *cp = &ap->alternative[i];
   2490 
   2491       if (!((cp->argnumc <= argnum
   2492 	     && cp->argnum1 <= argnum
   2493 	     && cp->argnum2 <= argnum)
   2494 	    || (cp->argtotal > 0 && cp->argtotal < argnum)))
   2495 	/* cp is still undecided.  */
   2496 	return false;
   2497     }
   2498   return true;
   2499 }
   2500 
   2501 
   2502 void
   2503 arglist_parser_done (struct arglist_parser *ap, int argnum)
   2504 {
   2505   size_t ncomplete;
   2506   size_t i;
   2507 
   2508   /* Determine the number of complete calls.  */
   2509   ncomplete = 0;
   2510   for (i = 0; i < ap->nalternatives; i++)
   2511     {
   2512       struct partial_call *cp = &ap->alternative[i];
   2513 
   2514       if (cp->argnumc == 0 && cp->argnum1 == 0 && cp->argnum2 == 0
   2515 	  && (cp->argtotal == 0 || cp->argtotal == argnum))
   2516 	ncomplete++;
   2517     }
   2518 
   2519   if (ncomplete > 0)
   2520     {
   2521       struct partial_call *best_cp = NULL;
   2522       bool ambiguous = false;
   2523 
   2524       /* Find complete calls where msgctxt, msgid, msgid_plural are all
   2525 	 provided.  */
   2526       for (i = 0; i < ap->nalternatives; i++)
   2527 	{
   2528 	  struct partial_call *cp = &ap->alternative[i];
   2529 
   2530 	  if (cp->argnumc == 0 && cp->argnum1 == 0 && cp->argnum2 == 0
   2531 	      && (cp->argtotal == 0 || cp->argtotal == argnum)
   2532 	      && cp->msgctxt != NULL
   2533 	      && cp->msgid != NULL
   2534 	      && cp->msgid_plural != NULL)
   2535 	    {
   2536 	      if (best_cp != NULL)
   2537 		{
   2538 		  ambiguous = true;
   2539 		  break;
   2540 		}
   2541 	      best_cp = cp;
   2542 	    }
   2543 	}
   2544 
   2545       if (best_cp == NULL)
   2546 	{
   2547 	  struct partial_call *best_cp1 = NULL;
   2548 	  struct partial_call *best_cp2 = NULL;
   2549 
   2550 	  /* Find complete calls where msgctxt, msgid are provided.  */
   2551 	  for (i = 0; i < ap->nalternatives; i++)
   2552 	    {
   2553 	      struct partial_call *cp = &ap->alternative[i];
   2554 
   2555 	      if (cp->argnumc == 0 && cp->argnum1 == 0 && cp->argnum2 == 0
   2556 		  && (cp->argtotal == 0 || cp->argtotal == argnum)
   2557 		  && cp->msgctxt != NULL
   2558 		  && cp->msgid != NULL)
   2559 		{
   2560 		  if (best_cp1 != NULL)
   2561 		    {
   2562 		      ambiguous = true;
   2563 		      break;
   2564 		    }
   2565 		  best_cp1 = cp;
   2566 		}
   2567 	    }
   2568 
   2569 	  /* Find complete calls where msgid, msgid_plural are provided.  */
   2570 	  for (i = 0; i < ap->nalternatives; i++)
   2571 	    {
   2572 	      struct partial_call *cp = &ap->alternative[i];
   2573 
   2574 	      if (cp->argnumc == 0 && cp->argnum1 == 0 && cp->argnum2 == 0
   2575 		  && (cp->argtotal == 0 || cp->argtotal == argnum)
   2576 		  && cp->msgid != NULL
   2577 		  && cp->msgid_plural != NULL)
   2578 		{
   2579 		  if (best_cp2 != NULL)
   2580 		    {
   2581 		      ambiguous = true;
   2582 		      break;
   2583 		    }
   2584 		  best_cp2 = cp;
   2585 		}
   2586 	    }
   2587 
   2588 	  if (best_cp1 != NULL)
   2589 	    best_cp = best_cp1;
   2590 	  if (best_cp2 != NULL)
   2591 	    {
   2592 	      if (best_cp != NULL)
   2593 		ambiguous = true;
   2594 	      else
   2595 		best_cp = best_cp2;
   2596 	    }
   2597 	}
   2598 
   2599       if (best_cp == NULL)
   2600 	{
   2601 	  /* Find complete calls where msgid is provided.  */
   2602 	  for (i = 0; i < ap->nalternatives; i++)
   2603 	    {
   2604 	      struct partial_call *cp = &ap->alternative[i];
   2605 
   2606 	      if (cp->argnumc == 0 && cp->argnum1 == 0 && cp->argnum2 == 0
   2607 		  && (cp->argtotal == 0 || cp->argtotal == argnum)
   2608 		  && cp->msgid != NULL)
   2609 		{
   2610 		  if (best_cp != NULL)
   2611 		    {
   2612 		      ambiguous = true;
   2613 		      break;
   2614 		    }
   2615 		  best_cp = cp;
   2616 		}
   2617 	    }
   2618 	}
   2619 
   2620       if (ambiguous)
   2621 	{
   2622 	  error_with_progname = false;
   2623 	  error_at_line (0, 0,
   2624 			 best_cp->msgid_pos.file_name,
   2625 			 best_cp->msgid_pos.line_number,
   2626 			 _("ambiguous argument specification for keyword '%.*s'"),
   2627 			 (int) ap->keyword_len, ap->keyword);
   2628 	  error_with_progname = true;
   2629 	}
   2630 
   2631       if (best_cp != NULL)
   2632 	{
   2633 	  /* best_cp indicates the best found complete call.
   2634 	     Now call remember_a_message.  */
   2635 	  message_ty *mp;
   2636 
   2637 	  /* Split strings in the GNOME glib syntax "msgctxt|msgid".  */
   2638 	  if (best_cp->argnum1_glib_context || best_cp->argnum2_glib_context)
   2639 	    /* split_keywordspec should not allow the context to be specified
   2640 	       in two different ways.  */
   2641 	    if (best_cp->msgctxt != NULL)
   2642 	      abort ();
   2643 	  if (best_cp->argnum1_glib_context)
   2644 	    {
   2645 	      const char *separator = strchr (best_cp->msgid, '|');
   2646 
   2647 	      if (separator == NULL)
   2648 		{
   2649 		  error_with_progname = false;
   2650 		  error_at_line (0, 0,
   2651 				 best_cp->msgid_pos.file_name,
   2652 				 best_cp->msgid_pos.line_number,
   2653 				 _("warning: missing context for keyword '%.*s'"),
   2654 				 (int) ap->keyword_len, ap->keyword);
   2655 		  error_with_progname = true;
   2656 		}
   2657 	      else
   2658 		{
   2659 		  size_t ctxt_len = separator - best_cp->msgid;
   2660 		  char *ctxt = (char *) xmalloc (ctxt_len + 1);
   2661 
   2662 		  memcpy (ctxt, best_cp->msgid, ctxt_len);
   2663 		  ctxt[ctxt_len] = '\0';
   2664 		  best_cp->msgctxt = ctxt;
   2665 		  best_cp->msgid = xstrdup (separator + 1);
   2666 		}
   2667 	    }
   2668 	  if (best_cp->msgid_plural != NULL && best_cp->argnum2_glib_context)
   2669 	    {
   2670 	      const char *separator = strchr (best_cp->msgid_plural, '|');
   2671 
   2672 	      if (separator == NULL)
   2673 		{
   2674 		  error_with_progname = false;
   2675 		  error_at_line (0, 0,
   2676 				 best_cp->msgid_plural_pos.file_name,
   2677 				 best_cp->msgid_plural_pos.line_number,
   2678 				 _("warning: missing context for plural argument of keyword '%.*s'"),
   2679 				 (int) ap->keyword_len, ap->keyword);
   2680 		  error_with_progname = true;
   2681 		}
   2682 	      else
   2683 		{
   2684 		  size_t ctxt_len = separator - best_cp->msgid_plural;
   2685 		  char *ctxt = (char *) xmalloc (ctxt_len + 1);
   2686 
   2687 		  memcpy (ctxt, best_cp->msgid_plural, ctxt_len);
   2688 		  ctxt[ctxt_len] = '\0';
   2689 		  if (best_cp->msgctxt == NULL)
   2690 		    best_cp->msgctxt = ctxt;
   2691 		  else
   2692 		    {
   2693 		      if (strcmp (ctxt, best_cp->msgctxt) != 0)
   2694 			{
   2695 			  error_with_progname = false;
   2696 			  error_at_line (0, 0,
   2697 					 best_cp->msgid_plural_pos.file_name,
   2698 					 best_cp->msgid_plural_pos.line_number,
   2699 					 _("context mismatch between singular and plural form"));
   2700 			  error_with_progname = true;
   2701 			}
   2702 		      free (ctxt);
   2703 		    }
   2704 		  best_cp->msgid_plural = xstrdup (separator + 1);
   2705 		}
   2706 	    }
   2707 
   2708 	  mp = remember_a_message (ap->mlp, best_cp->msgctxt, best_cp->msgid,
   2709 				   best_cp->msgid_context,
   2710 				   &best_cp->msgid_pos,
   2711 				   best_cp->msgid_comment);
   2712 	  if (best_cp->msgid_plural != NULL)
   2713 	    remember_a_message_plural (mp, best_cp->msgid_plural,
   2714 				       best_cp->msgid_plural_context,
   2715 				       &best_cp->msgid_plural_pos,
   2716 				       NULL);
   2717 	  if (best_cp->xcomments.nitems > 0)
   2718 	    {
   2719 	      /* Add best_cp->xcomments to mp->comment_dot, unless already
   2720 		 present.  */
   2721 	      size_t i;
   2722 
   2723 	      for (i = 0; i < best_cp->xcomments.nitems; i++)
   2724 		{
   2725 		  const char *xcomment = best_cp->xcomments.item[i];
   2726 		  bool found = false;
   2727 
   2728 		  if (mp->comment_dot != NULL)
   2729 		    {
   2730 		      size_t j;
   2731 
   2732 		      for (j = 0; j < mp->comment_dot->nitems; j++)
   2733 			if (strcmp (xcomment, mp->comment_dot->item[j]) == 0)
   2734 			  {
   2735 			    found = true;
   2736 			    break;
   2737 			  }
   2738 		    }
   2739 		  if (!found)
   2740 		    message_comment_dot_append (mp, xcomment);
   2741 		}
   2742 	    }
   2743 	}
   2744     }
   2745   else
   2746     {
   2747       /* No complete call was parsed.  */
   2748       /* Note: There is a memory leak here: When there is more than one
   2749 	 alternative, the same string can be stored in multiple alternatives,
   2750 	 and it's not easy to free all strings reliably.  */
   2751       if (ap->nalternatives == 1)
   2752 	{
   2753 	  if (ap->alternative[0].msgctxt != NULL)
   2754 	    free (ap->alternative[0].msgctxt);
   2755 	  if (ap->alternative[0].msgid != NULL)
   2756 	    free (ap->alternative[0].msgid);
   2757 	  if (ap->alternative[0].msgid_plural != NULL)
   2758 	    free (ap->alternative[0].msgid_plural);
   2759 	}
   2760     }
   2761 
   2762   for (i = 0; i < ap->nalternatives; i++)
   2763     drop_reference (ap->alternative[i].msgid_comment);
   2764   free (ap);
   2765 }
   2766 
   2767 
   2768 static message_ty *
   2769 construct_header ()
   2770 {
   2771   time_t now;
   2772   char *timestring;
   2773   message_ty *mp;
   2774   char *msgstr;
   2775   static lex_pos_ty pos = { __FILE__, __LINE__ };
   2776 
   2777   if (msgid_bugs_address != NULL && msgid_bugs_address[0] == '\0')
   2778     multiline_warning (xasprintf (_("warning: ")),
   2779 		       xstrdup (_("\
   2780 The option --msgid-bugs-address was not specified.\n\
   2781 If you are using a `Makevars' file, please specify\n\
   2782 the MSGID_BUGS_ADDRESS variable there; otherwise please\n\
   2783 specify an --msgid-bugs-address command line option.\n\
   2784 ")));
   2785 
   2786   time (&now);
   2787   timestring = po_strftime (&now);
   2788 
   2789   msgstr = xasprintf ("\
   2790 Project-Id-Version: PACKAGE VERSION\n\
   2791 Report-Msgid-Bugs-To: %s\n\
   2792 POT-Creation-Date: %s\n\
   2793 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n\
   2794 Last-Translator: FULL NAME <EMAIL@ADDRESS>\n\
   2795 Language-Team: LANGUAGE <LL (at) li.org>\n\
   2796 MIME-Version: 1.0\n\
   2797 Content-Type: text/plain; charset=CHARSET\n\
   2798 Content-Transfer-Encoding: 8bit\n",
   2799 		      msgid_bugs_address != NULL ? msgid_bugs_address : "",
   2800 		      timestring);
   2801   free (timestring);
   2802 
   2803   mp = message_alloc (NULL, "", NULL, msgstr, strlen (msgstr) + 1, &pos);
   2804 
   2805   message_comment_append (mp,
   2806 			  copyright_holder[0] != '\0'
   2807 			  ? xasprintf ("\
   2808 SOME DESCRIPTIVE TITLE.\n\
   2809 Copyright (C) YEAR %s\n\
   2810 This file is distributed under the same license as the PACKAGE package.\n\
   2811 FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n",
   2812 				       copyright_holder)
   2813 			  : "\
   2814 SOME DESCRIPTIVE TITLE.\n\
   2815 This file is put in the public domain.\n\
   2816 FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n");
   2817 
   2818   mp->is_fuzzy = true;
   2819 
   2820   return mp;
   2821 }
   2822 
   2823 static void
   2824 finalize_header (msgdomain_list_ty *mdlp)
   2825 {
   2826   /* If the generated PO file has plural forms, add a Plural-Forms template
   2827      to the constructed header.  */
   2828   {
   2829     bool has_plural;
   2830     size_t i, j;
   2831 
   2832     has_plural = false;
   2833     for (i = 0; i < mdlp->nitems; i++)
   2834       {
   2835 	message_list_ty *mlp = mdlp->item[i]->messages;
   2836 
   2837 	for (j = 0; j < mlp->nitems; j++)
   2838 	  {
   2839 	    message_ty *mp = mlp->item[j];
   2840 
   2841 	    if (mp->msgid_plural != NULL)
   2842 	      {
   2843 		has_plural = true;
   2844 		break;
   2845 	      }
   2846 	  }
   2847 	if (has_plural)
   2848 	  break;
   2849       }
   2850 
   2851     if (has_plural)
   2852       {
   2853 	message_ty *header =
   2854 	  message_list_search (mdlp->item[0]->messages, NULL, "");
   2855 	if (header != NULL
   2856 	    && c_strstr (header->msgstr, "Plural-Forms:") == NULL)
   2857 	  {
   2858 	    size_t insertpos = strlen (header->msgstr);
   2859 	    const char *suffix;
   2860 	    size_t suffix_len;
   2861 	    char *new_msgstr;
   2862 
   2863 	    suffix = "\nPlural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n";
   2864 	    if (insertpos == 0 || header->msgstr[insertpos-1] == '\n')
   2865 	      suffix++;
   2866 	    suffix_len = strlen (suffix);
   2867 	    new_msgstr = (char *) xmalloc (header->msgstr_len + suffix_len);
   2868 	    memcpy (new_msgstr, header->msgstr, insertpos);
   2869 	    memcpy (new_msgstr + insertpos, suffix, suffix_len);
   2870 	    memcpy (new_msgstr + insertpos + suffix_len,
   2871 		    header->msgstr + insertpos,
   2872 		    header->msgstr_len - insertpos);
   2873 	    header->msgstr = new_msgstr;
   2874 	    header->msgstr_len = header->msgstr_len + suffix_len;
   2875 	  }
   2876       }
   2877   }
   2878 
   2879   /* If not all the strings were plain ASCII, or if the output syntax
   2880      requires a charset conversion, set the charset in the header to UTF-8.
   2881      All messages have already been converted to UTF-8 in remember_a_message
   2882      and remember_a_message_plural.  */
   2883   {
   2884     bool has_nonascii = false;
   2885     size_t i;
   2886 
   2887     for (i = 0; i < mdlp->nitems; i++)
   2888       {
   2889 	message_list_ty *mlp = mdlp->item[i]->messages;
   2890 
   2891 	if (!is_ascii_message_list (mlp))
   2892 	  has_nonascii = true;
   2893       }
   2894 
   2895     if (has_nonascii || output_syntax->requires_utf8)
   2896       {
   2897 	message_list_ty *mlp = mdlp->item[0]->messages;
   2898 
   2899 	iconv_message_list (mlp, po_charset_utf8, po_charset_utf8, NULL);
   2900       }
   2901   }
   2902 }
   2903 
   2904 
   2905 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
   2906 #define ENDOF(a) ((a) + SIZEOF(a))
   2907 
   2908 
   2909 static extractor_ty
   2910 language_to_extractor (const char *name)
   2911 {
   2912   struct table_ty
   2913   {
   2914     const char *name;
   2915     extractor_func func;
   2916     flag_context_list_table_ty *flag_table;
   2917     struct formatstring_parser *formatstring_parser1;
   2918     struct formatstring_parser *formatstring_parser2;
   2919   };
   2920   typedef struct table_ty table_ty;
   2921 
   2922   static table_ty table[] =
   2923   {
   2924     SCANNERS_C
   2925     SCANNERS_PO
   2926     SCANNERS_SH
   2927     SCANNERS_PYTHON
   2928     SCANNERS_LISP
   2929     SCANNERS_ELISP
   2930     SCANNERS_LIBREP
   2931     SCANNERS_SCHEME
   2932     SCANNERS_SMALLTALK
   2933     SCANNERS_JAVA
   2934     SCANNERS_PROPERTIES
   2935     SCANNERS_CSHARP
   2936     SCANNERS_AWK
   2937     SCANNERS_YCP
   2938     SCANNERS_TCL
   2939     SCANNERS_PERL
   2940     SCANNERS_PHP
   2941     SCANNERS_STRINGTABLE
   2942     SCANNERS_RST
   2943     SCANNERS_GLADE
   2944     /* Here may follow more languages and their scanners: pike, etc...
   2945        Make sure new scanners honor the --exclude-file option.  */
   2946   };
   2947 
   2948   table_ty *tp;
   2949 
   2950   for (tp = table; tp < ENDOF(table); ++tp)
   2951     if (c_strcasecmp (name, tp->name) == 0)
   2952       {
   2953 	extractor_ty result;
   2954 
   2955 	result.func = tp->func;
   2956 	result.flag_table = tp->flag_table;
   2957 	result.formatstring_parser1 = tp->formatstring_parser1;
   2958 	result.formatstring_parser2 = tp->formatstring_parser2;
   2959 
   2960 	/* Handle --qt.  It's preferrable to handle this facility here rather
   2961 	   than through an option --language=C++/Qt because the latter would
   2962 	   conflict with the language "C++" regarding the file extensions.  */
   2963 	if (recognize_format_qt && strcmp (tp->name, "C++") == 0)
   2964 	  {
   2965 	    result.flag_table = &flag_table_cxx_qt;
   2966 	    result.formatstring_parser2 = &formatstring_qt;
   2967 	  }
   2968 	/* Likewise for --boost.  */
   2969 	if (recognize_format_boost && strcmp (tp->name, "C++") == 0)
   2970 	  {
   2971 	    result.flag_table = &flag_table_cxx_boost;
   2972 	    result.formatstring_parser2 = &formatstring_boost;
   2973 	  }
   2974 
   2975 	return result;
   2976       }
   2977 
   2978   error (EXIT_FAILURE, 0, _("language `%s' unknown"), name);
   2979   /* NOTREACHED */
   2980   {
   2981     extractor_ty result = { NULL, NULL, NULL, NULL };
   2982     return result;
   2983   }
   2984 }
   2985 
   2986 
   2987 static const char *
   2988 extension_to_language (const char *extension)
   2989 {
   2990   struct table_ty
   2991   {
   2992     const char *extension;
   2993     const char *language;
   2994   };
   2995   typedef struct table_ty table_ty;
   2996 
   2997   static table_ty table[] =
   2998   {
   2999     EXTENSIONS_C
   3000     EXTENSIONS_PO
   3001     EXTENSIONS_SH
   3002     EXTENSIONS_PYTHON
   3003     EXTENSIONS_LISP
   3004     EXTENSIONS_ELISP
   3005     EXTENSIONS_LIBREP
   3006     EXTENSIONS_SCHEME
   3007     EXTENSIONS_SMALLTALK
   3008     EXTENSIONS_JAVA
   3009     EXTENSIONS_PROPERTIES
   3010     EXTENSIONS_CSHARP
   3011     EXTENSIONS_AWK
   3012     EXTENSIONS_YCP
   3013     EXTENSIONS_TCL
   3014     EXTENSIONS_PERL
   3015     EXTENSIONS_PHP
   3016     EXTENSIONS_STRINGTABLE
   3017     EXTENSIONS_RST
   3018     EXTENSIONS_GLADE
   3019     /* Here may follow more file extensions... */
   3020   };
   3021 
   3022   table_ty *tp;
   3023 
   3024   for (tp = table; tp < ENDOF(table); ++tp)
   3025     if (strcmp (extension, tp->extension) == 0)
   3026       return tp->language;
   3027   return NULL;
   3028 }
   3029