From: Bruno Haible Date: Tue, 20 Mar 2001 15:06:33 +0000 (+0000) Subject: New program 'ngettext'. X-Git-Tag: v0.10.36~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5598ba582b41a83aa01fc1f0b54c619274bbed91;p=thirdparty%2Fgettext.git New program 'ngettext'. --- diff --git a/po/ChangeLog b/po/ChangeLog index d14334026..48bd48b56 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2001-03-18 Bruno Haible + + * POTFILES.in: Add src/ngettext.c. + 2001-03-11 Bruno Haible * de.po: Update from Karl Eichwalder. diff --git a/po/POTFILES.in b/po/POTFILES.in index b852f0fbd..c34464070 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -18,6 +18,7 @@ src/msgcomm.c src/msgfmt.c src/msgmerge.c src/msgunfmt.c +src/ngettext.c src/open-po.c src/po-gram-gen.c src/po-lex.h diff --git a/src/ChangeLog b/src/ChangeLog index 29f40a49a..f3f726a98 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2001-03-18 Bruno Haible + + * gettext.c [TESTS]: When testing, set HAVE_SETLOCALE. + (main): Expand escape sequences also if no domain is given. Don't need + to call bindtextdomain if there are no string arguments. + * ngettext.c: New file. + * Makefile.am (bin_PROGRAMS): Add ngettext. + (ngettext_SOURCES): New variable. + 2001-03-19 Bruno Haible * xgettext.c (extension_to_language): Recognize "*.cpp" and "*.hpp" as diff --git a/src/Makefile.am b/src/Makefile.am index 2284f19d4..1b8e8ec32 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ AUTOMAKE_OPTIONS = 1.2 gnits -bin_PROGRAMS = gettext msgcmp msgfmt msgmerge msgunfmt xgettext msgcomm +bin_PROGRAMS = gettext ngettext msgcmp msgfmt msgmerge msgunfmt xgettext msgcomm noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-lex.h po.h open-po.h \ str-list.h write-po.h xget-lex.h dir-list.h po-gram-gen.h po-hash-gen.h @@ -39,6 +39,7 @@ YACC = @YACC@ -d # Source dependencies. gettext_SOURCES = gettext.c +ngettext_SOURCES = ngettext.c msgcmp_SOURCES = message.c msgcmp.c open-po.c po-gram-gen.y po-hash-gen.y \ po-lex.c po.c str-list.c dir-list.c msgfmt_SOURCES = msgfmt.c open-po.c po-gram-gen.y po-hash-gen.y po-lex.c po.c \ diff --git a/src/ngettext.c b/src/ngettext.c new file mode 100644 index 000000000..2b31f8304 --- /dev/null +++ b/src/ngettext.c @@ -0,0 +1,320 @@ +/* ngettext - retrieve plural form string from message catalog and print it. + Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. + + 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 2, 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, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "error.h" +#include "system.h" + +#include "libgettext.h" + +#define _(str) gettext (str) + +/* If nonzero expand escape sequences in strings before looking in the + message catalog. */ +int do_expand; + +/* Name the program is called with. */ +char *program_name; + +/* Long options. */ +static const struct option long_options[] = +{ + { "domain", required_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + +/* Prototypes for local functions. */ +static void usage PARAMS ((int __status)) +#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2) + __attribute__ ((noreturn)) +#endif +; +static const char *expand_escape PARAMS ((const char *__str)); + +int +main (argc, argv) + int argc; + char *argv[]; +{ + int optchar; + const char *msgid; + const char *msgid_plural; + const char *count; + unsigned long n; + + /* Default values for command line options. */ + int do_help = 0; + int do_version = 0; + const char *domain = getenv ("TEXTDOMAIN"); + const char *domaindir = getenv ("TEXTDOMAINDIR"); + do_expand = 0; + + /* Set program name for message texts. */ + program_name = argv[0]; + +#ifdef HAVE_SETLOCALE + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); +#endif + + /* Set the text message domain. */ + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + /* Parse command line options. */ + while ((optchar = getopt_long (argc, argv, "+d:eEhV", long_options, NULL)) + != EOF) + switch (optchar) + { + case '\0': /* Long option. */ + break; + case 'd': + domain = optarg; + break; + case 'e': + do_expand = 1; + break; + case 'E': + /* Ignore. Just for compatibility. */ + break; + case 'h': + do_help = 1; + break; + case 'V': + do_version = 1; + break; + default: + usage (EXIT_FAILURE); + } + + /* 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\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), + "1995-1997, 2000, 2001"); + printf (_("Written by %s.\n"), "Ulrich Drepper"); + exit (EXIT_SUCCESS); + } + + /* Help is requested. */ + if (do_help) + usage (EXIT_SUCCESS); + + /* More optional command line options. */ + switch (argc - optind) + { + default: + error (EXIT_FAILURE, 0, _("too many arguments")); + + case 4: + domain = argv[optind++]; + /* FALLTHROUGH */ + + case 3: + break; + + case 2: + case 1: + case 0: + error (EXIT_FAILURE, 0, _("missing arguments")); + } + + /* Now the mandatory command line options. */ + msgid = argv[optind++]; + msgid_plural = argv[optind++]; + count = argv[optind++]; + + if (optind != argc) + abort (); + + { + char *endp; + unsigned long tmp_val; + + errno = 0; + tmp_val = strtoul (count, &endp, 10); + if (errno == 0 && count[0] != '\0' && endp[0] == '\0') + n = tmp_val; + else + /* When COUNT is not valid, use plural. */ + n = 99; + } + + /* Expand escape sequences if enabled. */ + if (do_expand) + { + msgid = expand_escape (msgid); + msgid_plural = expand_escape (msgid_plural); + } + + /* If no domain name is given we don't translate, and we use English + plural form handling. */ + if (domain == NULL || domain[0] == '\0') + fputs (n == 1 ? msgid : msgid_plural, stdout); + else + { + /* Bind domain to appropriate directory. */ + if (domaindir != NULL && domaindir[0] != '\0') + bindtextdomain (domain, domaindir); + + /* Write out the result. */ + fputs (dngettext (domain, msgid, msgid_plural, n), stdout); + } + + exit (EXIT_SUCCESS); +} + + +/* Display usage information and exit. */ +static void +usage (status) + int status; +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); + else + { + /* xgettext: no-wrap */ + printf (_("\ +Usage: %s [OPTION] [TEXTDOMAIN] MSGID MSGID-PLURAL COUNT\n\ + -d, --domain=TEXTDOMAIN retrieve translated message from TEXTDOMAIN\n\ + -e enable expansion of some escape sequences\n\ + -E (ignored for compatibility)\n\ + -h, --help display this help and exit\n\ + -V, --version display version information and exit\n\ + [TEXTDOMAIN] retrieve translated message from TEXTDOMAIN\n\ + MSGID MSGID-PLURAL translate MSGID (singular) / MSGID-PLURAL (plural)\n\ + COUNT choose singular/plural form based on this value\n"), + program_name); + /* xgettext: no-wrap */ + printf (_("\ +\n\ +If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\ +environment variable TEXTDOMAIN. If the message catalog is not found in the\n\ +regular directory, another location can be specified with the environment\n\ +variable TEXTDOMAINDIR.\n\ +Standard search directory: %s\n"), LOCALEDIR); + fputs (_("Report bugs to .\n"), stdout); + } + + exit (status); +} + + +/* Expand some escape sequences found in the argument string. */ +static const char * +expand_escape (str) + const char *str; +{ + char *retval, *rp; + const char *cp = str; + + do + { + while (cp[0] != '\0' && cp[0] != '\\') + ++cp; + } + while (cp[0] != '\0' && cp[1] != '\0' + && strchr ("bfnrt\\01234567", cp[1]) == NULL); + + if (cp[0] == '\0') + return str; + + retval = (char *) xmalloc (strlen (str)); + + rp = retval + (cp - str); + memcpy (retval, str, cp - str); + + do + { + switch (*++cp) + { + case 'b': /* backspace */ + *rp++ = '\b'; + ++cp; + break; + case 'f': /* form feed */ + *rp++ = '\f'; + ++cp; + break; + case 'n': /* new line */ + *rp++ = '\n'; + ++cp; + break; + case 'r': /* carriage return */ + *rp++ = '\r'; + ++cp; + break; + case 't': /* horizontal tab */ + *rp++ = '\t'; + ++cp; + break; + case '\\': + *rp = '\\'; + ++cp; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { + int ch = *cp++ - '0'; + + if (*cp >= '0' && *cp <= '7') + { + ch *= 8; + ch += *cp++ - '0'; + + if (*cp >= '0' && *cp <= '7') + { + ch *= 8; + ch += *cp++ - '0'; + } + } + *rp = ch; + } + break; + default: + *rp = '\\'; + break; + } + + while (cp[0] != '\0' && cp[0] != '\\') + *rp++ = *cp++; + } + while (cp[0] != '\0'); + + /* Terminate string. */ + *rp = '\0'; + + return (const char *) retval; +} diff --git a/tests/xg-test1.ok.po b/tests/xg-test1.ok.po index 0b01f9f9a..bc4d73a18 100644 --- a/tests/xg-test1.ok.po +++ b/tests/xg-test1.ok.po @@ -232,10 +232,10 @@ msgstr "" msgid "format specifications for argument %lu are not the same" msgstr "" -msgid "missing arguments" +msgid "too many arguments" msgstr "" -msgid "too many arguments" +msgid "missing arguments" msgstr "" #, c-format, no-wrap