No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / src / msguniq.c
blob00b11bcb46c4ae63b0fae709252e78f288dcc2bd
1 /* Remove, select or merge duplicate translations.
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 "error.h"
34 #include "error-progname.h"
35 #include "progname.h"
36 #include "relocatable.h"
37 #include "basename.h"
38 #include "message.h"
39 #include "read-po.h"
40 #include "write-po.h"
41 #include "msgl-cat.h"
42 #include "exit.h"
43 #include "gettext.h"
45 #define _(str) gettext (str)
48 /* Force output of PO file even if empty. */
49 static int force_po;
51 /* Target encoding. */
52 static const char *to_code;
54 /* Long options. */
55 static const struct option long_options[] =
57 { "add-location", no_argument, &line_comment, 1 },
58 { "directory", required_argument, NULL, 'D' },
59 { "escape", no_argument, NULL, 'E' },
60 { "force-po", no_argument, &force_po, 1 },
61 { "help", no_argument, NULL, 'h' },
62 { "indent", no_argument, NULL, 'i' },
63 { "no-escape", no_argument, NULL, 'e' },
64 { "no-location", no_argument, &line_comment, 0 },
65 { "no-wrap", no_argument, NULL, CHAR_MAX + 2 },
66 { "output-file", required_argument, NULL, 'o' },
67 { "properties-input", no_argument, NULL, 'P' },
68 { "properties-output", no_argument, NULL, 'p' },
69 { "repeated", no_argument, NULL, 'd' },
70 { "sort-by-file", no_argument, NULL, 'F' },
71 { "sort-output", no_argument, NULL, 's' },
72 { "strict", no_argument, NULL, 'S' },
73 { "stringtable-input", no_argument, NULL, CHAR_MAX + 3 },
74 { "stringtable-output", no_argument, NULL, CHAR_MAX + 4 },
75 { "to-code", required_argument, NULL, 't' },
76 { "unique", no_argument, NULL, 'u' },
77 { "use-first", no_argument, NULL, CHAR_MAX + 1 },
78 { "version", no_argument, NULL, 'V' },
79 { "width", required_argument, NULL, 'w', },
80 { NULL, 0, NULL, 0 }
84 /* Forward declaration of local functions. */
85 static void usage (int status)
86 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
87 __attribute__ ((noreturn))
88 #endif
92 int
93 main (int argc, char **argv)
95 int optchar;
96 bool do_help;
97 bool do_version;
98 char *output_file;
99 const char *input_file;
100 string_list_ty *file_list;
101 msgdomain_list_ty *result;
102 bool sort_by_msgid = false;
103 bool sort_by_filepos = false;
105 /* Set program name for messages. */
106 set_program_name (argv[0]);
107 error_print_progname = maybe_print_progname;
109 #ifdef HAVE_SETLOCALE
110 /* Set locale via LC_ALL. */
111 setlocale (LC_ALL, "");
112 #endif
114 /* Set the text message domain. */
115 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
116 textdomain (PACKAGE);
118 /* Ensure that write errors on stdout are detected. */
119 atexit (close_stdout);
121 /* Set default values for variables. */
122 do_help = false;
123 do_version = false;
124 output_file = NULL;
125 input_file = NULL;
126 more_than = 0;
127 less_than = INT_MAX;
128 use_first = false;
130 while ((optchar = getopt_long (argc, argv, "dD:eEFhino:pPst:uVw:",
131 long_options, NULL)) != EOF)
132 switch (optchar)
134 case '\0': /* Long option. */
135 break;
137 case 'd':
138 more_than = 1;
139 less_than = INT_MAX;
140 break;
142 case 'D':
143 dir_list_append (optarg);
144 break;
146 case 'e':
147 message_print_style_escape (false);
148 break;
150 case 'E':
151 message_print_style_escape (true);
152 break;
154 case 'F':
155 sort_by_filepos = true;
156 break;
158 case 'h':
159 do_help = true;
160 break;
162 case 'i':
163 message_print_style_indent ();
164 break;
166 case 'n':
167 line_comment = 1;
168 break;
170 case 'o':
171 output_file = optarg;
172 break;
174 case 'p':
175 message_print_syntax_properties ();
176 break;
178 case 'P':
179 input_syntax = syntax_properties;
180 break;
182 case 's':
183 sort_by_msgid = true;
184 break;
186 case 'S':
187 message_print_style_uniforum ();
188 break;
190 case 't':
191 to_code = optarg;
192 break;
194 case 'u':
195 more_than = 0;
196 less_than = 2;
197 break;
199 case 'V':
200 do_version = true;
201 break;
203 case 'w':
205 int value;
206 char *endp;
207 value = strtol (optarg, &endp, 10);
208 if (endp != optarg)
209 message_page_width_set (value);
211 break;
213 case CHAR_MAX + 1:
214 use_first = true;
215 break;
217 case CHAR_MAX + 2: /* --no-wrap */
218 message_page_width_ignore ();
219 break;
221 case CHAR_MAX + 3: /* --stringtable-input */
222 input_syntax = syntax_stringtable;
223 break;
225 case CHAR_MAX + 4: /* --stringtable-output */
226 message_print_syntax_stringtable ();
227 break;
229 default:
230 usage (EXIT_FAILURE);
231 /* NOTREACHED */
234 /* Version information requested. */
235 if (do_version)
237 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
238 /* xgettext: no-wrap */
239 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
240 This is free software; see the source for copying conditions. There is NO\n\
241 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
243 "2001-2005");
244 printf (_("Written by %s.\n"), "Bruno Haible");
245 exit (EXIT_SUCCESS);
248 /* Help is requested. */
249 if (do_help)
250 usage (EXIT_SUCCESS);
252 /* Test whether we have an .po file name as argument. */
253 if (optind == argc)
254 input_file = "-";
255 else if (optind + 1 == argc)
256 input_file = argv[optind];
257 else
259 error (EXIT_SUCCESS, 0, _("at most one input file allowed"));
260 usage (EXIT_FAILURE);
263 /* Verify selected options. */
264 if (!line_comment && sort_by_filepos)
265 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
266 "--no-location", "--sort-by-file");
268 if (sort_by_msgid && sort_by_filepos)
269 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
270 "--sort-output", "--sort-by-file");
272 /* Determine list of files we have to process: a single file. */
273 file_list = string_list_alloc ();
274 string_list_append (file_list, input_file);
276 /* Read input files, then filter, convert and merge messages. */
277 allow_duplicates = true;
278 result = catenate_msgdomain_list (file_list, to_code);
280 string_list_free (file_list);
282 /* Sorting the list of messages. */
283 if (sort_by_filepos)
284 msgdomain_list_sort_by_filepos (result);
285 else if (sort_by_msgid)
286 msgdomain_list_sort_by_msgid (result);
288 /* Write the PO file. */
289 msgdomain_list_print (result, output_file, force_po, false);
291 exit (EXIT_SUCCESS);
295 /* Display usage information and exit. */
296 static void
297 usage (int status)
299 if (status != EXIT_SUCCESS)
300 fprintf (stderr, _("Try `%s --help' for more information.\n"),
301 program_name);
302 else
304 printf (_("\
305 Usage: %s [OPTION] [INPUTFILE]\n\
306 "), program_name);
307 printf ("\n");
308 /* xgettext: no-wrap */
309 printf (_("\
310 Unifies duplicate translations in a translation catalog.\n\
311 Finds duplicate translations of the same message ID. Such duplicates are\n\
312 invalid input for other programs like msgfmt, msgmerge or msgcat. By\n\
313 default, duplicates are merged together. When using the --repeated option,\n\
314 only duplicates are output, and all other messages are discarded. Comments\n\
315 and extracted comments will be cumulated, except that if --use-first is\n\
316 specified, they will be taken from the first translation. File positions\n\
317 will be cumulated. When using the --unique option, duplicates are discarded.\n\
318 "));
319 printf ("\n");
320 printf (_("\
321 Mandatory arguments to long options are mandatory for short options too.\n"));
322 printf ("\n");
323 printf (_("\
324 Input file location:\n"));
325 printf (_("\
326 INPUTFILE input PO file\n"));
327 printf (_("\
328 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
329 printf (_("\
330 If no input file is given or if it is -, standard input is read.\n"));
331 printf ("\n");
332 printf (_("\
333 Output file location:\n"));
334 printf (_("\
335 -o, --output-file=FILE write output to specified file\n"));
336 printf (_("\
337 The results are written to standard output if no output file is specified\n\
338 or if it is -.\n"));
339 printf ("\n");
340 printf (_("\
341 Message selection:\n"));
342 printf (_("\
343 -d, --repeated print only duplicates\n"));
344 printf (_("\
345 -u, --unique print only unique messages, discard duplicates\n"));
346 printf ("\n");
347 printf (_("\
348 Input file syntax:\n"));
349 printf (_("\
350 -P, --properties-input input file is in Java .properties syntax\n"));
351 printf (_("\
352 --stringtable-input input file is in NeXTstep/GNUstep .strings syntax\n"));
353 printf ("\n");
354 printf (_("\
355 Output details:\n"));
356 printf (_("\
357 -t, --to-code=NAME encoding for output\n"));
358 printf (_("\
359 --use-first use first available translation for each\n\
360 message, don't merge several translations\n"));
361 printf (_("\
362 -e, --no-escape do not use C escapes in output (default)\n"));
363 printf (_("\
364 -E, --escape use C escapes in output, no extended chars\n"));
365 printf (_("\
366 --force-po write PO file even if empty\n"));
367 printf (_("\
368 -i, --indent write the .po file using indented style\n"));
369 printf (_("\
370 --no-location do not write '#: filename:line' lines\n"));
371 printf (_("\
372 -n, --add-location generate '#: filename:line' lines (default)\n"));
373 printf (_("\
374 --strict write out strict Uniforum conforming .po file\n"));
375 printf (_("\
376 -p, --properties-output write out a Java .properties file\n"));
377 printf (_("\
378 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
379 printf (_("\
380 -w, --width=NUMBER set output page width\n"));
381 printf (_("\
382 --no-wrap do not break long message lines, longer than\n\
383 the output page width, into several lines\n"));
384 printf (_("\
385 -s, --sort-output generate sorted output\n"));
386 printf (_("\
387 -F, --sort-by-file sort output by file location\n"));
388 printf ("\n");
389 printf (_("\
390 Informative output:\n"));
391 printf (_("\
392 -h, --help display this help and exit\n"));
393 printf (_("\
394 -V, --version output version information and exit\n"));
395 printf ("\n");
396 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
397 stdout);
400 exit (status);