1 /* GNU gettext - internationalization aids
2 Copyright (C) 1997-1998, 2000-2005 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 2, or (at your option)
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, write to the Free Software Foundation,
18 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"
47 /* A convenience macro. I don't like writing gettext() every time. */
48 #define _(str) gettext (str)
51 /* Force output of PO file even if empty. */
54 /* Target encoding. */
55 static const char *to_code
;
58 static const struct option long_options
[] =
60 { "add-location", no_argument
, &line_comment
, 1 },
61 { "directory", required_argument
, NULL
, 'D' },
62 { "escape", no_argument
, NULL
, 'E' },
63 { "files-from", required_argument
, NULL
, 'f' },
64 { "force-po", no_argument
, &force_po
, 1 },
65 { "help", no_argument
, NULL
, 'h' },
66 { "indent", no_argument
, NULL
, 'i' },
67 { "no-escape", no_argument
, NULL
, 'e' },
68 { "no-location", no_argument
, &line_comment
, 0 },
69 { "no-wrap", no_argument
, NULL
, CHAR_MAX
+ 2 },
70 { "omit-header", no_argument
, NULL
, CHAR_MAX
+ 1 },
71 { "output", required_argument
, NULL
, 'o' }, /* for backward compatibility */
72 { "output-file", required_argument
, NULL
, 'o' },
73 { "properties-input", no_argument
, NULL
, 'P' },
74 { "properties-output", no_argument
, NULL
, 'p' },
75 { "sort-by-file", no_argument
, NULL
, 'F' },
76 { "sort-output", no_argument
, NULL
, 's' },
77 { "strict", no_argument
, NULL
, 'S' },
78 { "stringtable-input", no_argument
, NULL
, CHAR_MAX
+ 3 },
79 { "stringtable-output", no_argument
, NULL
, CHAR_MAX
+ 4 },
80 { "to-code", required_argument
, NULL
, 't' },
81 { "unique", no_argument
, NULL
, 'u' },
82 { "version", no_argument
, NULL
, 'V' },
83 { "width", required_argument
, NULL
, 'w', },
84 { "more-than", required_argument
, NULL
, '>', },
85 { "less-than", required_argument
, NULL
, '<', },
90 /* Forward declaration of local functions. */
91 static void usage (int status
)
92 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ > 4) || __GNUC__ > 2)
93 __attribute__ ((noreturn
))
99 main (int argc
, char *argv
[])
103 bool do_help
= false;
104 bool do_version
= false;
105 msgdomain_list_ty
*result
;
106 bool sort_by_msgid
= false;
107 bool sort_by_filepos
= false;
108 const char *files_from
= NULL
;
109 string_list_ty
*file_list
;
110 char *output_file
= NULL
;
112 /* Set program name for messages. */
113 set_program_name (argv
[0]);
114 error_print_progname
= maybe_print_progname
;
116 #ifdef HAVE_SETLOCALE
117 /* Set locale via LC_ALL. */
118 setlocale (LC_ALL
, "");
121 /* Set the text message domain. */
122 bindtextdomain (PACKAGE
, relocate (LOCALEDIR
));
123 textdomain (PACKAGE
);
125 /* Ensure that write errors on stdout are detected. */
126 atexit (close_stdout
);
128 /* Set default values for variables. */
133 while ((optchar
= getopt_long (argc
, argv
, "<:>:D:eEf:Fhino:pPst:uVw:",
134 long_options
, NULL
)) != EOF
)
137 case '\0': /* Long option. */
144 value
= strtol (optarg
, &endp
, 10);
154 value
= strtol (optarg
, &endp
, 10);
161 dir_list_append (optarg
);
165 message_print_style_escape (false);
169 message_print_style_escape (true);
177 sort_by_filepos
= true;
185 message_print_style_indent ();
193 output_file
= optarg
;
197 message_print_syntax_properties ();
201 input_syntax
= syntax_properties
;
205 sort_by_msgid
= true;
209 message_print_style_uniforum ();
228 value
= strtol (optarg
, &endp
, 10);
230 message_page_width_set (value
);
238 case CHAR_MAX
+ 2: /* --no-wrap */
239 message_page_width_ignore ();
242 case CHAR_MAX
+ 3: /* --stringtable-input */
243 input_syntax
= syntax_stringtable
;
246 case CHAR_MAX
+ 4: /* --stringtable-output */
247 message_print_syntax_stringtable ();
251 usage (EXIT_FAILURE
);
255 /* Version information requested. */
258 printf ("%s (GNU %s) %s\n", basename (program_name
), PACKAGE
, VERSION
);
259 /* xgettext: no-wrap */
260 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
261 This is free software; see the source for copying conditions. There is NO\n\
262 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
264 "1995-1998, 2000-2005");
265 printf (_("Written by %s.\n"), "Peter Miller");
269 /* Help is requested. */
271 usage (EXIT_SUCCESS
);
273 /* Verify selected options. */
274 if (!line_comment
&& sort_by_filepos
)
275 error (EXIT_FAILURE
, 0, _("%s and %s are mutually exclusive"),
276 "--no-location", "--sort-by-file");
278 if (sort_by_msgid
&& sort_by_filepos
)
279 error (EXIT_FAILURE
, 0, _("%s and %s are mutually exclusive"),
280 "--sort-output", "--sort-by-file");
282 /* Determine list of files we have to process. */
283 if (files_from
!= NULL
)
284 file_list
= read_names_from_file (files_from
);
286 file_list
= string_list_alloc ();
287 /* Append names from command line. */
288 for (cnt
= optind
; cnt
< argc
; ++cnt
)
289 string_list_append_unique (file_list
, argv
[cnt
]);
291 /* Test whether sufficient input files were given. */
292 if (file_list
->nitems
< 2)
294 error (EXIT_SUCCESS
, 0, _("at least two files must be specified"));
295 usage (EXIT_FAILURE
);
298 /* Default the message selection criteria, and check them for sanity. */
300 more_than
= (less_than
< 0 ? 1 : 0);
303 if (more_than
>= less_than
|| less_than
< 2)
304 error (EXIT_FAILURE
, 0,
305 _("impossible selection criteria specified (%d < n < %d)"),
306 more_than
, less_than
);
308 /* Read input files, then filter, convert and merge messages. */
309 allow_duplicates
= true;
311 result
= catenate_msgdomain_list (file_list
, to_code
);
313 string_list_free (file_list
);
315 /* Sorting the list of messages. */
317 msgdomain_list_sort_by_filepos (result
);
318 else if (sort_by_msgid
)
319 msgdomain_list_sort_by_msgid (result
);
321 /* Write the PO file. */
322 msgdomain_list_print (result
, output_file
, force_po
, false);
328 /* Display usage information and exit. */
332 if (status
!= EXIT_SUCCESS
)
333 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
338 Usage: %s [OPTION] [INPUTFILE]...\n\
341 /* xgettext: no-wrap */
343 Find messages which are common to two or more of the specified PO files.\n\
344 By using the --more-than option, greater commonality may be requested\n\
345 before messages are printed. Conversely, the --less-than option may be\n\
346 used to specify less commonality before messages are printed (i.e.\n\
347 --less-than=2 will only print the unique messages). Translations,\n\
348 comments and extract comments will be preserved, but only from the first\n\
349 PO file to define them. File positions from all PO files will be\n\
354 Mandatory arguments to long options are mandatory for short options too.\n"));
357 Input file location:\n"));
359 INPUTFILE ... input files\n"));
361 -f, --files-from=FILE get list of input files from FILE\n"));
363 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
365 If input file is -, standard input is read.\n"));
368 Output file location:\n"));
370 -o, --output-file=FILE write output to specified file\n"));
372 The results are written to standard output if no output file is specified\n\
376 Message selection:\n"));
378 -<, --less-than=NUMBER print messages with less than this many\n\
379 definitions, defaults to infinite if not set\n"));
381 ->, --more-than=NUMBER print messages with more than this many\n\
382 definitions, defaults to 1 if not set\n"));
384 -u, --unique shorthand for --less-than=2, requests\n\
385 that only unique messages be printed\n"));
388 Input file syntax:\n"));
390 -P, --properties-input input files are in Java .properties syntax\n"));
392 --stringtable-input input files are in NeXTstep/GNUstep .strings\n\
396 Output details:\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"));
425 --omit-header don't write header with `msgid \"\"' entry\n"));
428 Informative output:\n"));
430 -h, --help display this help and exit\n"));
432 -V, --version output version information and exit\n"));
434 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),