xref: /netbsd-src/external/gpl2/gettext/dist/gettext-tools/src/msgattrib.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
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