(root)/
gettext-0.22.4/
gettext-tools/
tests/
tstngettext.c
       1  /* ngettext - retrieve plural form strings from message catalog and print them.
       2     Copyright (C) 1995-1997, 2000-2007, 2012, 2018-2020 Free Software
       3     Foundation, Inc.
       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 3 of the License, or
       8     (at your option) 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, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifdef HAVE_CONFIG_H
      19  # include <config.h>
      20  #endif
      21  
      22  #include <getopt.h>
      23  #include <stdbool.h>
      24  #include <stdio.h>
      25  #include <stdlib.h>
      26  #include <string.h>
      27  #include <locale.h>
      28  #include <errno.h>
      29  
      30  #include "attribute.h"
      31  #include "noreturn.h"
      32  #include "closeout.h"
      33  #include "error.h"
      34  #include "progname.h"
      35  #include "relocatable.h"
      36  #include "basename-lgpl.h"
      37  #include "propername.h"
      38  #include "xsetenv.h"
      39  
      40  /* Make sure we use the included libintl, not the system's one. */
      41  #undef _LIBINTL_H
      42  #include "libgnuintl.h"
      43  
      44  #if defined _WIN32 && !defined __CYGWIN__
      45  # undef setlocale
      46  # define setlocale fake_setlocale
      47  extern char *setlocale (int category, const char *locale);
      48  #endif
      49  
      50  #define _(str) gettext (str)
      51  
      52  /* Long options.  */
      53  static const struct option long_options[] =
      54  {
      55    { "domain", required_argument, NULL, 'd' },
      56    { "env", required_argument, NULL, '=' },
      57    { "help", no_argument, NULL, 'h' },
      58    { "version", no_argument, NULL, 'V' },
      59    { NULL, 0, NULL, 0 }
      60  };
      61  
      62  /* Forward declaration of local functions.  */
      63  _GL_NORETURN_FUNC static void usage (int __status);
      64  
      65  int
      66  main (int argc, char *argv[])
      67  {
      68    int optchar;
      69    const char *msgid;
      70    const char *msgid_plural;
      71    const char *count;
      72    unsigned long n;
      73  
      74    /* Default values for command line options.  */
      75    bool do_help = false;
      76    bool do_version = false;
      77    bool environ_changed = false;
      78    const char *domain = getenv ("TEXTDOMAIN");
      79    const char *domaindir = getenv ("TEXTDOMAINDIR");
      80  
      81    /* Set program name for message texts.  */
      82    set_program_name (argv[0]);
      83  
      84    /* Set locale via LC_ALL.  */
      85    setlocale (LC_ALL, "");
      86  
      87    /* Set the text message domain.  */
      88    bindtextdomain (PACKAGE, relocate (LOCALEDIR));
      89    textdomain (PACKAGE);
      90  
      91    /* Ensure that write errors on stdout are detected.  */
      92    atexit (close_stdout);
      93  
      94    /* Parse command line options.  */
      95    while ((optchar = getopt_long (argc, argv, "+d:hV", long_options, NULL))
      96           != EOF)
      97      switch (optchar)
      98      {
      99      case '\0':          /* Long option.  */
     100        break;
     101      case 'd':
     102        domain = optarg;
     103        break;
     104      case 'h':
     105        do_help = true;
     106        break;
     107      case 'V':
     108        do_version = true;
     109        break;
     110      case '=':
     111        {
     112          /* Undocumented option --env sets an environment variable.  */
     113          char *separator = strchr (optarg, '=');
     114          if (separator != NULL)
     115            {
     116              *separator = '\0';
     117              xsetenv (optarg, separator + 1, 1);
     118              environ_changed = true;
     119              break;
     120            }
     121        }
     122        FALLTHROUGH;
     123      default:
     124        usage (EXIT_FAILURE);
     125      }
     126  
     127    if (environ_changed)
     128      /* Set locale again via LC_ALL.  */
     129      setlocale (LC_ALL, "");
     130  
     131    /* Version information is requested.  */
     132    if (do_version)
     133      {
     134        printf ("%s (GNU %s) %s\n", last_component (program_name),
     135                PACKAGE, VERSION);
     136        /* xgettext: no-wrap */
     137        printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
     138  License GPLv3+: GNU GPL version 3 or later <%s>\n\
     139  This is free software: you are free to change and redistribute it.\n\
     140  There is NO WARRANTY, to the extent permitted by law.\n\
     141  "),
     142                "1995-1997, 2000-2006", "https://gnu.org/licenses/gpl.html");
     143        printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
     144        exit (EXIT_SUCCESS);
     145      }
     146  
     147    /* Help is requested.  */
     148    if (do_help)
     149      usage (EXIT_SUCCESS);
     150  
     151    /* More optional command line options.  */
     152    if (argc - optind <= 2)
     153      error (EXIT_FAILURE, 0, _("missing arguments"));
     154  
     155    /* Now the mandatory command line options.  */
     156    msgid = argv[optind++];
     157    msgid_plural = argv[optind++];
     158  
     159    /* If no domain name is given we print the original string.
     160       We mark this assigning NULL to domain.  */
     161    if (domain == NULL || domain[0] == '\0')
     162      domain = NULL;
     163    else
     164      /* Bind domain to appropriate directory.  */
     165      if (domaindir != NULL && domaindir[0] != '\0')
     166        bindtextdomain (domain, domaindir);
     167  
     168    /* To speed up the plural-2 test, we accept more than one COUNT in one
     169       call.  */
     170    while (optind < argc)
     171      {
     172        count = argv[optind++];
     173  
     174        {
     175          char *endp;
     176          unsigned long tmp_val;
     177  
     178          errno = 0;
     179          tmp_val = strtoul (count, &endp, 10);
     180          if (errno == 0 && count[0] != '\0' && endp[0] == '\0')
     181            n = tmp_val;
     182          else
     183            /* When COUNT is not valid, use plural.  */
     184            n = 99;
     185        }
     186  
     187        /* If no domain name is given we don't translate, and we use English
     188           plural form handling.  */
     189        if (domain == NULL)
     190          fputs (n == 1 ? msgid : msgid_plural, stdout);
     191        else
     192          /* Write out the result.  */
     193          fputs (dngettext (domain, msgid, msgid_plural, n), stdout);
     194      }
     195  
     196    exit (EXIT_SUCCESS);
     197  }
     198  
     199  
     200  /* Display usage information and exit.  */
     201  static void
     202  usage (int status)
     203  {
     204    if (status != EXIT_SUCCESS)
     205      fprintf (stderr, _("Try '%s --help' for more information.\n"),
     206               program_name);
     207    else
     208      {
     209        /* xgettext: no-wrap */
     210        printf (_("\
     211  Usage: %s [OPTION] MSGID MSGID-PLURAL COUNT...\n\
     212    -d, --domain=TEXTDOMAIN   retrieve translated message from TEXTDOMAIN\n\
     213    -h, --help                display this help and exit\n\
     214    -V, --version             display version information and exit\n\
     215    MSGID MSGID-PLURAL        translate MSGID (singular) / MSGID-PLURAL (plural)\n\
     216    COUNT                     choose singular/plural form based on this value\n"),
     217                program_name);
     218        /* xgettext: no-wrap */
     219        printf (_("\
     220  \n\
     221  If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
     222  environment variable TEXTDOMAIN.  If the message catalog is not found in the\n\
     223  regular directory, another location can be specified with the environment\n\
     224  variable TEXTDOMAINDIR.\n\
     225  Standard search directory: %s\n"), LOCALEDIR);
     226        /* TRANSLATORS: The first placeholder is the web address of the Savannah
     227           project of this package.  The second placeholder is the bug-reporting
     228           email address for this package.  Please add _another line_ saying
     229           "Report translation bugs to <...>\n" with the address for translation
     230           bugs (typically your translation team's web or email address).  */
     231        printf(_("\
     232  Report bugs in the bug tracker at <%s>\n\
     233  or by email to <%s>.\n"),
     234               "https://savannah.gnu.org/projects/gettext",
     235               "bug-gettext@gnu.org");
     236      }
     237  
     238    exit (status);
     239  }