diff options
author | Bruno Haible <bruno@clisp.org> | 2001-09-10 12:00:43 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2001-09-10 12:00:43 +0000 |
commit | 0d0aa9df501a15ba609f103cfa93a5187038903e (patch) | |
tree | 848f0cddc6ec88907793c3e5da850d30b452e646 /src | |
parent | b7065a9614f37afd7a5bc4b409b86518dcb59b53 (diff) | |
download | external_gettext-0d0aa9df501a15ba609f103cfa93a5187038903e.zip external_gettext-0d0aa9df501a15ba609f103cfa93a5187038903e.tar.gz external_gettext-0d0aa9df501a15ba609f103cfa93a5187038903e.tar.bz2 |
New program msgattrib.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 6 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/msgattrib.c | 479 |
3 files changed, 490 insertions, 1 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 27c8a5b..9b4f5ac 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2001-09-08 Bruno Haible <haible@clisp.cons.org> + + * msgattrib.c: New file. + * Makefile.am (bin_PROGRAMS): Add msgattrib. + (msgattrib_SOURCES, msgattrib_LDADD): New variables. + 2001-09-02 Bruno Haible <haible@clisp.cons.org> * format-lisp.c (gcd): Remove function. Include "gcd.h" instead. diff --git a/src/Makefile.am b/src/Makefile.am index c52911f..b274c9a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS = 1.2 gnits bin_PROGRAMS = gettext ngettext \ msgcmp msgfmt msgmerge msgunfmt xgettext \ -msgcat msgcomm msgconv msgen msgexec msggrep msguniq +msgattrib msgcat msgcomm msgconv msgen msgexec msggrep msguniq noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-charset.h po-lex.h \ po.h open-po.h read-po.h str-list.h write-po.h dir-list.h file-list.h \ @@ -57,6 +57,9 @@ xgettext_SOURCES = message.c open-po.c po-gram-gen.y po-hash-gen.y \ po-charset.c po-lex.c po.c str-list.c xgettext.c dir-list.c write-po.c \ msgl-ascii.c file-list.c x-c.c x-po.c x-java.l \ format.c format-c.c format-java.c format-lisp.c format-python.c format-ycp.c +msgattrib_SOURCES = msgattrib.c message.c open-po.c po-gram-gen.y \ +po-hash-gen.y po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c \ +write-po.c msgl-ascii.c msgcat_SOURCES = msgcat.c message.c open-po.c po-gram-gen.y po-hash-gen.y \ po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c \ msgl-ascii.c msgl-iconv.c msgl-cat.c file-list.c @@ -87,6 +90,7 @@ msgfmt_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ msgmerge_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ msgunfmt_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ xgettext_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ +msgattrib_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ msgcat_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ msgcomm_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ msgconv_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@ diff --git a/src/msgattrib.c b/src/msgattrib.c new file mode 100644 index 0000000..c68f08f --- /dev/null +++ b/src/msgattrib.c @@ -0,0 +1,479 @@ +/* Manipulates attributes of messages in translation catalogs. + Copyright (C) 2001 Free Software Foundation, Inc. + Written by Bruno Haible <haible@clisp.cons.org>, 2001. + + 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 "config.h" +#endif + +#include <getopt.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> + +#include "dir-list.h" +#include "error.h" +#include "progname.h" +#include "message.h" +#include "read-po.h" +#include "write-po.h" +#include "system.h" +#include "libgettext.h" + +#define _(str) gettext (str) + + +/* Force output of PO file even if empty. */ +static int force_po; + +/* Bit mask of subsets to remove. */ +enum +{ + REMOVE_UNTRANSLATED = 1 << 0, + REMOVE_TRANSLATED = 1 << 1, + REMOVE_FUZZY = 1 << 2, + REMOVE_NONFUZZY = 1 << 3, + REMOVE_OBSOLETE = 1 << 4, + REMOVE_NONOBSOLETE = 1 << 5 +}; +static int to_remove; + +/* Bit mask of actions to perform on all messages. */ +enum +{ + SET_FUZZY = 1 << 0, + RESET_FUZZY = 1 << 1, + SET_OBSOLETE = 1 << 2, + RESET_OBSOLETE = 1 << 3 +}; +static int to_change; + +/* Long options. */ +static const struct option long_options[] = +{ + { "add-location", no_argument, &line_comment, 1 }, + { "clear-fuzzy", no_argument, NULL, CHAR_MAX + 8 }, + { "clear-obsolete", no_argument, NULL, CHAR_MAX + 10 }, + { "directory", required_argument, NULL, 'D' }, + { "escape", no_argument, NULL, 'E' }, + { "force-po", no_argument, &force_po, 1 }, + { "fuzzy", no_argument, NULL, CHAR_MAX + 11 }, + { "help", no_argument, NULL, 'h' }, + { "indent", no_argument, NULL, 'i' }, + { "no-escape", no_argument, NULL, 'e' }, + { "no-fuzzy", no_argument, NULL, CHAR_MAX + 3 }, + { "no-location", no_argument, &line_comment, 0 }, + { "no-obsolete", no_argument, NULL, CHAR_MAX + 5 }, + { "obsolete", no_argument, NULL, CHAR_MAX + 12 }, + { "only-fuzzy", no_argument, NULL, CHAR_MAX + 4 }, + { "only-obsolete", no_argument, NULL, CHAR_MAX + 6 }, + { "output-file", required_argument, NULL, 'o' }, + { "set-fuzzy", no_argument, NULL, CHAR_MAX + 7 }, + { "set-obsolete", no_argument, NULL, CHAR_MAX + 9 }, + { "sort-by-file", no_argument, NULL, 'F' }, + { "sort-output", no_argument, NULL, 's' }, + { "strict", no_argument, NULL, 'S' }, + { "translated", no_argument, NULL, CHAR_MAX + 1 }, + { "untranslated", no_argument, NULL, CHAR_MAX + 2 }, + { "version", no_argument, NULL, 'V' }, + { "width", required_argument, NULL, 'w', }, + { NULL, 0, NULL, 0 } +}; + + +/* Prototypes for local functions. Needed to ensure compiler checking of + function argument counts despite of K&R C function definition syntax. */ +static void usage PARAMS ((int status)); +static bool is_message_selected PARAMS ((const message_ty *mp)); +static void process_message_list PARAMS ((message_list_ty *mlp)); +static msgdomain_list_ty * + process_msgdomain_list PARAMS ((msgdomain_list_ty *mdlp)); + + +int +main (argc, argv) + int argc; + char **argv; +{ + int optchar; + bool do_help; + bool do_version; + char *output_file; + const char *input_file; + msgdomain_list_ty *result; + bool sort_by_msgid = false; + bool sort_by_filepos = false; + + /* Set program name for messages. */ + 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, LOCALEDIR); + textdomain (PACKAGE); + + /* Set default values for variables. */ + do_help = false; + do_version = false; + output_file = NULL; + input_file = NULL; + + while ((optchar = getopt_long (argc, argv, "D:eEFhino:sVw:", long_options, + NULL)) != EOF) + switch (optchar) + { + case '\0': /* Long option. */ + break; + + case 'D': + dir_list_append (optarg); + break; + + case 'e': + message_print_style_escape (false); + break; + + case 'E': + message_print_style_escape (true); + break; + + case 'F': + sort_by_filepos = true; + break; + + case 'h': + do_help = true; + break; + + case 'i': + message_print_style_indent (); + break; + + case 'n': + line_comment = 1; + break; + + case 'o': + output_file = optarg; + break; + + case 's': + sort_by_msgid = true; + break; + + case 'S': + message_print_style_uniforum (); + 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: /* --translated */ + to_remove |= REMOVE_UNTRANSLATED; + break; + + case CHAR_MAX + 2: /* --untranslated */ + to_remove |= REMOVE_TRANSLATED; + break; + + case CHAR_MAX + 3: /* --no-fuzzy */ + to_remove |= REMOVE_FUZZY; + break; + + case CHAR_MAX + 4: /* --only-fuzzy */ + to_remove |= REMOVE_NONFUZZY; + break; + + case CHAR_MAX + 5: /* --no-obsolete */ + to_remove |= REMOVE_OBSOLETE; + break; + + case CHAR_MAX + 6: /* --only-obsolete */ + to_remove |= REMOVE_NONOBSOLETE; + break; + + case CHAR_MAX + 7: /* --set-fuzzy */ + to_change |= SET_FUZZY; + break; + + case CHAR_MAX + 8: /* --clear-fuzzy */ + to_change |= RESET_FUZZY; + break; + + case CHAR_MAX + 9: /* --set-obsolete */ + to_change |= SET_OBSOLETE; + break; + + case CHAR_MAX + 10: /* --clear-obsolete */ + to_change |= RESET_OBSOLETE; + break; + + case CHAR_MAX + 11: /* --fuzzy */ + to_remove |= REMOVE_NONFUZZY; + to_change |= RESET_FUZZY; + break; + + case CHAR_MAX + 12: /* --obsolete */ + to_remove |= REMOVE_NONOBSOLETE; + to_change |= RESET_OBSOLETE; + break; + + default: + usage (EXIT_FAILURE); + /* NOTREACHED */ + } + + /* Version information 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\ +"), + "2001"); + printf (_("Written by %s.\n"), "Bruno Haible"); + exit (EXIT_SUCCESS); + } + + /* Help is requested. */ + if (do_help) + usage (EXIT_SUCCESS); + + /* Test whether we have an .po file name as argument. */ + if (optind == argc) + input_file = "-"; + else if (optind + 1 == argc) + input_file = argv[optind]; + else + { + error (EXIT_SUCCESS, 0, _("at most one input file allowed")); + usage (EXIT_FAILURE); + } + + /* Verify selected options. */ + if (!line_comment && sort_by_filepos) + error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), + "--no-location", "--sort-by-file"); + + if (sort_by_msgid && sort_by_filepos) + error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"), + "--sort-output", "--sort-by-file"); + + /* Read input file. */ + result = read_po_file (input_file); + + /* Filter the messages and manipulate the attributes. */ + result = process_msgdomain_list (result); + + /* Sorting the list of messages. */ + if (sort_by_filepos) + msgdomain_list_sort_by_filepos (result); + else if (sort_by_msgid) + msgdomain_list_sort_by_msgid (result); + + /* Write the PO file. */ + msgdomain_list_print (result, output_file, force_po, false); + + 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] [INPUTFILE]\n\ +"), program_name); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Filters the messages of a translation catalog according to their attributes,\n\ +and manipulates the attributes.\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Mandatory arguments to long options are mandatory for short options too.\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Input file location:\n\ + INPUTFILE input PO file\n\ + -D, --directory=DIRECTORY add DIRECTORY to list for input files search\n\ +If no input file is given or if it is -, standard input is read.\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Output file location:\n\ + -o, --output-file=FILE write output to specified file\n\ +The results are written to standard output if no output file is specified\n\ +or if it is -.\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Message selection:\n\ + --translated keep translated, remove untranslated messages\n\ + --untranslated keep untranslated, remove translated messages\n\ + --no-fuzzy remove 'fuzzy' marked messages\n\ + --only-fuzzy keep 'fuzzy' marked messages\n\ + --no-obsolete remove obsolete #~ messages\n\ + --only-obsolete keep obsolete #~ messages\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Attribute manipulation: + --set-fuzzy set all messages 'fuzzy'\n\ + --clear-fuzzy set all messages non-'fuzzy'\n\ + --set-obsolete set all messages obsolete\n\ + --clear-obsolete set all messages non-obsolete\n\ + --fuzzy synonym for --only-fuzzy --clear-fuzzy\n\ + --obsolete synonym for --only-obsolete --clear-obsolete\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Output details:\n\ + -e, --no-escape do not use C escapes in output (default)\n\ + -E, --escape use C escapes in output, no extended chars\n\ + --force-po write PO file even if empty\n\ + -i, --indent write the .po file using indented style\n\ + --no-location do not write '#: filename:line' lines\n\ + -n, --add-location generate '#: filename:line' lines (default)\n\ + --strict write out strict Uniforum conforming .po file\n\ + -w, --width=NUMBER set output page width\n\ + -s, --sort-output generate sorted output and remove duplicates\n\ + -F, --sort-by-file sort output by file location\n\ +")); + printf ("\n"); + /* xgettext: no-wrap */ + printf (_("\ +Informative output:\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ +")); + printf ("\n"); + fputs (_("Report bugs to <bug-gnu-utils@gnu.org>.\n"), + stdout); + } + + exit (status); +} + + +/* Return true if a message should be kept. */ +static bool +is_message_selected (mp) + const message_ty *mp; +{ + /* Always keep the header entry. */ + if (mp->msgid[0] == '\0') + return true; + + if ((to_remove & (REMOVE_UNTRANSLATED | REMOVE_TRANSLATED)) + && (mp->msgstr[0] == '\0' + ? to_remove & REMOVE_UNTRANSLATED + : to_remove & REMOVE_TRANSLATED)) + return false; + + if ((to_remove & (REMOVE_FUZZY | REMOVE_NONFUZZY)) + && (mp->is_fuzzy + ? to_remove & REMOVE_FUZZY + : to_remove & REMOVE_NONFUZZY)) + return false; + + if ((to_remove & (REMOVE_OBSOLETE | REMOVE_NONOBSOLETE)) + && (mp->obsolete + ? to_remove & REMOVE_OBSOLETE + : to_remove & REMOVE_NONOBSOLETE)) + return false; + + return true; +} + + +static void +process_message_list (mlp) + message_list_ty *mlp; +{ + /* Keep only the selected messages. */ + message_list_remove_if_not (mlp, is_message_selected); + + /* Change the attributes. */ + if (to_change) + { + size_t j; + + for (j = 0; j < mlp->nitems; j++) + { + message_ty *mp = mlp->item[j]; + + if (to_change & SET_FUZZY) + mp->is_fuzzy = true; + if (to_change & RESET_FUZZY) + mp->is_fuzzy = false; + if (to_change & SET_OBSOLETE) + mp->obsolete = true; + if (to_change & RESET_OBSOLETE) + mp->obsolete = false; + } + } +} + + +static msgdomain_list_ty * +process_msgdomain_list (mdlp) + msgdomain_list_ty *mdlp; +{ + size_t k; + + for (k = 0; k < mdlp->nitems; k++) + process_message_list (mdlp->item[k]->messages); + + return mdlp; +} |