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.  */
55static int force_po;
56
57/* Long options.  */
58static 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.  */
84static void usage (int status)
85#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
86	__attribute__ ((noreturn))
87#endif
88;
89
90
91int
92main (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\
214This is free software; see the source for copying conditions.  There is NO\n\
215warranty; 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.  */
267static void
268usage (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 (_("\
276Usage: %s [OPTION] INPUTFILE\n\
277"), program_name);
278      printf ("\n");
279      /* xgettext: no-wrap */
280      printf (_("\
281Creates an English translation catalog.  The input file is the last\n\
282created English PO file, or a PO Template file (generally created by\n\
283xgettext).  Untranslated entries are assigned a translation that is\n\
284identical to the msgid.\n\
285"));
286      printf ("\n");
287      printf (_("\
288Mandatory arguments to long options are mandatory for short options too.\n"));
289      printf ("\n");
290      printf (_("\
291Input 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 (_("\
297If input file is -, standard input is read.\n"));
298      printf ("\n");
299      printf (_("\
300Output file location:\n"));
301      printf (_("\
302  -o, --output-file=FILE      write output to specified file\n"));
303      printf (_("\
304The results are written to standard output if no output file is specified\n\
305or if it is -.\n"));
306      printf ("\n");
307      printf (_("\
308Input 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 (_("\
315Output 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 (_("\
345Informative 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