1 /* Creates an English translation catalog.
2 Copyright (C) 2001-2006 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
4
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.
9
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.
14
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <getopt.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <locale.h>
29
30 #include "closeout.h"
31 #include "dir-list.h"
32 #include "error.h"
33 #include "error-progname.h"
34 #include "progname.h"
35 #include "relocatable.h"
36 #include "basename.h"
37 #include "message.h"
38 #include "read-catalog.h"
39 #include "read-po.h"
40 #include "read-properties.h"
41 #include "read-stringtable.h"
42 #include "msgl-english.h"
43 #include "write-catalog.h"
44 #include "write-po.h"
45 #include "write-properties.h"
46 #include "write-stringtable.h"
47 #include "exit.h"
48 #include "propername.h"
49 #include "gettext.h"
50
51 #define _(str) gettext (str)
52
53
54 /* Force output of PO file even if empty. */
55 static int force_po;
56
57 /* Long options. */
58 static const struct option long_options[] =
59 {
60 { "add-location", no_argument, &line_comment, 1 },
61 { "directory", required_argument, NULL, 'D' },
62 { "escape", no_argument, NULL, 'E' },
63 { "force-po", no_argument, &force_po, 1 },
64 { "help", no_argument, NULL, 'h' },
65 { "indent", no_argument, NULL, 'i' },
66 { "no-escape", no_argument, NULL, 'e' },
67 { "no-location", no_argument, &line_comment, 0 },
68 { "no-wrap", no_argument, NULL, CHAR_MAX + 1 },
69 { "output-file", required_argument, NULL, 'o' },
70 { "properties-input", no_argument, NULL, 'P' },
71 { "properties-output", no_argument, NULL, 'p' },
72 { "sort-by-file", no_argument, NULL, 'F' },
73 { "sort-output", no_argument, NULL, 's' },
74 { "strict", no_argument, NULL, 'S' },
75 { "stringtable-input", no_argument, NULL, CHAR_MAX + 2 },
76 { "stringtable-output", no_argument, NULL, CHAR_MAX + 3 },
77 { "version", no_argument, NULL, 'V' },
78 { "width", required_argument, NULL, 'w', },
79 { NULL, 0, NULL, 0 }
80 };
81
82
83 /* Forward declaration of local functions. */
84 static void usage (int status)
85 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
86 __attribute__ ((noreturn))
87 #endif
88 ;
89
90
91 int
main(int argc,char ** argv)92 main (int argc, char **argv)
93 {
94 int opt;
95 bool do_help;
96 bool do_version;
97 char *output_file;
98 msgdomain_list_ty *result;
99 catalog_input_format_ty input_syntax = &input_format_po;
100 catalog_output_format_ty output_syntax = &output_format_po;
101 bool sort_by_filepos = false;
102 bool sort_by_msgid = false;
103
104 /* Set program name for messages. */
105 set_program_name (argv[0]);
106 error_print_progname = maybe_print_progname;
107
108 #ifdef HAVE_SETLOCALE
109 /* Set locale via LC_ALL. */
110 setlocale (LC_ALL, "");
111 #endif
112
113 /* Set the text message domain. */
114 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
115 bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
116 textdomain (PACKAGE);
117
118 /* Ensure that write errors on stdout are detected. */
119 atexit (close_stdout);
120
121 /* Set default values for variables. */
122 do_help = false;
123 do_version = false;
124 output_file = NULL;
125
126 while ((opt = getopt_long (argc, argv, "D:eEFhio:pPsVw:", long_options, NULL))
127 != EOF)
128 switch (opt)
129 {
130 case '\0': /* Long option. */
131 break;
132
133 case 'D':
134 dir_list_append (optarg);
135 break;
136
137 case 'e':
138 message_print_style_escape (false);
139 break;
140
141 case 'E':
142 message_print_style_escape (true);
143 break;
144
145 case 'F':
146 sort_by_filepos = true;
147 break;
148
149 case 'h':
150 do_help = true;
151 break;
152
153 case 'i':
154 message_print_style_indent ();
155 break;
156
157 case 'o':
158 output_file = optarg;
159 break;
160
161 case 'p':
162 output_syntax = &output_format_properties;
163 break;
164
165 case 'P':
166 input_syntax = &input_format_properties;
167 break;
168
169 case 's':
170 sort_by_msgid = true;
171 break;
172
173 case 'S':
174 message_print_style_uniforum ();
175 break;
176
177 case 'V':
178 do_version = true;
179 break;
180
181 case 'w':
182 {
183 int value;
184 char *endp;
185 value = strtol (optarg, &endp, 10);
186 if (endp != optarg)
187 message_page_width_set (value);
188 }
189 break;
190
191 case CHAR_MAX + 1: /* --no-wrap */
192 message_page_width_ignore ();
193 break;
194
195 case CHAR_MAX + 2: /* --stringtable-input */
196 input_syntax = &input_format_stringtable;
197 break;
198
199 case CHAR_MAX + 3: /* --stringtable-output */
200 output_syntax = &output_format_stringtable;
201 break;
202
203 default:
204 usage (EXIT_FAILURE);
205 break;
206 }
207
208 /* Version information is requested. */
209 if (do_version)
210 {
211 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
212 /* xgettext: no-wrap */
213 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
214 This is free software; see the source for copying conditions. There is NO\n\
215 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
216 "),
217 "2001-2006");
218 printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
219 exit (EXIT_SUCCESS);
220 }
221
222 /* Help is requested. */
223 if (do_help)
224 usage (EXIT_SUCCESS);
225
226 /* Test whether we have an .po file name as argument. */
227 if (optind >= argc)
228 {
229 error (EXIT_SUCCESS, 0, _("no input file given"));
230 usage (EXIT_FAILURE);
231 }
232 if (optind + 1 != argc)
233 {
234 error (EXIT_SUCCESS, 0, _("exactly one input file required"));
235 usage (EXIT_FAILURE);
236 }
237
238 /* Verify selected options. */
239 if (!line_comment && sort_by_filepos)
240 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
241 "--no-location", "--sort-by-file");
242
243 if (sort_by_msgid && sort_by_filepos)
244 error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
245 "--sort-output", "--sort-by-file");
246
247 /* Read input file. */
248 result = read_catalog_file (argv[optind], input_syntax);
249
250 /* Add English translations. */
251 result = msgdomain_list_english (result);
252
253 /* Sort the results. */
254 if (sort_by_filepos)
255 msgdomain_list_sort_by_filepos (result);
256 else if (sort_by_msgid)
257 msgdomain_list_sort_by_msgid (result);
258
259 /* Write the merged message list out. */
260 msgdomain_list_print (result, output_file, output_syntax, force_po, false);
261
262 exit (EXIT_SUCCESS);
263 }
264
265
266 /* Display usage information and exit. */
267 static void
usage(int status)268 usage (int status)
269 {
270 if (status != EXIT_SUCCESS)
271 fprintf (stderr, _("Try `%s --help' for more information.\n"),
272 program_name);
273 else
274 {
275 printf (_("\
276 Usage: %s [OPTION] INPUTFILE\n\
277 "), program_name);
278 printf ("\n");
279 /* xgettext: no-wrap */
280 printf (_("\
281 Creates an English translation catalog. The input file is the last\n\
282 created English PO file, or a PO Template file (generally created by\n\
283 xgettext). Untranslated entries are assigned a translation that is\n\
284 identical to the msgid.\n\
285 "));
286 printf ("\n");
287 printf (_("\
288 Mandatory arguments to long options are mandatory for short options too.\n"));
289 printf ("\n");
290 printf (_("\
291 Input file location:\n"));
292 printf (_("\
293 INPUTFILE input PO or POT file\n"));
294 printf (_("\
295 -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
296 printf (_("\
297 If input file is -, standard input is read.\n"));
298 printf ("\n");
299 printf (_("\
300 Output file location:\n"));
301 printf (_("\
302 -o, --output-file=FILE write output to specified file\n"));
303 printf (_("\
304 The results are written to standard output if no output file is specified\n\
305 or if it is -.\n"));
306 printf ("\n");
307 printf (_("\
308 Input file syntax:\n"));
309 printf (_("\
310 -P, --properties-input input file is in Java .properties syntax\n"));
311 printf (_("\
312 --stringtable-input input file is in NeXTstep/GNUstep .strings syntax\n"));
313 printf ("\n");
314 printf (_("\
315 Output details:\n"));
316 printf (_("\
317 -e, --no-escape do not use C escapes in output (default)\n"));
318 printf (_("\
319 -E, --escape use C escapes in output, no extended chars\n"));
320 printf (_("\
321 --force-po write PO file even if empty\n"));
322 printf (_("\
323 -i, --indent indented output style\n"));
324 printf (_("\
325 --no-location suppress '#: filename:line' lines\n"));
326 printf (_("\
327 --add-location preserve '#: filename:line' lines (default)\n"));
328 printf (_("\
329 --strict strict Uniforum output style\n"));
330 printf (_("\
331 -p, --properties-output write out a Java .properties file\n"));
332 printf (_("\
333 --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
334 printf (_("\
335 -w, --width=NUMBER set output page width\n"));
336 printf (_("\
337 --no-wrap do not break long message lines, longer than\n\
338 the output page width, into several lines\n"));
339 printf (_("\
340 -s, --sort-output generate sorted output\n"));
341 printf (_("\
342 -F, --sort-by-file sort output by file location\n"));
343 printf ("\n");
344 printf (_("\
345 Informative output:\n"));
346 printf (_("\
347 -h, --help display this help and exit\n"));
348 printf (_("\
349 -V, --version output version information and exit\n"));
350 printf ("\n");
351 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
352 stdout);
353 }
354
355 exit (status);
356 }
357