No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / src / msgcat.c
blobc58385c5143ae256ce584dff8368f887399dba16
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)
8 any later version.
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. */
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include <getopt.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <locale.h>
30 #include "closeout.h"
31 #include "dir-list.h"
32 #include "str-list.h"
33 #include "file-list.h"
34 #include "error.h"
35 #include "error-progname.h"
36 #include "progname.h"
37 #include "relocatable.h"
38 #include "basename.h"
39 #include "message.h"
40 #include "read-po.h"
41 #include "write-po.h"
42 #include "msgl-cat.h"
43 #include "exit.h"
44 #include "gettext.h"
46 #define _(str) gettext (str)
49 /* Force output of PO file even if empty. */
50 static int force_po;
52 /* Target encoding. */
53 static const char *to_code;
55 /* Long options. */
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, '<', },
83 { NULL, 0, NULL, 0 }
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))
91 #endif
95 int
96 main (int argc, char **argv)
98 int cnt;
99 int optchar;
100 bool do_help;
101 bool do_version;
102 char *output_file;
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, "");
117 #endif
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. */
127 do_help = false;
128 do_version = false;
129 output_file = NULL;
130 files_from = NULL;
131 more_than = 0;
132 less_than = INT_MAX;
133 use_first = false;
135 while ((optchar = getopt_long (argc, argv, "<:>:D:eEf:Fhino:pPst:uVw:",
136 long_options, NULL)) != EOF)
137 switch (optchar)
139 case '\0': /* Long option. */
140 break;
142 case '>':
144 int value;
145 char *endp;
146 value = strtol (optarg, &endp, 10);
147 if (endp != optarg)
148 more_than = value;
150 break;
152 case '<':
154 int value;
155 char *endp;
156 value = strtol (optarg, &endp, 10);
157 if (endp != optarg)
158 less_than = value;
160 break;
162 case 'D':
163 dir_list_append (optarg);
164 break;
166 case 'e':
167 message_print_style_escape (false);
168 break;
170 case 'E':
171 message_print_style_escape (true);
172 break;
174 case 'f':
175 files_from = optarg;
176 break;
178 case 'F':
179 sort_by_filepos = true;
180 break;
182 case 'h':
183 do_help = true;
184 break;
186 case 'i':
187 message_print_style_indent ();
188 break;
190 case 'n':
191 line_comment = 1;
192 break;
194 case 'o':
195 output_file = optarg;
196 break;
198 case 'p':
199 message_print_syntax_properties ();
200 output_syntax = syntax_properties;
201 break;
203 case 'P':
204 input_syntax = syntax_properties;
205 break;
207 case 's':
208 sort_by_msgid = true;
209 break;
211 case 'S':
212 message_print_style_uniforum ();
213 break;
215 case 't':
216 to_code = optarg;
217 break;
219 case 'u':
220 less_than = 2;
221 break;
223 case 'V':
224 do_version = true;
225 break;
227 case 'w':
229 int value;
230 char *endp;
231 value = strtol (optarg, &endp, 10);
232 if (endp != optarg)
233 message_page_width_set (value);
235 break;
237 case CHAR_MAX + 1:
238 use_first = true;
239 break;
241 case CHAR_MAX + 2: /* --no-wrap */
242 message_page_width_ignore ();
243 break;
245 case CHAR_MAX + 3: /* --stringtable-input */
246 input_syntax = syntax_stringtable;
247 break;
249 case CHAR_MAX + 4: /* --stringtable-output */
250 message_print_syntax_stringtable ();
251 break;
253 default:
254 usage (EXIT_FAILURE);
255 /* NOTREACHED */
258 /* Version information requested. */
259 if (do_version)
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\
267 "2001-2005");
268 printf (_("Written by %s.\n"), "Bruno Haible");
269 exit (EXIT_SUCCESS);
272 /* Help is requested. */
273 if (do_help)
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);
294 else
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
304 ? to_code
305 : "UTF-8");
307 string_list_free (file_list);
309 /* Sorting the list of messages. */
310 if (sort_by_filepos)
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);
318 exit (EXIT_SUCCESS);
322 /* Display usage information and exit. */
323 static void
324 usage (int status)
326 if (status != EXIT_SUCCESS)
327 fprintf (stderr, _("Try `%s --help' for more information.\n"),
328 program_name);
329 else
331 printf (_("\
332 Usage: %s [OPTION] [INPUTFILE]...\n\
333 "), program_name);
334 printf ("\n");
335 /* xgettext: no-wrap */
336 printf (_("\
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\
346 "));
347 printf ("\n");
348 printf (_("\
349 Mandatory arguments to long options are mandatory for short options too.\n"));
350 printf ("\n");
351 printf (_("\
352 Input file location:\n"));
353 printf (_("\
354 INPUTFILE ... input files\n"));
355 printf (_("\
356 -f, --files-from=FILE get list of input files from FILE\n"));
357 printf (_("\
358 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
359 printf (_("\
360 If input file is -, standard input is read.\n"));
361 printf ("\n");
362 printf (_("\
363 Output file location:\n"));
364 printf (_("\
365 -o, --output-file=FILE write output to specified file\n"));
366 printf (_("\
367 The results are written to standard output if no output file is specified\n\
368 or if it is -.\n"));
369 printf ("\n");
370 printf (_("\
371 Message selection:\n"));
372 printf (_("\
373 -<, --less-than=NUMBER print messages with less than this many\n\
374 definitions, defaults to infinite if not set\n"));
375 printf (_("\
376 ->, --more-than=NUMBER print messages with more than this many\n\
377 definitions, defaults to 0 if not set\n"));
378 printf (_("\
379 -u, --unique shorthand for --less-than=2, requests\n\
380 that only unique messages be printed\n"));
381 printf ("\n");
382 printf (_("\
383 Input file syntax:\n"));
384 printf (_("\
385 -P, --properties-input input files are in Java .properties syntax\n"));
386 printf (_("\
387 --stringtable-input input files are in NeXTstep/GNUstep .strings\n\
388 syntax\n"));
389 printf ("\n");
390 printf (_("\
391 Output details:\n"));
392 printf (_("\
393 -t, --to-code=NAME encoding for output\n"));
394 printf (_("\
395 --use-first use first available translation for each\n\
396 message, don't merge several translations\n"));
397 printf (_("\
398 -e, --no-escape do not use C escapes in output (default)\n"));
399 printf (_("\
400 -E, --escape use C escapes in output, no extended chars\n"));
401 printf (_("\
402 --force-po write PO file even if empty\n"));
403 printf (_("\
404 -i, --indent write the .po file using indented style\n"));
405 printf (_("\
406 --no-location do not write '#: filename:line' lines\n"));
407 printf (_("\
408 -n, --add-location generate '#: filename:line' lines (default)\n"));
409 printf (_("\
410 --strict write out strict Uniforum conforming .po file\n"));
411 printf (_("\
412 -p, --properties-output write out a Java .properties file\n"));
413 printf (_("\
414 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
415 printf (_("\
416 -w, --width=NUMBER set output page width\n"));
417 printf (_("\
418 --no-wrap do not break long message lines, longer than\n\
419 the output page width, into several lines\n"));
420 printf (_("\
421 -s, --sort-output generate sorted output\n"));
422 printf (_("\
423 -F, --sort-by-file sort output by file location\n"));
424 printf ("\n");
425 printf (_("\
426 Informative output:\n"));
427 printf (_("\
428 -h, --help display this help and exit\n"));
429 printf (_("\
430 -V, --version output version information and exit\n"));
431 printf ("\n");
432 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
433 stdout);
436 exit (status);