(root)/
gettext-0.22.4/
gettext-tools/
tests/
tstgettext.c
       1  /* gettext - retrieve text string from message catalog and print it.
       2     Copyright (C) 1995-1997, 2000-2007, 2012, 2018-2020 Free Software
       3     Foundation, Inc.
       4     Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, May 1995.
       5  
       6     This program is free software: you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifdef HAVE_CONFIG_H
      20  # include <config.h>
      21  #endif
      22  
      23  #include <getopt.h>
      24  #include <stdbool.h>
      25  #include <stdio.h>
      26  #include <stdlib.h>
      27  #include <string.h>
      28  #include <locale.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 "xalloc.h"
      38  #include "propername.h"
      39  #include "xsetenv.h"
      40  #include "../../gettext-runtime/src/escapes.h"
      41  
      42  /* Make sure we use the included libintl, not the system's one. */
      43  #undef _LIBINTL_H
      44  #include "libgnuintl.h"
      45  
      46  #if defined _WIN32 && !defined __CYGWIN__
      47  # undef setlocale
      48  # define setlocale fake_setlocale
      49  extern char *setlocale (int category, const char *locale);
      50  #endif
      51  
      52  #define _(str) gettext (str)
      53  
      54  /* If false, add newline after last string.  This makes only sense in
      55     the 'echo' emulation mode.  */
      56  static bool inhibit_added_newline;
      57  
      58  /* If true, expand escape sequences in strings before looking in the
      59     message catalog.  */
      60  static bool do_expand;
      61  
      62  /* Long options.  */
      63  static const struct option long_options[] =
      64  {
      65    { "domain", required_argument, NULL, 'd' },
      66    { "env", required_argument, NULL, '=' },
      67    { "help", no_argument, NULL, 'h' },
      68    { "shell-script", no_argument, NULL, 's' },
      69    { "version", no_argument, NULL, 'V' },
      70    { NULL, 0, NULL, 0 }
      71  };
      72  
      73  /* Forward declaration of local functions.  */
      74  _GL_NORETURN_FUNC static void usage (int status);
      75  
      76  int
      77  main (int argc, char *argv[])
      78  {
      79    int optchar;
      80    const char *msgid;
      81  
      82    /* Default values for command line options.  */
      83    bool do_help = false;
      84    bool do_shell = false;
      85    bool do_version = false;
      86    bool environ_changed = false;
      87    const char *domain = getenv ("TEXTDOMAIN");
      88    const char *domaindir = getenv ("TEXTDOMAINDIR");
      89    inhibit_added_newline = false;
      90    do_expand = false;
      91  
      92    /* Set program name for message texts.  */
      93    set_program_name (argv[0]);
      94  
      95    /* Set locale via LC_ALL.  */
      96    setlocale (LC_ALL, "");
      97  
      98    /* Set the text message domain.  */
      99    bindtextdomain (PACKAGE, relocate (LOCALEDIR));
     100    textdomain (PACKAGE);
     101  
     102    /* Ensure that write errors on stdout are detected.  */
     103    atexit (close_stdout);
     104  
     105    /* Parse command line options.  */
     106    while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL))
     107           != EOF)
     108      switch (optchar)
     109      {
     110      case '\0':          /* Long option.  */
     111        break;
     112      case 'd':
     113        domain = optarg;
     114        break;
     115      case 'e':
     116        do_expand = true;
     117        break;
     118      case 'E':
     119        /* Ignore.  Just for compatibility.  */
     120        break;
     121      case 'h':
     122        do_help = true;
     123        break;
     124      case 'n':
     125        inhibit_added_newline = true;
     126        break;
     127      case 's':
     128        do_shell = true;
     129        break;
     130      case 'V':
     131        do_version = true;
     132        break;
     133      case '=':
     134        {
     135          /* Undocumented option --env sets an environment variable.  */
     136          char *separator = strchr (optarg, '=');
     137          if (separator != NULL)
     138            {
     139              *separator = '\0';
     140              xsetenv (optarg, separator + 1, 1);
     141              environ_changed = true;
     142              break;
     143            }
     144        }
     145        FALLTHROUGH;
     146      default:
     147        usage (EXIT_FAILURE);
     148      }
     149  
     150    if (environ_changed)
     151      /* Set locale again via LC_ALL.  */
     152      setlocale (LC_ALL, "");
     153  
     154    /* Version information is requested.  */
     155    if (do_version)
     156      {
     157        printf ("%s (GNU %s) %s\n", last_component (program_name),
     158                PACKAGE, VERSION);
     159        /* xgettext: no-wrap */
     160        printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
     161  License GPLv3+: GNU GPL version 3 or later <%s>\n\
     162  This is free software: you are free to change and redistribute it.\n\
     163  There is NO WARRANTY, to the extent permitted by law.\n\
     164  "),
     165                "1995-1997, 2000-2006", "https://gnu.org/licenses/gpl.html");
     166        printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
     167        exit (EXIT_SUCCESS);
     168      }
     169  
     170    /* Help is requested.  */
     171    if (do_help)
     172      usage (EXIT_SUCCESS);
     173  
     174    /* We have two major modes: use following Uniforum spec and as
     175       internationalized 'echo' program.  */
     176    if (!do_shell)
     177      {
     178        /* We have to write a single strings translation to stdout.  */
     179  
     180        /* Get arguments.  */
     181        switch (argc - optind)
     182          {
     183            default:
     184              error (EXIT_FAILURE, 0, _("too many arguments"));
     185  
     186            case 2:
     187              domain = argv[optind++];
     188              FALLTHROUGH;
     189  
     190            case 1:
     191              break;
     192  
     193            case 0:
     194              error (EXIT_FAILURE, 0, _("missing arguments"));
     195          }
     196  
     197        msgid = argv[optind++];
     198  
     199        /* Expand escape sequences if enabled.  */
     200        if (do_expand)
     201          msgid = expand_escapes (msgid, &inhibit_added_newline);
     202  
     203        /* If no domain name is given we don't translate.  */
     204        if (domain == NULL || domain[0] == '\0')
     205          {
     206            fputs (msgid, stdout);
     207          }
     208        else
     209          {
     210            /* Bind domain to appropriate directory.  */
     211            if (domaindir != NULL && domaindir[0] != '\0')
     212              bindtextdomain (domain, domaindir);
     213  
     214            /* Write out the result.  */
     215            fputs (dgettext (domain, msgid), stdout);
     216          }
     217      }
     218    else
     219      {
     220        if (optind < argc)
     221          {
     222            /* If no domain name is given we print the original string.
     223               We mark this assigning NULL to domain.  */
     224            if (domain == NULL || domain[0] == '\0')
     225              domain = NULL;
     226            else
     227              /* Bind domain to appropriate directory.  */
     228              if (domaindir != NULL && domaindir[0] != '\0')
     229                bindtextdomain (domain, domaindir);
     230  
     231            /* We have to simulate 'echo'.  All arguments are strings.  */
     232            do
     233              {
     234                msgid = argv[optind++];
     235  
     236                /* Expand escape sequences if enabled.  */
     237                if (do_expand)
     238                  msgid = expand_escapes (msgid, &inhibit_added_newline);
     239  
     240                /* Write out the result.  */
     241                fputs (domain == NULL ? msgid : dgettext (domain, msgid),
     242                       stdout);
     243  
     244                /* We separate the arguments by a single ' '.  */
     245                if (optind < argc)
     246                  fputc (' ', stdout);
     247              }
     248            while (optind < argc);
     249          }
     250  
     251        /* If not otherwise told: add trailing newline.  */
     252        if (!inhibit_added_newline)
     253          fputc ('\n', stdout);
     254      }
     255  
     256    exit (EXIT_SUCCESS);
     257  }
     258  
     259  
     260  /* Display usage information and exit.  */
     261  static void
     262  usage (int status)
     263  {
     264    if (status != EXIT_SUCCESS)
     265      fprintf (stderr, _("Try '%s --help' for more information.\n"),
     266               program_name);
     267    else
     268      {
     269        /* xgettext: no-wrap */
     270        printf (_("\
     271  Usage: %s [OPTION] [[TEXTDOMAIN] MSGID]\n\
     272  or:    %s [OPTION] -s [MSGID]...\n\
     273  "), program_name, program_name);
     274        printf ("\n");
     275        /* xgettext: no-wrap */
     276        printf (_("\
     277  Display native language translation of a textual message.\n"));
     278        printf ("\n");
     279        /* xgettext: no-wrap */
     280        printf (_("\
     281    -d, --domain=TEXTDOMAIN   retrieve translated messages from TEXTDOMAIN\n\
     282    -e                        enable expansion of some escape sequences\n\
     283    -E                        (ignored for compatibility)\n\
     284    -h, --help                display this help and exit\n\
     285    -n                        suppress trailing newline\n\
     286    -V, --version             display version information and exit\n\
     287    [TEXTDOMAIN] MSGID        retrieve translated message corresponding\n\
     288                              to MSGID from TEXTDOMAIN\n"));
     289        printf ("\n");
     290        /* xgettext: no-wrap */
     291        printf (_("\
     292  If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
     293  environment variable TEXTDOMAIN.  If the message catalog is not found in the\n\
     294  regular directory, another location can be specified with the environment\n\
     295  variable TEXTDOMAINDIR.\n\
     296  When used with the -s option the program behaves like the 'echo' command.\n\
     297  But it does not simply copy its arguments to stdout.  Instead those messages\n\
     298  found in the selected catalog are translated.\n\
     299  Standard search directory: %s\n"),
     300                getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
     301        printf ("\n");
     302        /* TRANSLATORS: The first placeholder is the web address of the Savannah
     303           project of this package.  The second placeholder is the bug-reporting
     304           email address for this package.  Please add _another line_ saying
     305           "Report translation bugs to <...>\n" with the address for translation
     306           bugs (typically your translation team's web or email address).  */
     307        printf(_("\
     308  Report bugs in the bug tracker at <%s>\n\
     309  or by email to <%s>.\n"),
     310               "https://savannah.gnu.org/projects/gettext",
     311               "bug-gettext@gnu.org");
     312      }
     313  
     314    exit (status);
     315  }