1 /* GNU gettext - internationalization aids
2 Copyright (C) 1997-1998, 2000-2007, 2009-2012 Free Software Foundation, Inc.
4 This file was written by Peter Miller <millerp@canb.auug.org.au>
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
32 #include "file-list.h"
34 #include "error-progname.h"
36 #include "relocatable.h"
39 #include "read-catalog.h"
41 #include "read-properties.h"
42 #include "read-stringtable.h"
43 #include "write-catalog.h"
45 #include "write-properties.h"
46 #include "write-stringtable.h"
49 #include "propername.h"
53 /* A convenience macro. I don't like writing gettext() every time. */
54 #define _(str) gettext (str)
57 /* Force output of PO file even if empty. */
60 /* Target encoding. */
61 static const char *to_code;
64 static const struct option long_options[] =
66 { "add-location", no_argument, &line_comment, 1 },
67 { "color", optional_argument, NULL, CHAR_MAX + 5 },
68 { "directory", required_argument, NULL, 'D' },
69 { "escape", no_argument, NULL, 'E' },
70 { "files-from", required_argument, NULL, 'f' },
71 { "force-po", no_argument, &force_po, 1 },
72 { "help", no_argument, NULL, 'h' },
73 { "indent", no_argument, NULL, 'i' },
74 { "no-escape", no_argument, NULL, 'e' },
75 { "no-location", no_argument, &line_comment, 0 },
76 { "no-wrap", no_argument, NULL, CHAR_MAX + 2 },
77 { "omit-header", no_argument, NULL, CHAR_MAX + 1 },
78 { "output", required_argument, NULL, 'o' }, /* for backward compatibility */
79 { "output-file", required_argument, NULL, 'o' },
80 { "properties-input", no_argument, NULL, 'P' },
81 { "properties-output", no_argument, NULL, 'p' },
82 { "sort-by-file", no_argument, NULL, 'F' },
83 { "sort-output", no_argument, NULL, 's' },
84 { "strict", no_argument, NULL, 'S' },
85 { "stringtable-input", no_argument, NULL, CHAR_MAX + 3 },
86 { "stringtable-output", no_argument, NULL, CHAR_MAX + 4 },
87 { "style", required_argument, NULL, CHAR_MAX + 6 },
88 { "to-code", required_argument, NULL, 't' },
89 { "unique", no_argument, NULL, 'u' },
90 { "version", no_argument, NULL, 'V' },
91 { "width", required_argument, NULL, 'w', },
92 { "more-than", required_argument, NULL, '>', },
93 { "less-than", required_argument, NULL, '<', },
98 /* Forward declaration of local functions. */
99 static void usage (int status)
100 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ > 4) || __GNUC__ > 2)
101 __attribute__ ((noreturn))
107 main (int argc, char *argv[])
111 bool do_help = false;
112 bool do_version = false;
113 msgdomain_list_ty *result;
114 catalog_input_format_ty input_syntax = &input_format_po;
115 catalog_output_format_ty output_syntax = &output_format_po;
116 bool sort_by_msgid = false;
117 bool sort_by_filepos = false;
118 const char *files_from = NULL;
119 string_list_ty *file_list;
120 char *output_file = NULL;
122 /* Set program name for messages. */
123 set_program_name (argv[0]);
124 error_print_progname = maybe_print_progname;
126 #ifdef HAVE_SETLOCALE
127 /* Set locale via LC_ALL. */
128 setlocale (LC_ALL, "");
131 /* Set the text message domain. */
132 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
133 bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
134 textdomain (PACKAGE);
136 /* Ensure that write errors on stdout are detected. */
137 atexit (close_stdout);
139 /* Set default values for variables. */
144 while ((optchar = getopt_long (argc, argv, "<:>:D:eEf:Fhino:pPst:uVw:",
145 long_options, NULL)) != EOF)
148 case '\0': /* Long option. */
155 value = strtol (optarg, &endp, 10);
165 value = strtol (optarg, &endp, 10);
172 dir_list_append (optarg);
176 message_print_style_escape (false);
180 message_print_style_escape (true);
188 sort_by_filepos = true;
196 message_print_style_indent ();
204 output_file = optarg;
208 output_syntax = &output_format_properties;
212 input_syntax = &input_format_properties;
216 sort_by_msgid = true;
220 message_print_style_uniforum ();
239 value = strtol (optarg, &endp, 10);
241 message_page_width_set (value);
249 case CHAR_MAX + 2: /* --no-wrap */
250 message_page_width_ignore ();
253 case CHAR_MAX + 3: /* --stringtable-input */
254 input_syntax = &input_format_stringtable;
257 case CHAR_MAX + 4: /* --stringtable-output */
258 output_syntax = &output_format_stringtable;
261 case CHAR_MAX + 5: /* --color */
262 if (handle_color_option (optarg) || color_test_mode)
263 usage (EXIT_FAILURE);
266 case CHAR_MAX + 6: /* --style */
267 handle_style_option (optarg);
271 usage (EXIT_FAILURE);
275 /* Version information requested. */
278 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
279 /* xgettext: no-wrap */
280 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
281 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
282 This is free software: you are free to change and redistribute it.\n\
283 There is NO WARRANTY, to the extent permitted by law.\n\
285 "1995-1998, 2000-2010");
286 printf (_("Written by %s.\n"), proper_name ("Peter Miller"));
290 /* Help is requested. */
292 usage (EXIT_SUCCESS);
294 /* Verify selected options. */
295 if (!line_comment && sort_by_filepos)
296 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
297 "--no-location", "--sort-by-file");
299 if (sort_by_msgid && sort_by_filepos)
300 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
301 "--sort-output", "--sort-by-file");
303 /* Determine list of files we have to process. */
304 if (files_from != NULL)
305 file_list = read_names_from_file (files_from);
307 file_list = string_list_alloc ();
308 /* Append names from command line. */
309 for (cnt = optind; cnt < argc; ++cnt)
310 string_list_append_unique (file_list, argv[cnt]);
312 /* Test whether sufficient input files were given. */
313 if (file_list->nitems < 2)
315 error (EXIT_SUCCESS, 0, _("at least two files must be specified"));
316 usage (EXIT_FAILURE);
319 /* Default the message selection criteria, and check them for sanity. */
321 more_than = (less_than < 0 ? 1 : 0);
324 if (more_than >= less_than || less_than < 2)
325 error (EXIT_FAILURE, 0,
326 _("impossible selection criteria specified (%d < n < %d)"),
327 more_than, less_than);
329 /* Read input files, then filter, convert and merge messages. */
330 allow_duplicates = true;
332 result = catenate_msgdomain_list (file_list, input_syntax, to_code);
334 string_list_free (file_list);
336 /* Sorting the list of messages. */
338 msgdomain_list_sort_by_filepos (result);
339 else if (sort_by_msgid)
340 msgdomain_list_sort_by_msgid (result);
342 /* Write the PO file. */
343 msgdomain_list_print (result, output_file, output_syntax, force_po, false);
349 /* Display usage information and exit. */
353 if (status != EXIT_SUCCESS)
354 fprintf (stderr, _("Try '%s --help' for more information.\n"),
359 Usage: %s [OPTION] [INPUTFILE]...\n\
362 /* xgettext: no-wrap */
364 Find messages which are common to two or more of the specified PO files.\n\
365 By using the --more-than option, greater commonality may be requested\n\
366 before messages are printed. Conversely, the --less-than option may be\n\
367 used to specify less commonality before messages are printed (i.e.\n\
368 --less-than=2 will only print the unique messages). Translations,\n\
369 comments and extracted comments will be preserved, but only from the first\n\
370 PO file to define them. File positions from all PO files will be\n\
375 Mandatory arguments to long options are mandatory for short options too.\n"));
378 Input file location:\n"));
380 INPUTFILE ... input files\n"));
382 -f, --files-from=FILE get list of input files from FILE\n"));
384 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
386 If input file is -, standard input is read.\n"));
389 Output file location:\n"));
391 -o, --output-file=FILE write output to specified file\n"));
393 The results are written to standard output if no output file is specified\n\
397 Message selection:\n"));
399 -<, --less-than=NUMBER print messages with less than this many\n\
400 definitions, defaults to infinite if not set\n"));
402 ->, --more-than=NUMBER print messages with more than this many\n\
403 definitions, defaults to 1 if not set\n"));
405 -u, --unique shorthand for --less-than=2, requests\n\
406 that only unique messages be printed\n"));
409 Input file syntax:\n"));
411 -P, --properties-input input files are in Java .properties syntax\n"));
413 --stringtable-input input files are in NeXTstep/GNUstep .strings\n\
417 Output details:\n"));
419 --color use colors and other text attributes always\n\
420 --color=WHEN use colors and other text attributes if WHEN.\n\
421 WHEN may be 'always', 'never', 'auto', or 'html'.\n"));
423 --style=STYLEFILE specify CSS style rule file for --color\n"));
425 -e, --no-escape do not use C escapes in output (default)\n"));
427 -E, --escape use C escapes in output, no extended chars\n"));
429 --force-po write PO file even if empty\n"));
431 -i, --indent write the .po file using indented style\n"));
433 --no-location do not write '#: filename:line' lines\n"));
435 -n, --add-location generate '#: filename:line' lines (default)\n"));
437 --strict write out strict Uniforum conforming .po file\n"));
439 -p, --properties-output write out a Java .properties file\n"));
441 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
443 -w, --width=NUMBER set output page width\n"));
445 --no-wrap do not break long message lines, longer than\n\
446 the output page width, into several lines\n"));
448 -s, --sort-output generate sorted output\n"));
450 -F, --sort-by-file sort output by file location\n"));
452 --omit-header don't write header with 'msgid \"\"' entry\n"));
455 Informative output:\n"));
457 -h, --help display this help and exit\n"));
459 -V, --version output version information and exit\n"));
461 /* TRANSLATORS: The placeholder indicates the bug-reporting address
462 for this package. Please add _another line_ saying
463 "Report translation bugs to <...>\n" with the address for translation
464 bugs (typically your translation team's web or email address). */
465 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),