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