mirror of
https://github.com/php-win-ext/gettext.git
synced 2026-04-29 03:53:18 +02:00
556 lines
16 KiB
C
556 lines
16 KiB
C
/* msgunfmt - converts binary .mo files to Uniforum style .po files
|
|
Copyright (C) 1995-1998, 2000-2007, 2009-2010, 2012 Free Software Foundation, Inc.
|
|
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <getopt.h>
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <locale.h>
|
|
|
|
#include "closeout.h"
|
|
#include "error.h"
|
|
#include "error-progname.h"
|
|
#include "progname.h"
|
|
#include "relocatable.h"
|
|
#include "basename.h"
|
|
#include "message.h"
|
|
#include "msgunfmt.h"
|
|
#include "read-mo.h"
|
|
#include "read-java.h"
|
|
#include "read-csharp.h"
|
|
#include "read-resources.h"
|
|
#include "read-tcl.h"
|
|
#include "write-catalog.h"
|
|
#include "write-po.h"
|
|
#include "write-properties.h"
|
|
#include "write-stringtable.h"
|
|
#include "color.h"
|
|
#include "propername.h"
|
|
#include "gettext.h"
|
|
|
|
#define _(str) gettext (str)
|
|
|
|
|
|
/* Be more verbose. */
|
|
bool verbose;
|
|
|
|
/* Java mode input file specification. */
|
|
static bool java_mode;
|
|
static const char *java_resource_name;
|
|
static const char *java_locale_name;
|
|
|
|
/* C# mode input file specification. */
|
|
static bool csharp_mode;
|
|
static const char *csharp_resource_name;
|
|
static const char *csharp_locale_name;
|
|
static const char *csharp_base_directory;
|
|
|
|
/* C# resources mode input file specification. */
|
|
static bool csharp_resources_mode;
|
|
|
|
/* Tcl mode input file specification. */
|
|
static bool tcl_mode;
|
|
static const char *tcl_locale_name;
|
|
static const char *tcl_base_directory;
|
|
|
|
/* Force output of PO file even if empty. */
|
|
static int force_po;
|
|
|
|
/* Long options. */
|
|
static const struct option long_options[] =
|
|
{
|
|
{ "color", optional_argument, NULL, CHAR_MAX + 6 },
|
|
{ "csharp", no_argument, NULL, CHAR_MAX + 4 },
|
|
{ "csharp-resources", no_argument, NULL, CHAR_MAX + 5 },
|
|
{ "escape", no_argument, NULL, 'E' },
|
|
{ "force-po", no_argument, &force_po, 1 },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "indent", no_argument, NULL, 'i' },
|
|
{ "java", no_argument, NULL, 'j' },
|
|
{ "locale", required_argument, NULL, 'l' },
|
|
{ "no-escape", no_argument, NULL, 'e' },
|
|
{ "no-wrap", no_argument, NULL, CHAR_MAX + 2 },
|
|
{ "output-file", required_argument, NULL, 'o' },
|
|
{ "properties-output", no_argument, NULL, 'p' },
|
|
{ "resource", required_argument, NULL, 'r' },
|
|
{ "sort-output", no_argument, NULL, 's' },
|
|
{ "strict", no_argument, NULL, 'S' },
|
|
{ "stringtable-output", no_argument, NULL, CHAR_MAX + 3 },
|
|
{ "style", required_argument, NULL, CHAR_MAX + 7 },
|
|
{ "tcl", no_argument, NULL, CHAR_MAX + 1 },
|
|
{ "verbose", no_argument, NULL, 'v' },
|
|
{ "version", no_argument, NULL, 'V' },
|
|
{ "width", required_argument, NULL, 'w', },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
|
|
/* Forward declaration of local functions. */
|
|
static void usage (int status)
|
|
#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
|
|
__attribute__ ((noreturn))
|
|
#endif
|
|
;
|
|
static void read_one_file (message_list_ty *mlp, const char *filename);
|
|
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
int optchar;
|
|
bool do_help = false;
|
|
bool do_version = false;
|
|
const char *output_file = "-";
|
|
msgdomain_list_ty *result;
|
|
catalog_output_format_ty output_syntax = &output_format_po;
|
|
bool sort_by_msgid = false;
|
|
|
|
/* Set program name for messages. */
|
|
set_program_name (argv[0]);
|
|
error_print_progname = maybe_print_progname;
|
|
|
|
#ifdef HAVE_SETLOCALE
|
|
/* Set locale via LC_ALL. */
|
|
setlocale (LC_ALL, "");
|
|
#endif
|
|
|
|
/* Set the text message domain. */
|
|
bindtextdomain (PACKAGE, relocate (LOCALEDIR));
|
|
bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
|
|
textdomain (PACKAGE);
|
|
|
|
/* Ensure that write errors on stdout are detected. */
|
|
atexit (close_stdout);
|
|
|
|
while ((optchar = getopt_long (argc, argv, "d:eEhijl:o:pr:svVw:",
|
|
long_options, NULL))
|
|
!= EOF)
|
|
switch (optchar)
|
|
{
|
|
case '\0':
|
|
/* long option */
|
|
break;
|
|
|
|
case 'd':
|
|
csharp_base_directory = optarg;
|
|
tcl_base_directory = optarg;
|
|
break;
|
|
|
|
case 'e':
|
|
message_print_style_escape (false);
|
|
break;
|
|
|
|
case 'E':
|
|
message_print_style_escape (true);
|
|
break;
|
|
|
|
case 'h':
|
|
do_help = true;
|
|
break;
|
|
|
|
case 'i':
|
|
message_print_style_indent ();
|
|
break;
|
|
|
|
case 'j':
|
|
java_mode = true;
|
|
break;
|
|
|
|
case 'l':
|
|
java_locale_name = optarg;
|
|
csharp_locale_name = optarg;
|
|
tcl_locale_name = optarg;
|
|
break;
|
|
|
|
case 'o':
|
|
output_file = optarg;
|
|
break;
|
|
|
|
case 'p':
|
|
output_syntax = &output_format_properties;
|
|
break;
|
|
|
|
case 'r':
|
|
java_resource_name = optarg;
|
|
csharp_resource_name = optarg;
|
|
break;
|
|
|
|
case 's':
|
|
sort_by_msgid = true;
|
|
break;
|
|
|
|
case 'S':
|
|
message_print_style_uniforum ();
|
|
break;
|
|
|
|
case 'v':
|
|
verbose = true;
|
|
break;
|
|
|
|
case 'V':
|
|
do_version = true;
|
|
break;
|
|
|
|
case 'w':
|
|
{
|
|
int value;
|
|
char *endp;
|
|
value = strtol (optarg, &endp, 10);
|
|
if (endp != optarg)
|
|
message_page_width_set (value);
|
|
}
|
|
break;
|
|
|
|
case CHAR_MAX + 1: /* --tcl */
|
|
tcl_mode = true;
|
|
break;
|
|
|
|
case CHAR_MAX + 2: /* --no-wrap */
|
|
message_page_width_ignore ();
|
|
break;
|
|
|
|
case CHAR_MAX + 3: /* --stringtable-output */
|
|
output_syntax = &output_format_stringtable;
|
|
break;
|
|
|
|
case CHAR_MAX + 4: /* --csharp */
|
|
csharp_mode = true;
|
|
break;
|
|
|
|
case CHAR_MAX + 5: /* --csharp-resources */
|
|
csharp_resources_mode = true;
|
|
break;
|
|
|
|
case CHAR_MAX + 6: /* --color */
|
|
if (handle_color_option (optarg) || color_test_mode)
|
|
usage (EXIT_FAILURE);
|
|
break;
|
|
|
|
case CHAR_MAX + 7: /* --style */
|
|
handle_style_option (optarg);
|
|
break;
|
|
|
|
default:
|
|
usage (EXIT_FAILURE);
|
|
break;
|
|
}
|
|
|
|
/* Version information is requested. */
|
|
if (do_version)
|
|
{
|
|
printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
|
|
/* xgettext: no-wrap */
|
|
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
|
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
|
|
This is free software: you are free to change and redistribute it.\n\
|
|
There is NO WARRANTY, to the extent permitted by law.\n\
|
|
"),
|
|
"1995-1998, 2000-2010");
|
|
printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
|
|
exit (EXIT_SUCCESS);
|
|
}
|
|
|
|
/* Help is requested. */
|
|
if (do_help)
|
|
usage (EXIT_SUCCESS);
|
|
|
|
/* Check for contradicting options. */
|
|
{
|
|
unsigned int modes =
|
|
(java_mode ? 1 : 0)
|
|
| (csharp_mode ? 2 : 0)
|
|
| (csharp_resources_mode ? 4 : 0)
|
|
| (tcl_mode ? 8 : 0);
|
|
static const char *mode_options[] =
|
|
{ "--java", "--csharp", "--csharp-resources", "--tcl" };
|
|
/* More than one bit set? */
|
|
if (modes & (modes - 1))
|
|
{
|
|
const char *first_option;
|
|
const char *second_option;
|
|
unsigned int i;
|
|
for (i = 0; ; i++)
|
|
if (modes & (1 << i))
|
|
break;
|
|
first_option = mode_options[i];
|
|
for (i = i + 1; ; i++)
|
|
if (modes & (1 << i))
|
|
break;
|
|
second_option = mode_options[i];
|
|
error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
|
|
first_option, second_option);
|
|
}
|
|
}
|
|
if (java_mode)
|
|
{
|
|
if (optind < argc)
|
|
{
|
|
error (EXIT_FAILURE, 0,
|
|
_("%s and explicit file names are mutually exclusive"),
|
|
"--java");
|
|
}
|
|
}
|
|
else if (csharp_mode)
|
|
{
|
|
if (optind < argc)
|
|
{
|
|
error (EXIT_FAILURE, 0,
|
|
_("%s and explicit file names are mutually exclusive"),
|
|
"--csharp");
|
|
}
|
|
if (csharp_locale_name == NULL)
|
|
{
|
|
error (EXIT_SUCCESS, 0,
|
|
_("%s requires a \"-l locale\" specification"),
|
|
"--csharp");
|
|
usage (EXIT_FAILURE);
|
|
}
|
|
if (csharp_base_directory == NULL)
|
|
{
|
|
error (EXIT_SUCCESS, 0,
|
|
_("%s requires a \"-d directory\" specification"),
|
|
"--csharp");
|
|
usage (EXIT_FAILURE);
|
|
}
|
|
}
|
|
else if (tcl_mode)
|
|
{
|
|
if (optind < argc)
|
|
{
|
|
error (EXIT_FAILURE, 0,
|
|
_("%s and explicit file names are mutually exclusive"),
|
|
"--tcl");
|
|
}
|
|
if (tcl_locale_name == NULL)
|
|
{
|
|
error (EXIT_SUCCESS, 0,
|
|
_("%s requires a \"-l locale\" specification"),
|
|
"--tcl");
|
|
usage (EXIT_FAILURE);
|
|
}
|
|
if (tcl_base_directory == NULL)
|
|
{
|
|
error (EXIT_SUCCESS, 0,
|
|
_("%s requires a \"-d directory\" specification"),
|
|
"--tcl");
|
|
usage (EXIT_FAILURE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (java_resource_name != NULL)
|
|
{
|
|
error (EXIT_SUCCESS, 0, _("%s is only valid with %s or %s"),
|
|
"--resource", "--java", "--csharp");
|
|
usage (EXIT_FAILURE);
|
|
}
|
|
if (java_locale_name != NULL)
|
|
{
|
|
error (EXIT_SUCCESS, 0, _("%s is only valid with %s or %s"),
|
|
"--locale", "--java", "--csharp");
|
|
usage (EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
/* Read the given .mo file. */
|
|
if (java_mode)
|
|
{
|
|
result = msgdomain_read_java (java_resource_name, java_locale_name);
|
|
}
|
|
else if (csharp_mode)
|
|
{
|
|
result = msgdomain_read_csharp (csharp_resource_name, csharp_locale_name,
|
|
csharp_base_directory);
|
|
}
|
|
else if (tcl_mode)
|
|
{
|
|
result = msgdomain_read_tcl (tcl_locale_name, tcl_base_directory);
|
|
}
|
|
else
|
|
{
|
|
message_list_ty *mlp;
|
|
|
|
mlp = message_list_alloc (false);
|
|
if (optind < argc)
|
|
{
|
|
do
|
|
read_one_file (mlp, argv[optind]);
|
|
while (++optind < argc);
|
|
}
|
|
else
|
|
read_one_file (mlp, "-");
|
|
|
|
result = msgdomain_list_alloc (false);
|
|
result->item[0]->messages = mlp;
|
|
}
|
|
|
|
/* Sorting the list of messages. */
|
|
if (sort_by_msgid)
|
|
msgdomain_list_sort_by_msgid (result);
|
|
|
|
/* Write the resulting message list to the given .po file. */
|
|
msgdomain_list_print (result, output_file, output_syntax, force_po, false);
|
|
|
|
/* No problems. */
|
|
exit (EXIT_SUCCESS);
|
|
}
|
|
|
|
|
|
/* Display usage information and exit. */
|
|
static void
|
|
usage (int status)
|
|
{
|
|
if (status != EXIT_SUCCESS)
|
|
fprintf (stderr, _("Try '%s --help' for more information.\n"),
|
|
program_name);
|
|
else
|
|
{
|
|
printf (_("\
|
|
Usage: %s [OPTION] [FILE]...\n\
|
|
"), program_name);
|
|
printf ("\n");
|
|
printf (_("\
|
|
Convert binary message catalog to Uniforum style .po file.\n\
|
|
"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Mandatory arguments to long options are mandatory for short options too.\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Operation mode:\n"));
|
|
printf (_("\
|
|
-j, --java Java mode: input is a Java ResourceBundle class\n"));
|
|
printf (_("\
|
|
--csharp C# mode: input is a .NET .dll file\n"));
|
|
printf (_("\
|
|
--csharp-resources C# resources mode: input is a .NET .resources file\n"));
|
|
printf (_("\
|
|
--tcl Tcl mode: input is a tcl/msgcat .msg file\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Input file location:\n"));
|
|
printf (_("\
|
|
FILE ... input .mo files\n"));
|
|
printf (_("\
|
|
If no input file is given or if it is -, standard input is read.\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Input file location in Java mode:\n"));
|
|
printf (_("\
|
|
-r, --resource=RESOURCE resource name\n"));
|
|
printf (_("\
|
|
-l, --locale=LOCALE locale name, either language or language_COUNTRY\n"));
|
|
printf (_("\
|
|
The class name is determined by appending the locale name to the resource name,\n\
|
|
separated with an underscore. The class is located using the CLASSPATH.\n\
|
|
"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Input file location in C# mode:\n"));
|
|
printf (_("\
|
|
-r, --resource=RESOURCE resource name\n"));
|
|
printf (_("\
|
|
-l, --locale=LOCALE locale name, either language or language_COUNTRY\n"));
|
|
printf (_("\
|
|
-d DIRECTORY base directory for locale dependent .dll files\n"));
|
|
printf (_("\
|
|
The -l and -d options are mandatory. The .dll file is located in a\n\
|
|
subdirectory of the specified directory whose name depends on the locale.\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Input file location in Tcl mode:\n"));
|
|
printf (_("\
|
|
-l, --locale=LOCALE locale name, either language or language_COUNTRY\n"));
|
|
printf (_("\
|
|
-d DIRECTORY base directory of .msg message catalogs\n"));
|
|
printf (_("\
|
|
The -l and -d options are mandatory. The .msg file is located in the\n\
|
|
specified directory.\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Output file location:\n"));
|
|
printf (_("\
|
|
-o, --output-file=FILE write output to specified file\n"));
|
|
printf (_("\
|
|
The results are written to standard output if no output file is specified\n\
|
|
or if it is -.\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Output details:\n"));
|
|
printf (_("\
|
|
--color use colors and other text attributes always\n\
|
|
--color=WHEN use colors and other text attributes if WHEN.\n\
|
|
WHEN may be 'always', 'never', 'auto', or 'html'.\n"));
|
|
printf (_("\
|
|
--style=STYLEFILE specify CSS style rule file for --color\n"));
|
|
printf (_("\
|
|
-e, --no-escape do not use C escapes in output (default)\n"));
|
|
printf (_("\
|
|
-E, --escape use C escapes in output, no extended chars\n"));
|
|
printf (_("\
|
|
--force-po write PO file even if empty\n"));
|
|
printf (_("\
|
|
-i, --indent write indented output style\n"));
|
|
printf (_("\
|
|
--strict write strict uniforum style\n"));
|
|
printf (_("\
|
|
-p, --properties-output write out a Java .properties file\n"));
|
|
printf (_("\
|
|
--stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
|
|
printf (_("\
|
|
-w, --width=NUMBER set output page width\n"));
|
|
printf (_("\
|
|
--no-wrap do not break long message lines, longer than\n\
|
|
the output page width, into several lines\n"));
|
|
printf (_("\
|
|
-s, --sort-output generate sorted output\n"));
|
|
printf ("\n");
|
|
printf (_("\
|
|
Informative output:\n"));
|
|
printf (_("\
|
|
-h, --help display this help and exit\n"));
|
|
printf (_("\
|
|
-V, --version output version information and exit\n"));
|
|
printf (_("\
|
|
-v, --verbose increase verbosity level\n"));
|
|
printf ("\n");
|
|
/* TRANSLATORS: The placeholder indicates the bug-reporting address
|
|
for this package. Please add _another line_ saying
|
|
"Report translation bugs to <...>\n" with the address for translation
|
|
bugs (typically your translation team's web or email address). */
|
|
fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
|
|
stdout);
|
|
}
|
|
|
|
exit (status);
|
|
}
|
|
|
|
|
|
static void
|
|
read_one_file (message_list_ty *mlp, const char *filename)
|
|
{
|
|
if (csharp_resources_mode)
|
|
read_resources_file (mlp, filename);
|
|
else
|
|
read_mo_file (mlp, filename);
|
|
}
|