1 /* Concatenates several translation catalogs.
2 Copyright (C) 2001-2005 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 #include "file-list.h"
35 #include "error-progname.h"
37 #include "relocatable.h"
46 #define _(str) gettext (str)
49 /* Force output of PO file even if empty. */
52 /* Target encoding. */
53 static const char *to_code
;
56 static const struct option long_options
[] =
58 { "add-location", no_argument
, &line_comment
, 1 },
59 { "directory", required_argument
, NULL
, 'D' },
60 { "escape", no_argument
, NULL
, 'E' },
61 { "files-from", required_argument
, NULL
, 'f' },
62 { "force-po", no_argument
, &force_po
, 1 },
63 { "help", no_argument
, NULL
, 'h' },
64 { "indent", no_argument
, NULL
, 'i' },
65 { "no-escape", no_argument
, NULL
, 'e' },
66 { "no-location", no_argument
, &line_comment
, 0 },
67 { "no-wrap", no_argument
, NULL
, CHAR_MAX
+ 2 },
68 { "output-file", required_argument
, NULL
, 'o' },
69 { "properties-input", no_argument
, NULL
, 'P' },
70 { "properties-output", no_argument
, NULL
, 'p' },
71 { "sort-by-file", no_argument
, NULL
, 'F' },
72 { "sort-output", no_argument
, NULL
, 's' },
73 { "strict", no_argument
, NULL
, 'S' },
74 { "stringtable-input", no_argument
, NULL
, CHAR_MAX
+ 3 },
75 { "stringtable-output", no_argument
, NULL
, CHAR_MAX
+ 4 },
76 { "to-code", required_argument
, NULL
, 't' },
77 { "unique", no_argument
, NULL
, 'u' },
78 { "use-first", no_argument
, NULL
, CHAR_MAX
+ 1 },
79 { "version", no_argument
, NULL
, 'V' },
80 { "width", required_argument
, NULL
, 'w', },
81 { "more-than", required_argument
, NULL
, '>', },
82 { "less-than", required_argument
, NULL
, '<', },
87 /* Forward declaration of local functions. */
88 static void usage (int status
)
89 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
90 __attribute__ ((noreturn
))
96 main (int argc
, char **argv
)
103 const char *files_from
;
104 string_list_ty
*file_list
;
105 msgdomain_list_ty
*result
;
106 input_syntax_ty output_syntax
= syntax_po
;
107 bool sort_by_msgid
= false;
108 bool sort_by_filepos
= false;
110 /* Set program name for messages. */
111 set_program_name (argv
[0]);
112 error_print_progname
= maybe_print_progname
;
114 #ifdef HAVE_SETLOCALE
115 /* Set locale via LC_ALL. */
116 setlocale (LC_ALL
, "");
119 /* Set the text message domain. */
120 bindtextdomain (PACKAGE
, relocate (LOCALEDIR
));
121 textdomain (PACKAGE
);
123 /* Ensure that write errors on stdout are detected. */
124 atexit (close_stdout
);
126 /* Set default values for variables. */
135 while ((optchar
= getopt_long (argc
, argv
, "<:>:D:eEf:Fhino:pPst:uVw:",
136 long_options
, NULL
)) != EOF
)
139 case '\0': /* Long option. */
146 value
= strtol (optarg
, &endp
, 10);
156 value
= strtol (optarg
, &endp
, 10);
163 dir_list_append (optarg
);
167 message_print_style_escape (false);
171 message_print_style_escape (true);
179 sort_by_filepos
= true;
187 message_print_style_indent ();
195 output_file
= optarg
;
199 message_print_syntax_properties ();
200 output_syntax
= syntax_properties
;
204 input_syntax
= syntax_properties
;
208 sort_by_msgid
= true;
212 message_print_style_uniforum ();
231 value
= strtol (optarg
, &endp
, 10);
233 message_page_width_set (value
);
241 case CHAR_MAX
+ 2: /* --no-wrap */
242 message_page_width_ignore ();
245 case CHAR_MAX
+ 3: /* --stringtable-input */
246 input_syntax
= syntax_stringtable
;
249 case CHAR_MAX
+ 4: /* --stringtable-output */
250 message_print_syntax_stringtable ();
254 usage (EXIT_FAILURE
);
258 /* Version information requested. */
261 printf ("%s (GNU %s) %s\n", basename (program_name
), PACKAGE
, VERSION
);
262 /* xgettext: no-wrap */
263 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
264 This is free software; see the source for copying conditions. There is NO\n\
265 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
268 printf (_("Written by %s.\n"), "Bruno Haible");
272 /* Help is requested. */
274 usage (EXIT_SUCCESS
);
276 /* Verify selected options. */
277 if (!line_comment
&& sort_by_filepos
)
278 error (EXIT_FAILURE
, 0, _("%s and %s are mutually exclusive"),
279 "--no-location", "--sort-by-file");
281 if (sort_by_msgid
&& sort_by_filepos
)
282 error (EXIT_FAILURE
, 0, _("%s and %s are mutually exclusive"),
283 "--sort-output", "--sort-by-file");
285 /* Check the message selection criteria for sanity. */
286 if (more_than
>= less_than
|| less_than
< 2)
287 error (EXIT_FAILURE
, 0,
288 _("impossible selection criteria specified (%d < n < %d)"),
289 more_than
, less_than
);
291 /* Determine list of files we have to process. */
292 if (files_from
!= NULL
)
293 file_list
= read_names_from_file (files_from
);
295 file_list
= string_list_alloc ();
296 /* Append names from command line. */
297 for (cnt
= optind
; cnt
< argc
; ++cnt
)
298 string_list_append_unique (file_list
, argv
[cnt
]);
300 /* Read input files, then filter, convert and merge messages. */
301 result
= catenate_msgdomain_list (file_list
,
302 output_syntax
!= syntax_properties
303 && output_syntax
!= syntax_stringtable
307 string_list_free (file_list
);
309 /* Sorting the list of messages. */
311 msgdomain_list_sort_by_filepos (result
);
312 else if (sort_by_msgid
)
313 msgdomain_list_sort_by_msgid (result
);
315 /* Write the PO file. */
316 msgdomain_list_print (result
, output_file
, force_po
, false);
322 /* Display usage information and exit. */
326 if (status
!= EXIT_SUCCESS
)
327 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
332 Usage: %s [OPTION] [INPUTFILE]...\n\
335 /* xgettext: no-wrap */
337 Concatenates and merges the specified PO files.\n\
338 Find messages which are common to two or more of the specified PO files.\n\
339 By using the --more-than option, greater commonality may be requested\n\
340 before messages are printed. Conversely, the --less-than option may be\n\
341 used to specify less commonality before messages are printed (i.e.\n\
342 --less-than=2 will only print the unique messages). Translations,\n\
343 comments and extract comments will be cumulated, except that if --use-first\n\
344 is specified, they will be taken from the first PO file to define them.\n\
345 File positions from all PO files will be cumulated.\n\
349 Mandatory arguments to long options are mandatory for short options too.\n"));
352 Input file location:\n"));
354 INPUTFILE ... input files\n"));
356 -f, --files-from=FILE get list of input files from FILE\n"));
358 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
360 If input file is -, standard input is read.\n"));
363 Output file location:\n"));
365 -o, --output-file=FILE write output to specified file\n"));
367 The results are written to standard output if no output file is specified\n\
371 Message selection:\n"));
373 -<, --less-than=NUMBER print messages with less than this many\n\
374 definitions, defaults to infinite if not set\n"));
376 ->, --more-than=NUMBER print messages with more than this many\n\
377 definitions, defaults to 0 if not set\n"));
379 -u, --unique shorthand for --less-than=2, requests\n\
380 that only unique messages be printed\n"));
383 Input file syntax:\n"));
385 -P, --properties-input input files are in Java .properties syntax\n"));
387 --stringtable-input input files are in NeXTstep/GNUstep .strings\n\
391 Output details:\n"));
393 -t, --to-code=NAME encoding for output\n"));
395 --use-first use first available translation for each\n\
396 message, don't merge several translations\n"));
398 -e, --no-escape do not use C escapes in output (default)\n"));
400 -E, --escape use C escapes in output, no extended chars\n"));
402 --force-po write PO file even if empty\n"));
404 -i, --indent write the .po file using indented style\n"));
406 --no-location do not write '#: filename:line' lines\n"));
408 -n, --add-location generate '#: filename:line' lines (default)\n"));
410 --strict write out strict Uniforum conforming .po file\n"));
412 -p, --properties-output write out a Java .properties file\n"));
414 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
416 -w, --width=NUMBER set output page width\n"));
418 --no-wrap do not break long message lines, longer than\n\
419 the output page width, into several lines\n"));
421 -s, --sort-output generate sorted output\n"));
423 -F, --sort-by-file sort output by file location\n"));
426 Informative output:\n"));
428 -h, --help display this help and exit\n"));
430 -V, --version output version information and exit\n"));
432 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),