(root)/
gettext-0.22.4/
gettext-tools/
src/
msgen.c
       1  /* Creates an English translation catalog.
       2     Copyright (C) 2001-2007, 2009-2010, 2012, 2014, 2016, 2018-2023 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 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  
      19  #ifdef HAVE_CONFIG_H
      20  # include "config.h"
      21  #endif
      22  
      23  #include <getopt.h>
      24  #include <limits.h>
      25  #include <stdio.h>
      26  #include <stdlib.h>
      27  #include <locale.h>
      28  
      29  #include <textstyle.h>
      30  
      31  #include "noreturn.h"
      32  #include "closeout.h"
      33  #include "dir-list.h"
      34  #include "error.h"
      35  #include "error-progname.h"
      36  #include "progname.h"
      37  #include "relocatable.h"
      38  #include "basename-lgpl.h"
      39  #include "message.h"
      40  #include "read-catalog.h"
      41  #include "read-po.h"
      42  #include "read-properties.h"
      43  #include "read-stringtable.h"
      44  #include "msgl-english.h"
      45  #include "msgl-header.h"
      46  #include "write-catalog.h"
      47  #include "write-po.h"
      48  #include "write-properties.h"
      49  #include "write-stringtable.h"
      50  #include "propername.h"
      51  #include "gettext.h"
      52  
      53  #define _(str) gettext (str)
      54  
      55  
      56  /* Force output of PO file even if empty.  */
      57  static int force_po;
      58  
      59  /* Long options.  */
      60  static const struct option long_options[] =
      61  {
      62    { "add-location", optional_argument, NULL, 'n' },
      63    { "color", optional_argument, NULL, CHAR_MAX + 5 },
      64    { "directory", required_argument, NULL, 'D' },
      65    { "escape", no_argument, NULL, 'E' },
      66    { "force-po", no_argument, &force_po, 1 },
      67    { "help", no_argument, NULL, 'h' },
      68    { "indent", no_argument, NULL, 'i' },
      69    { "lang", required_argument, NULL, CHAR_MAX + 4 },
      70    { "no-escape", no_argument, NULL, 'e' },
      71    { "no-location", no_argument, NULL, CHAR_MAX + 7 },
      72    { "no-wrap", no_argument, NULL, CHAR_MAX + 1 },
      73    { "output-file", required_argument, NULL, 'o' },
      74    { "properties-input", no_argument, NULL, 'P' },
      75    { "properties-output", no_argument, NULL, 'p' },
      76    { "sort-by-file", no_argument, NULL, 'F' },
      77    { "sort-output", no_argument, NULL, 's' },
      78    { "strict", no_argument, NULL, 'S' },
      79    { "stringtable-input", no_argument, NULL, CHAR_MAX + 2 },
      80    { "stringtable-output", no_argument, NULL, CHAR_MAX + 3 },
      81    { "style", required_argument, NULL, CHAR_MAX + 6 },
      82    { "version", no_argument, NULL, 'V' },
      83    { "width", required_argument, NULL, 'w' },
      84    { NULL, 0, NULL, 0 }
      85  };
      86  
      87  
      88  /* Forward declaration of local functions.  */
      89  _GL_NORETURN_FUNC static void usage (int status);
      90  
      91  
      92  int
      93  main (int argc, char **argv)
      94  {
      95    int opt;
      96    bool do_help;
      97    bool do_version;
      98    char *output_file;
      99    msgdomain_list_ty *result;
     100    catalog_input_format_ty input_syntax = &input_format_po;
     101    catalog_output_format_ty output_syntax = &output_format_po;
     102    bool sort_by_filepos = false;
     103    bool sort_by_msgid = false;
     104    /* Language (ISO-639 code) and optional territory (ISO-3166 code).  */
     105    const char *catalogname = NULL;
     106  
     107    /* Set program name for messages.  */
     108    set_program_name (argv[0]);
     109    error_print_progname = maybe_print_progname;
     110  
     111    /* Set locale via LC_ALL.  */
     112    setlocale (LC_ALL, "");
     113  
     114    /* Set the text message domain.  */
     115    bindtextdomain (PACKAGE, relocate (LOCALEDIR));
     116    bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
     117    textdomain (PACKAGE);
     118  
     119    /* Ensure that write errors on stdout are detected.  */
     120    atexit (close_stdout);
     121  
     122    /* Set default values for variables.  */
     123    do_help = false;
     124    do_version = false;
     125    output_file = NULL;
     126  
     127    while ((opt = getopt_long (argc, argv,
     128                               "D:eEFhin:o:pPsVw:",
     129                               long_options, NULL)) != EOF)
     130      switch (opt)
     131        {
     132        case '\0':                /* Long option.  */
     133          break;
     134  
     135        case 'D':
     136          dir_list_append (optarg);
     137          break;
     138  
     139        case 'e':
     140          message_print_style_escape (false);
     141          break;
     142  
     143        case 'E':
     144          message_print_style_escape (true);
     145          break;
     146  
     147        case 'F':
     148          sort_by_filepos = true;
     149          break;
     150  
     151        case 'h':
     152          do_help = true;
     153          break;
     154  
     155        case 'i':
     156          message_print_style_indent ();
     157          break;
     158  
     159        case 'n':
     160          if (handle_filepos_comment_option (optarg))
     161            usage (EXIT_FAILURE);
     162          break;
     163  
     164        case 'o':
     165          output_file = optarg;
     166          break;
     167  
     168        case 'p':
     169          output_syntax = &output_format_properties;
     170          break;
     171  
     172        case 'P':
     173          input_syntax = &input_format_properties;
     174          break;
     175  
     176        case 's':
     177          sort_by_msgid = true;
     178          break;
     179  
     180        case 'S':
     181          message_print_style_uniforum ();
     182          break;
     183  
     184        case 'V':
     185          do_version = true;
     186          break;
     187  
     188        case 'w':
     189          {
     190            int value;
     191            char *endp;
     192            value = strtol (optarg, &endp, 10);
     193            if (endp != optarg)
     194              message_page_width_set (value);
     195          }
     196          break;
     197  
     198        case CHAR_MAX + 1: /* --no-wrap */
     199          message_page_width_ignore ();
     200          break;
     201  
     202        case CHAR_MAX + 2: /* --stringtable-input */
     203          input_syntax = &input_format_stringtable;
     204          break;
     205  
     206        case CHAR_MAX + 3: /* --stringtable-output */
     207          output_syntax = &output_format_stringtable;
     208          break;
     209  
     210        case CHAR_MAX + 4: /* --lang */
     211          catalogname = optarg;
     212          break;
     213  
     214        case CHAR_MAX + 5: /* --color */
     215          if (handle_color_option (optarg) || color_test_mode)
     216            usage (EXIT_FAILURE);
     217          break;
     218  
     219        case CHAR_MAX + 6: /* --style */
     220          handle_style_option (optarg);
     221          break;
     222  
     223        case CHAR_MAX + 7: /* --no-location */
     224          message_print_style_filepos (filepos_comment_none);
     225          break;
     226  
     227        default:
     228          usage (EXIT_FAILURE);
     229          break;
     230        }
     231  
     232    /* Version information is requested.  */
     233    if (do_version)
     234      {
     235        printf ("%s (GNU %s) %s\n", last_component (program_name),
     236                PACKAGE, VERSION);
     237        /* xgettext: no-wrap */
     238        printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
     239  License GPLv3+: GNU GPL version 3 or later <%s>\n\
     240  This is free software: you are free to change and redistribute it.\n\
     241  There is NO WARRANTY, to the extent permitted by law.\n\
     242  "),
     243                "2001-2023", "https://gnu.org/licenses/gpl.html");
     244        printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
     245        exit (EXIT_SUCCESS);
     246      }
     247  
     248    /* Help is requested.  */
     249    if (do_help)
     250      usage (EXIT_SUCCESS);
     251  
     252    /* Test whether we have an .po file name as argument.  */
     253    if (optind >= argc)
     254      {
     255        error (EXIT_SUCCESS, 0, _("no input file given"));
     256        usage (EXIT_FAILURE);
     257      }
     258    if (optind + 1 != argc)
     259      {
     260        error (EXIT_SUCCESS, 0, _("exactly one input file required"));
     261        usage (EXIT_FAILURE);
     262      }
     263  
     264    /* Verify selected options.  */
     265    if (sort_by_msgid && sort_by_filepos)
     266      error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
     267             "--sort-output", "--sort-by-file");
     268  
     269    /* Read input file.  */
     270    result = read_catalog_file (argv[optind], input_syntax);
     271  
     272    /* Add English translations.  */
     273    result = msgdomain_list_english (result);
     274  
     275    /* Sort the results.  */
     276    if (sort_by_filepos)
     277      msgdomain_list_sort_by_filepos (result);
     278    else if (sort_by_msgid)
     279      msgdomain_list_sort_by_msgid (result);
     280  
     281    /* Set the Language field in the header.  */
     282    if (catalogname != NULL)
     283      msgdomain_list_set_header_field (result, "Language:", catalogname);
     284  
     285    /* Write the merged message list out.  */
     286    msgdomain_list_print (result, output_file, output_syntax, force_po, false);
     287  
     288    exit (EXIT_SUCCESS);
     289  }
     290  
     291  
     292  /* Display usage information and exit.  */
     293  static void
     294  usage (int status)
     295  {
     296    if (status != EXIT_SUCCESS)
     297      fprintf (stderr, _("Try '%s --help' for more information.\n"),
     298               program_name);
     299    else
     300      {
     301        printf (_("\
     302  Usage: %s [OPTION] INPUTFILE\n\
     303  "), program_name);
     304        printf ("\n");
     305        /* xgettext: no-wrap */
     306        printf (_("\
     307  Creates an English translation catalog.  The input file is the last\n\
     308  created English PO file, or a PO Template file (generally created by\n\
     309  xgettext).  Untranslated entries are assigned a translation that is\n\
     310  identical to the msgid.\n\
     311  "));
     312        printf ("\n");
     313        printf (_("\
     314  Mandatory arguments to long options are mandatory for short options too.\n"));
     315        printf ("\n");
     316        printf (_("\
     317  Input file location:\n"));
     318        printf (_("\
     319    INPUTFILE                   input PO or POT file\n"));
     320        printf (_("\
     321    -D, --directory=DIRECTORY   add DIRECTORY to list for input files search\n"));
     322        printf (_("\
     323  If input file is -, standard input is read.\n"));
     324        printf ("\n");
     325        printf (_("\
     326  Output file location:\n"));
     327        printf (_("\
     328    -o, --output-file=FILE      write output to specified file\n"));
     329        printf (_("\
     330  The results are written to standard output if no output file is specified\n\
     331  or if it is -.\n"));
     332        printf ("\n");
     333        printf (_("\
     334  Input file syntax:\n"));
     335        printf (_("\
     336    -P, --properties-input      input file is in Java .properties syntax\n"));
     337        printf (_("\
     338        --stringtable-input     input file is in NeXTstep/GNUstep .strings syntax\n"));
     339        printf ("\n");
     340        printf (_("\
     341  Output details:\n"));
     342        printf (_("\
     343        --lang=CATALOGNAME      set 'Language' field in the header entry\n"));
     344        printf (_("\
     345        --color                 use colors and other text attributes always\n\
     346        --color=WHEN            use colors and other text attributes if WHEN.\n\
     347                                WHEN may be 'always', 'never', 'auto', or 'html'.\n"));
     348        printf (_("\
     349        --style=STYLEFILE       specify CSS style rule file for --color\n"));
     350        printf (_("\
     351    -e, --no-escape             do not use C escapes in output (default)\n"));
     352        printf (_("\
     353    -E, --escape                use C escapes in output, no extended chars\n"));
     354        printf (_("\
     355        --force-po              write PO file even if empty\n"));
     356        printf (_("\
     357    -i, --indent                indented output style\n"));
     358        printf (_("\
     359        --no-location           suppress '#: filename:line' lines\n"));
     360        printf (_("\
     361    -n, --add-location          preserve '#: filename:line' lines (default)\n"));
     362        printf (_("\
     363        --strict                strict Uniforum output style\n"));
     364        printf (_("\
     365    -p, --properties-output     write out a Java .properties file\n"));
     366        printf (_("\
     367        --stringtable-output    write out a NeXTstep/GNUstep .strings file\n"));
     368        printf (_("\
     369    -w, --width=NUMBER          set output page width\n"));
     370        printf (_("\
     371        --no-wrap               do not break long message lines, longer than\n\
     372                                the output page width, into several lines\n"));
     373        printf (_("\
     374    -s, --sort-output           generate sorted output\n"));
     375        printf (_("\
     376    -F, --sort-by-file          sort output by file location\n"));
     377        printf ("\n");
     378        printf (_("\
     379  Informative output:\n"));
     380        printf (_("\
     381    -h, --help                  display this help and exit\n"));
     382        printf (_("\
     383    -V, --version               output version information and exit\n"));
     384        printf ("\n");
     385        /* TRANSLATORS: The first placeholder is the web address of the Savannah
     386           project of this package.  The second placeholder is the bug-reporting
     387           email address for this package.  Please add _another line_ saying
     388           "Report translation bugs to <...>\n" with the address for translation
     389           bugs (typically your translation team's web or email address).  */
     390        printf(_("\
     391  Report bugs in the bug tracker at <%s>\n\
     392  or by email to <%s>.\n"),
     393               "https://savannah.gnu.org/projects/gettext",
     394               "bug-gettext@gnu.org");
     395      }
     396  
     397    exit (status);
     398  }