1*946379e7Schristos /* Manipulates attributes of messages in translation catalogs.
2*946379e7Schristos Copyright (C) 2001-2006 Free Software Foundation, Inc.
3*946379e7Schristos Written by Bruno Haible <haible@clisp.cons.org>, 2001.
4*946379e7Schristos
5*946379e7Schristos This program is free software; you can redistribute it and/or modify
6*946379e7Schristos it under the terms of the GNU General Public License as published by
7*946379e7Schristos the Free Software Foundation; either version 2, or (at your option)
8*946379e7Schristos any later version.
9*946379e7Schristos
10*946379e7Schristos This program is distributed in the hope that it will be useful,
11*946379e7Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
12*946379e7Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*946379e7Schristos GNU General Public License for more details.
14*946379e7Schristos
15*946379e7Schristos You should have received a copy of the GNU General Public License
16*946379e7Schristos along with this program; if not, write to the Free Software Foundation,
17*946379e7Schristos Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18*946379e7Schristos
19*946379e7Schristos
20*946379e7Schristos #ifdef HAVE_CONFIG_H
21*946379e7Schristos # include "config.h"
22*946379e7Schristos #endif
23*946379e7Schristos
24*946379e7Schristos #include <getopt.h>
25*946379e7Schristos #include <limits.h>
26*946379e7Schristos #include <stdio.h>
27*946379e7Schristos #include <stdlib.h>
28*946379e7Schristos #include <locale.h>
29*946379e7Schristos
30*946379e7Schristos #include "closeout.h"
31*946379e7Schristos #include "dir-list.h"
32*946379e7Schristos #include "error.h"
33*946379e7Schristos #include "error-progname.h"
34*946379e7Schristos #include "progname.h"
35*946379e7Schristos #include "relocatable.h"
36*946379e7Schristos #include "basename.h"
37*946379e7Schristos #include "message.h"
38*946379e7Schristos #include "read-catalog.h"
39*946379e7Schristos #include "read-po.h"
40*946379e7Schristos #include "read-properties.h"
41*946379e7Schristos #include "read-stringtable.h"
42*946379e7Schristos #include "write-catalog.h"
43*946379e7Schristos #include "write-po.h"
44*946379e7Schristos #include "write-properties.h"
45*946379e7Schristos #include "write-stringtable.h"
46*946379e7Schristos #include "exit.h"
47*946379e7Schristos #include "propername.h"
48*946379e7Schristos #include "gettext.h"
49*946379e7Schristos
50*946379e7Schristos #define _(str) gettext (str)
51*946379e7Schristos
52*946379e7Schristos
53*946379e7Schristos /* Force output of PO file even if empty. */
54*946379e7Schristos static int force_po;
55*946379e7Schristos
56*946379e7Schristos /* Bit mask of subsets to remove. */
57*946379e7Schristos enum
58*946379e7Schristos {
59*946379e7Schristos REMOVE_UNTRANSLATED = 1 << 0,
60*946379e7Schristos REMOVE_TRANSLATED = 1 << 1,
61*946379e7Schristos REMOVE_FUZZY = 1 << 2,
62*946379e7Schristos REMOVE_NONFUZZY = 1 << 3,
63*946379e7Schristos REMOVE_OBSOLETE = 1 << 4,
64*946379e7Schristos REMOVE_NONOBSOLETE = 1 << 5
65*946379e7Schristos };
66*946379e7Schristos static int to_remove;
67*946379e7Schristos
68*946379e7Schristos /* Bit mask of actions to perform on all messages. */
69*946379e7Schristos enum
70*946379e7Schristos {
71*946379e7Schristos SET_FUZZY = 1 << 0,
72*946379e7Schristos RESET_FUZZY = 1 << 1,
73*946379e7Schristos SET_OBSOLETE = 1 << 2,
74*946379e7Schristos RESET_OBSOLETE = 1 << 3,
75*946379e7Schristos REMOVE_PREV = 1 << 4
76*946379e7Schristos };
77*946379e7Schristos static int to_change;
78*946379e7Schristos
79*946379e7Schristos /* Long options. */
80*946379e7Schristos static const struct option long_options[] =
81*946379e7Schristos {
82*946379e7Schristos { "add-location", no_argument, &line_comment, 1 },
83*946379e7Schristos { "clear-fuzzy", no_argument, NULL, CHAR_MAX + 8 },
84*946379e7Schristos { "clear-obsolete", no_argument, NULL, CHAR_MAX + 10 },
85*946379e7Schristos { "clear-previous", no_argument, NULL, CHAR_MAX + 18 },
86*946379e7Schristos { "directory", required_argument, NULL, 'D' },
87*946379e7Schristos { "escape", no_argument, NULL, 'E' },
88*946379e7Schristos { "force-po", no_argument, &force_po, 1 },
89*946379e7Schristos { "fuzzy", no_argument, NULL, CHAR_MAX + 11 },
90*946379e7Schristos { "help", no_argument, NULL, 'h' },
91*946379e7Schristos { "ignore-file", required_argument, NULL, CHAR_MAX + 15 },
92*946379e7Schristos { "indent", no_argument, NULL, 'i' },
93*946379e7Schristos { "no-escape", no_argument, NULL, 'e' },
94*946379e7Schristos { "no-fuzzy", no_argument, NULL, CHAR_MAX + 3 },
95*946379e7Schristos { "no-location", no_argument, &line_comment, 0 },
96*946379e7Schristos { "no-obsolete", no_argument, NULL, CHAR_MAX + 5 },
97*946379e7Schristos { "no-wrap", no_argument, NULL, CHAR_MAX + 13 },
98*946379e7Schristos { "obsolete", no_argument, NULL, CHAR_MAX + 12 },
99*946379e7Schristos { "only-file", required_argument, NULL, CHAR_MAX + 14 },
100*946379e7Schristos { "only-fuzzy", no_argument, NULL, CHAR_MAX + 4 },
101*946379e7Schristos { "only-obsolete", no_argument, NULL, CHAR_MAX + 6 },
102*946379e7Schristos { "output-file", required_argument, NULL, 'o' },
103*946379e7Schristos { "properties-input", no_argument, NULL, 'P' },
104*946379e7Schristos { "properties-output", no_argument, NULL, 'p' },
105*946379e7Schristos { "set-fuzzy", no_argument, NULL, CHAR_MAX + 7 },
106*946379e7Schristos { "set-obsolete", no_argument, NULL, CHAR_MAX + 9 },
107*946379e7Schristos { "sort-by-file", no_argument, NULL, 'F' },
108*946379e7Schristos { "sort-output", no_argument, NULL, 's' },
109*946379e7Schristos { "stringtable-input", no_argument, NULL, CHAR_MAX + 16 },
110*946379e7Schristos { "stringtable-output", no_argument, NULL, CHAR_MAX + 17 },
111*946379e7Schristos { "strict", no_argument, NULL, 'S' },
112*946379e7Schristos { "translated", no_argument, NULL, CHAR_MAX + 1 },
113*946379e7Schristos { "untranslated", no_argument, NULL, CHAR_MAX + 2 },
114*946379e7Schristos { "version", no_argument, NULL, 'V' },
115*946379e7Schristos { "width", required_argument, NULL, 'w', },
116*946379e7Schristos { NULL, 0, NULL, 0 }
117*946379e7Schristos };
118*946379e7Schristos
119*946379e7Schristos
120*946379e7Schristos /* Forward declaration of local functions. */
121*946379e7Schristos static void usage (int status)
122*946379e7Schristos #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
123*946379e7Schristos __attribute__ ((noreturn))
124*946379e7Schristos #endif
125*946379e7Schristos ;
126*946379e7Schristos static msgdomain_list_ty *process_msgdomain_list (msgdomain_list_ty *mdlp,
127*946379e7Schristos msgdomain_list_ty *only_mdlp,
128*946379e7Schristos msgdomain_list_ty *ignore_mdlp);
129*946379e7Schristos
130*946379e7Schristos
131*946379e7Schristos int
main(int argc,char ** argv)132*946379e7Schristos main (int argc, char **argv)
133*946379e7Schristos {
134*946379e7Schristos int optchar;
135*946379e7Schristos bool do_help;
136*946379e7Schristos bool do_version;
137*946379e7Schristos char *output_file;
138*946379e7Schristos const char *input_file;
139*946379e7Schristos const char *only_file;
140*946379e7Schristos const char *ignore_file;
141*946379e7Schristos msgdomain_list_ty *only_mdlp;
142*946379e7Schristos msgdomain_list_ty *ignore_mdlp;
143*946379e7Schristos msgdomain_list_ty *result;
144*946379e7Schristos catalog_input_format_ty input_syntax = &input_format_po;
145*946379e7Schristos catalog_output_format_ty output_syntax = &output_format_po;
146*946379e7Schristos bool sort_by_msgid = false;
147*946379e7Schristos bool sort_by_filepos = false;
148*946379e7Schristos
149*946379e7Schristos /* Set program name for messages. */
150*946379e7Schristos set_program_name (argv[0]);
151*946379e7Schristos error_print_progname = maybe_print_progname;
152*946379e7Schristos
153*946379e7Schristos #ifdef HAVE_SETLOCALE
154*946379e7Schristos /* Set locale via LC_ALL. */
155*946379e7Schristos setlocale (LC_ALL, "");
156*946379e7Schristos #endif
157*946379e7Schristos
158*946379e7Schristos /* Set the text message domain. */
159*946379e7Schristos bindtextdomain (PACKAGE, relocate (LOCALEDIR));
160*946379e7Schristos bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
161*946379e7Schristos textdomain (PACKAGE);
162*946379e7Schristos
163*946379e7Schristos /* Ensure that write errors on stdout are detected. */
164*946379e7Schristos atexit (close_stdout);
165*946379e7Schristos
166*946379e7Schristos /* Set default values for variables. */
167*946379e7Schristos do_help = false;
168*946379e7Schristos do_version = false;
169*946379e7Schristos output_file = NULL;
170*946379e7Schristos input_file = NULL;
171*946379e7Schristos only_file = NULL;
172*946379e7Schristos ignore_file = NULL;
173*946379e7Schristos
174*946379e7Schristos while ((optchar = getopt_long (argc, argv, "D:eEFhino:pPsVw:", long_options,
175*946379e7Schristos NULL)) != EOF)
176*946379e7Schristos switch (optchar)
177*946379e7Schristos {
178*946379e7Schristos case '\0': /* Long option. */
179*946379e7Schristos break;
180*946379e7Schristos
181*946379e7Schristos case 'D':
182*946379e7Schristos dir_list_append (optarg);
183*946379e7Schristos break;
184*946379e7Schristos
185*946379e7Schristos case 'e':
186*946379e7Schristos message_print_style_escape (false);
187*946379e7Schristos break;
188*946379e7Schristos
189*946379e7Schristos case 'E':
190*946379e7Schristos message_print_style_escape (true);
191*946379e7Schristos break;
192*946379e7Schristos
193*946379e7Schristos case 'F':
194*946379e7Schristos sort_by_filepos = true;
195*946379e7Schristos break;
196*946379e7Schristos
197*946379e7Schristos case 'h':
198*946379e7Schristos do_help = true;
199*946379e7Schristos break;
200*946379e7Schristos
201*946379e7Schristos case 'i':
202*946379e7Schristos message_print_style_indent ();
203*946379e7Schristos break;
204*946379e7Schristos
205*946379e7Schristos case 'n':
206*946379e7Schristos line_comment = 1;
207*946379e7Schristos break;
208*946379e7Schristos
209*946379e7Schristos case 'o':
210*946379e7Schristos output_file = optarg;
211*946379e7Schristos break;
212*946379e7Schristos
213*946379e7Schristos case 'p':
214*946379e7Schristos output_syntax = &output_format_properties;
215*946379e7Schristos break;
216*946379e7Schristos
217*946379e7Schristos case 'P':
218*946379e7Schristos input_syntax = &input_format_properties;
219*946379e7Schristos break;
220*946379e7Schristos
221*946379e7Schristos case 's':
222*946379e7Schristos sort_by_msgid = true;
223*946379e7Schristos break;
224*946379e7Schristos
225*946379e7Schristos case 'S':
226*946379e7Schristos message_print_style_uniforum ();
227*946379e7Schristos break;
228*946379e7Schristos
229*946379e7Schristos case 'V':
230*946379e7Schristos do_version = true;
231*946379e7Schristos break;
232*946379e7Schristos
233*946379e7Schristos case 'w':
234*946379e7Schristos {
235*946379e7Schristos int value;
236*946379e7Schristos char *endp;
237*946379e7Schristos value = strtol (optarg, &endp, 10);
238*946379e7Schristos if (endp != optarg)
239*946379e7Schristos message_page_width_set (value);
240*946379e7Schristos }
241*946379e7Schristos break;
242*946379e7Schristos
243*946379e7Schristos case CHAR_MAX + 1: /* --translated */
244*946379e7Schristos to_remove |= REMOVE_UNTRANSLATED;
245*946379e7Schristos break;
246*946379e7Schristos
247*946379e7Schristos case CHAR_MAX + 2: /* --untranslated */
248*946379e7Schristos to_remove |= REMOVE_TRANSLATED;
249*946379e7Schristos break;
250*946379e7Schristos
251*946379e7Schristos case CHAR_MAX + 3: /* --no-fuzzy */
252*946379e7Schristos to_remove |= REMOVE_FUZZY;
253*946379e7Schristos break;
254*946379e7Schristos
255*946379e7Schristos case CHAR_MAX + 4: /* --only-fuzzy */
256*946379e7Schristos to_remove |= REMOVE_NONFUZZY;
257*946379e7Schristos break;
258*946379e7Schristos
259*946379e7Schristos case CHAR_MAX + 5: /* --no-obsolete */
260*946379e7Schristos to_remove |= REMOVE_OBSOLETE;
261*946379e7Schristos break;
262*946379e7Schristos
263*946379e7Schristos case CHAR_MAX + 6: /* --only-obsolete */
264*946379e7Schristos to_remove |= REMOVE_NONOBSOLETE;
265*946379e7Schristos break;
266*946379e7Schristos
267*946379e7Schristos case CHAR_MAX + 7: /* --set-fuzzy */
268*946379e7Schristos to_change |= SET_FUZZY;
269*946379e7Schristos break;
270*946379e7Schristos
271*946379e7Schristos case CHAR_MAX + 8: /* --clear-fuzzy */
272*946379e7Schristos to_change |= RESET_FUZZY;
273*946379e7Schristos break;
274*946379e7Schristos
275*946379e7Schristos case CHAR_MAX + 9: /* --set-obsolete */
276*946379e7Schristos to_change |= SET_OBSOLETE;
277*946379e7Schristos break;
278*946379e7Schristos
279*946379e7Schristos case CHAR_MAX + 10: /* --clear-obsolete */
280*946379e7Schristos to_change |= RESET_OBSOLETE;
281*946379e7Schristos break;
282*946379e7Schristos
283*946379e7Schristos case CHAR_MAX + 11: /* --fuzzy */
284*946379e7Schristos to_remove |= REMOVE_NONFUZZY;
285*946379e7Schristos to_change |= RESET_FUZZY;
286*946379e7Schristos break;
287*946379e7Schristos
288*946379e7Schristos case CHAR_MAX + 12: /* --obsolete */
289*946379e7Schristos to_remove |= REMOVE_NONOBSOLETE;
290*946379e7Schristos to_change |= RESET_OBSOLETE;
291*946379e7Schristos break;
292*946379e7Schristos
293*946379e7Schristos case CHAR_MAX + 13: /* --no-wrap */
294*946379e7Schristos message_page_width_ignore ();
295*946379e7Schristos break;
296*946379e7Schristos
297*946379e7Schristos case CHAR_MAX + 14: /* --only-file */
298*946379e7Schristos only_file = optarg;
299*946379e7Schristos break;
300*946379e7Schristos
301*946379e7Schristos case CHAR_MAX + 15: /* --ignore-file */
302*946379e7Schristos ignore_file = optarg;
303*946379e7Schristos break;
304*946379e7Schristos
305*946379e7Schristos case CHAR_MAX + 16: /* --stringtable-input */
306*946379e7Schristos input_syntax = &input_format_stringtable;
307*946379e7Schristos break;
308*946379e7Schristos
309*946379e7Schristos case CHAR_MAX + 17: /* --stringtable-output */
310*946379e7Schristos output_syntax = &output_format_stringtable;
311*946379e7Schristos break;
312*946379e7Schristos
313*946379e7Schristos case CHAR_MAX + 18: /* --clear-previous */
314*946379e7Schristos to_change |= REMOVE_PREV;
315*946379e7Schristos break;
316*946379e7Schristos
317*946379e7Schristos default:
318*946379e7Schristos usage (EXIT_FAILURE);
319*946379e7Schristos /* NOTREACHED */
320*946379e7Schristos }
321*946379e7Schristos
322*946379e7Schristos /* Version information requested. */
323*946379e7Schristos if (do_version)
324*946379e7Schristos {
325*946379e7Schristos printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
326*946379e7Schristos /* xgettext: no-wrap */
327*946379e7Schristos printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
328*946379e7Schristos This is free software; see the source for copying conditions. There is NO\n\
329*946379e7Schristos warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
330*946379e7Schristos "),
331*946379e7Schristos "2001-2006");
332*946379e7Schristos printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
333*946379e7Schristos exit (EXIT_SUCCESS);
334*946379e7Schristos }
335*946379e7Schristos
336*946379e7Schristos /* Help is requested. */
337*946379e7Schristos if (do_help)
338*946379e7Schristos usage (EXIT_SUCCESS);
339*946379e7Schristos
340*946379e7Schristos /* Test whether we have an .po file name as argument. */
341*946379e7Schristos if (optind == argc)
342*946379e7Schristos input_file = "-";
343*946379e7Schristos else if (optind + 1 == argc)
344*946379e7Schristos input_file = argv[optind];
345*946379e7Schristos else
346*946379e7Schristos {
347*946379e7Schristos error (EXIT_SUCCESS, 0, _("at most one input file allowed"));
348*946379e7Schristos usage (EXIT_FAILURE);
349*946379e7Schristos }
350*946379e7Schristos
351*946379e7Schristos /* Verify selected options. */
352*946379e7Schristos if (!line_comment && sort_by_filepos)
353*946379e7Schristos error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
354*946379e7Schristos "--no-location", "--sort-by-file");
355*946379e7Schristos
356*946379e7Schristos if (sort_by_msgid && sort_by_filepos)
357*946379e7Schristos error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
358*946379e7Schristos "--sort-output", "--sort-by-file");
359*946379e7Schristos
360*946379e7Schristos /* Read input file. */
361*946379e7Schristos result = read_catalog_file (input_file, input_syntax);
362*946379e7Schristos
363*946379e7Schristos /* Read optional files that limit the extent of the attribute changes. */
364*946379e7Schristos only_mdlp = (only_file != NULL
365*946379e7Schristos ? read_catalog_file (only_file, input_syntax)
366*946379e7Schristos : NULL);
367*946379e7Schristos ignore_mdlp = (ignore_file != NULL
368*946379e7Schristos ? read_catalog_file (ignore_file, input_syntax)
369*946379e7Schristos : NULL);
370*946379e7Schristos
371*946379e7Schristos /* Filter the messages and manipulate the attributes. */
372*946379e7Schristos result = process_msgdomain_list (result, only_mdlp, ignore_mdlp);
373*946379e7Schristos
374*946379e7Schristos /* Sorting the list of messages. */
375*946379e7Schristos if (sort_by_filepos)
376*946379e7Schristos msgdomain_list_sort_by_filepos (result);
377*946379e7Schristos else if (sort_by_msgid)
378*946379e7Schristos msgdomain_list_sort_by_msgid (result);
379*946379e7Schristos
380*946379e7Schristos /* Write the PO file. */
381*946379e7Schristos msgdomain_list_print (result, output_file, output_syntax, force_po, false);
382*946379e7Schristos
383*946379e7Schristos exit (EXIT_SUCCESS);
384*946379e7Schristos }
385*946379e7Schristos
386*946379e7Schristos
387*946379e7Schristos /* Display usage information and exit. */
388*946379e7Schristos static void
usage(int status)389*946379e7Schristos usage (int status)
390*946379e7Schristos {
391*946379e7Schristos if (status != EXIT_SUCCESS)
392*946379e7Schristos fprintf (stderr, _("Try `%s --help' for more information.\n"),
393*946379e7Schristos program_name);
394*946379e7Schristos else
395*946379e7Schristos {
396*946379e7Schristos printf (_("\
397*946379e7Schristos Usage: %s [OPTION] [INPUTFILE]\n\
398*946379e7Schristos "), program_name);
399*946379e7Schristos printf ("\n");
400*946379e7Schristos /* xgettext: no-wrap */
401*946379e7Schristos printf (_("\
402*946379e7Schristos Filters the messages of a translation catalog according to their attributes,\n\
403*946379e7Schristos and manipulates the attributes.\n"));
404*946379e7Schristos printf ("\n");
405*946379e7Schristos printf (_("\
406*946379e7Schristos Mandatory arguments to long options are mandatory for short options too.\n"));
407*946379e7Schristos printf ("\n");
408*946379e7Schristos printf (_("\
409*946379e7Schristos Input file location:\n"));
410*946379e7Schristos printf (_("\
411*946379e7Schristos INPUTFILE input PO file\n"));
412*946379e7Schristos printf (_("\
413*946379e7Schristos -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n"));
414*946379e7Schristos printf (_("\
415*946379e7Schristos If no input file is given or if it is -, standard input is read.\n"));
416*946379e7Schristos printf ("\n");
417*946379e7Schristos printf (_("\
418*946379e7Schristos Output file location:\n"));
419*946379e7Schristos printf (_("\
420*946379e7Schristos -o, --output-file=FILE write output to specified file\n"));
421*946379e7Schristos printf (_("\
422*946379e7Schristos The results are written to standard output if no output file is specified\n\
423*946379e7Schristos or if it is -.\n"));
424*946379e7Schristos printf ("\n");
425*946379e7Schristos printf (_("\
426*946379e7Schristos Message selection:\n"));
427*946379e7Schristos printf (_("\
428*946379e7Schristos --translated keep translated, remove untranslated messages\n"));
429*946379e7Schristos printf (_("\
430*946379e7Schristos --untranslated keep untranslated, remove translated messages\n"));
431*946379e7Schristos printf (_("\
432*946379e7Schristos --no-fuzzy remove 'fuzzy' marked messages\n"));
433*946379e7Schristos printf (_("\
434*946379e7Schristos --only-fuzzy keep 'fuzzy' marked messages\n"));
435*946379e7Schristos printf (_("\
436*946379e7Schristos --no-obsolete remove obsolete #~ messages\n"));
437*946379e7Schristos printf (_("\
438*946379e7Schristos --only-obsolete keep obsolete #~ messages\n"));
439*946379e7Schristos printf ("\n");
440*946379e7Schristos printf (_("\
441*946379e7Schristos Attribute manipulation:\n"));
442*946379e7Schristos printf (_("\
443*946379e7Schristos --set-fuzzy set all messages 'fuzzy'\n"));
444*946379e7Schristos printf (_("\
445*946379e7Schristos --clear-fuzzy set all messages non-'fuzzy'\n"));
446*946379e7Schristos printf (_("\
447*946379e7Schristos --set-obsolete set all messages obsolete\n"));
448*946379e7Schristos printf (_("\
449*946379e7Schristos --clear-obsolete set all messages non-obsolete\n"));
450*946379e7Schristos printf (_("\
451*946379e7Schristos --clear-previous remove the \"previous msgid\" from all messages\n"));
452*946379e7Schristos printf (_("\
453*946379e7Schristos --only-file=FILE.po manipulate only entries listed in FILE.po\n"));
454*946379e7Schristos printf (_("\
455*946379e7Schristos --ignore-file=FILE.po manipulate only entries not listed in FILE.po\n"));
456*946379e7Schristos printf (_("\
457*946379e7Schristos --fuzzy synonym for --only-fuzzy --clear-fuzzy\n"));
458*946379e7Schristos printf (_("\
459*946379e7Schristos --obsolete synonym for --only-obsolete --clear-obsolete\n"));
460*946379e7Schristos printf ("\n");
461*946379e7Schristos printf (_("\
462*946379e7Schristos Input file syntax:\n"));
463*946379e7Schristos printf (_("\
464*946379e7Schristos -P, --properties-input input file is in Java .properties syntax\n"));
465*946379e7Schristos printf (_("\
466*946379e7Schristos --stringtable-input input file is in NeXTstep/GNUstep .strings syntax\n"));
467*946379e7Schristos printf ("\n");
468*946379e7Schristos printf (_("\
469*946379e7Schristos Output details:\n"));
470*946379e7Schristos printf (_("\
471*946379e7Schristos -e, --no-escape do not use C escapes in output (default)\n"));
472*946379e7Schristos printf (_("\
473*946379e7Schristos -E, --escape use C escapes in output, no extended chars\n"));
474*946379e7Schristos printf (_("\
475*946379e7Schristos --force-po write PO file even if empty\n"));
476*946379e7Schristos printf (_("\
477*946379e7Schristos -i, --indent write the .po file using indented style\n"));
478*946379e7Schristos printf (_("\
479*946379e7Schristos --no-location do not write '#: filename:line' lines\n"));
480*946379e7Schristos printf (_("\
481*946379e7Schristos -n, --add-location generate '#: filename:line' lines (default)\n"));
482*946379e7Schristos printf (_("\
483*946379e7Schristos --strict write out strict Uniforum conforming .po file\n"));
484*946379e7Schristos printf (_("\
485*946379e7Schristos -p, --properties-output write out a Java .properties file\n"));
486*946379e7Schristos printf (_("\
487*946379e7Schristos --stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
488*946379e7Schristos printf (_("\
489*946379e7Schristos -w, --width=NUMBER set output page width\n"));
490*946379e7Schristos printf (_("\
491*946379e7Schristos --no-wrap do not break long message lines, longer than\n\
492*946379e7Schristos the output page width, into several lines\n"));
493*946379e7Schristos printf (_("\
494*946379e7Schristos -s, --sort-output generate sorted output\n"));
495*946379e7Schristos printf (_("\
496*946379e7Schristos -F, --sort-by-file sort output by file location\n"));
497*946379e7Schristos printf ("\n");
498*946379e7Schristos printf (_("\
499*946379e7Schristos Informative output:\n"));
500*946379e7Schristos printf (_("\
501*946379e7Schristos -h, --help display this help and exit\n"));
502*946379e7Schristos printf (_("\
503*946379e7Schristos -V, --version output version information and exit\n"));
504*946379e7Schristos printf ("\n");
505*946379e7Schristos fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
506*946379e7Schristos stdout);
507*946379e7Schristos }
508*946379e7Schristos
509*946379e7Schristos exit (status);
510*946379e7Schristos }
511*946379e7Schristos
512*946379e7Schristos
513*946379e7Schristos /* Return true if a message should be kept. */
514*946379e7Schristos static bool
is_message_selected(const message_ty * mp)515*946379e7Schristos is_message_selected (const message_ty *mp)
516*946379e7Schristos {
517*946379e7Schristos /* Always keep the header entry. */
518*946379e7Schristos if (is_header (mp))
519*946379e7Schristos return true;
520*946379e7Schristos
521*946379e7Schristos if ((to_remove & (REMOVE_UNTRANSLATED | REMOVE_TRANSLATED))
522*946379e7Schristos && (mp->msgstr[0] == '\0'
523*946379e7Schristos ? to_remove & REMOVE_UNTRANSLATED
524*946379e7Schristos : to_remove & REMOVE_TRANSLATED))
525*946379e7Schristos return false;
526*946379e7Schristos
527*946379e7Schristos if ((to_remove & (REMOVE_FUZZY | REMOVE_NONFUZZY))
528*946379e7Schristos && (mp->is_fuzzy
529*946379e7Schristos ? to_remove & REMOVE_FUZZY
530*946379e7Schristos : to_remove & REMOVE_NONFUZZY))
531*946379e7Schristos return false;
532*946379e7Schristos
533*946379e7Schristos if ((to_remove & (REMOVE_OBSOLETE | REMOVE_NONOBSOLETE))
534*946379e7Schristos && (mp->obsolete
535*946379e7Schristos ? to_remove & REMOVE_OBSOLETE
536*946379e7Schristos : to_remove & REMOVE_NONOBSOLETE))
537*946379e7Schristos return false;
538*946379e7Schristos
539*946379e7Schristos return true;
540*946379e7Schristos }
541*946379e7Schristos
542*946379e7Schristos
543*946379e7Schristos static void
process_message_list(message_list_ty * mlp,message_list_ty * only_mlp,message_list_ty * ignore_mlp)544*946379e7Schristos process_message_list (message_list_ty *mlp,
545*946379e7Schristos message_list_ty *only_mlp, message_list_ty *ignore_mlp)
546*946379e7Schristos {
547*946379e7Schristos /* Keep only the selected messages. */
548*946379e7Schristos message_list_remove_if_not (mlp, is_message_selected);
549*946379e7Schristos
550*946379e7Schristos /* Change the attributes. */
551*946379e7Schristos if (to_change)
552*946379e7Schristos {
553*946379e7Schristos size_t j;
554*946379e7Schristos
555*946379e7Schristos for (j = 0; j < mlp->nitems; j++)
556*946379e7Schristos {
557*946379e7Schristos message_ty *mp = mlp->item[j];
558*946379e7Schristos
559*946379e7Schristos /* Attribute changes only affect messages listed in --only-file
560*946379e7Schristos and not listed in --ignore-file. */
561*946379e7Schristos if ((only_mlp
562*946379e7Schristos ? message_list_search (only_mlp, mp->msgctxt, mp->msgid) != NULL
563*946379e7Schristos : true)
564*946379e7Schristos && (ignore_mlp
565*946379e7Schristos ? message_list_search (ignore_mlp, mp->msgctxt, mp->msgid) == NULL
566*946379e7Schristos : true))
567*946379e7Schristos {
568*946379e7Schristos if (to_change & SET_FUZZY)
569*946379e7Schristos mp->is_fuzzy = true;
570*946379e7Schristos if (to_change & RESET_FUZZY)
571*946379e7Schristos mp->is_fuzzy = false;
572*946379e7Schristos /* Always keep the header entry non-obsolete. */
573*946379e7Schristos if ((to_change & SET_OBSOLETE) && !is_header (mp))
574*946379e7Schristos mp->obsolete = true;
575*946379e7Schristos if (to_change & RESET_OBSOLETE)
576*946379e7Schristos mp->obsolete = false;
577*946379e7Schristos if (to_change & REMOVE_PREV)
578*946379e7Schristos {
579*946379e7Schristos mp->prev_msgctxt = NULL;
580*946379e7Schristos mp->prev_msgid = NULL;
581*946379e7Schristos mp->prev_msgid_plural = NULL;
582*946379e7Schristos }
583*946379e7Schristos }
584*946379e7Schristos }
585*946379e7Schristos }
586*946379e7Schristos }
587*946379e7Schristos
588*946379e7Schristos
589*946379e7Schristos static msgdomain_list_ty *
process_msgdomain_list(msgdomain_list_ty * mdlp,msgdomain_list_ty * only_mdlp,msgdomain_list_ty * ignore_mdlp)590*946379e7Schristos process_msgdomain_list (msgdomain_list_ty *mdlp,
591*946379e7Schristos msgdomain_list_ty *only_mdlp,
592*946379e7Schristos msgdomain_list_ty *ignore_mdlp)
593*946379e7Schristos {
594*946379e7Schristos size_t k;
595*946379e7Schristos
596*946379e7Schristos for (k = 0; k < mdlp->nitems; k++)
597*946379e7Schristos process_message_list (mdlp->item[k]->messages,
598*946379e7Schristos only_mdlp
599*946379e7Schristos ? msgdomain_list_sublist (only_mdlp,
600*946379e7Schristos mdlp->item[k]->domain,
601*946379e7Schristos true)
602*946379e7Schristos : NULL,
603*946379e7Schristos ignore_mdlp
604*946379e7Schristos ? msgdomain_list_sublist (ignore_mdlp,
605*946379e7Schristos mdlp->item[k]->domain,
606*946379e7Schristos false)
607*946379e7Schristos : NULL);
608*946379e7Schristos
609*946379e7Schristos return mdlp;
610*946379e7Schristos }
611