diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2014-08-25 19:13:37 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2014-08-25 19:20:00 +0300 |
commit | e26cb120ffe5f7303ddd8b514246ac6874e83f9f (patch) | |
tree | 64ca646b34103a5e8934b42fbbd9ca732a14e034 | |
parent | 713bc0ca4b4ea3114d33f06c57c117de7f9fef11 (diff) | |
download | direvent-e26cb120ffe5f7303ddd8b514246ac6874e83f9f.tar.gz direvent-e26cb120ffe5f7303ddd8b514246ac6874e83f9f.tar.bz2 |
I18N
* .gitignore: Add am
* bootstrap: Create am, unless exists.
* Makefile.am (SUBDIRS): Add po
* acinclude.m4: New file.
* configure.ac: Use gettext
* doc/direvent.texi: Update
* po/.gitignore: New file
* po/POTFILES.in: New file.
* po/Makevars: New file.
* src/Makefile.am (LDADD): Add @LIBINTL@
(noinst_HEADERS): Add gettext.h
* src/config.c: gettextize
* src/direvent.c: Likewise.
* src/environ.c: Likewise.
* src/hashtab.c: Likewise.
* src/progman.c: Likewise.
* src/watcher.c: Likewise.
* src/gettext.h: New file.
* src/direvent.h: Add missing prototypes.
* tests/re05.at: Remove superfluous quoting.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | acinclude.m4 | 44 | ||||
-rwxr-xr-x | bootstrap | 1 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | doc/direvent.texi | 12 | ||||
m--------- | grecs | 0 | ||||
-rw-r--r-- | po/.gitignore | 20 | ||||
-rw-r--r-- | po/Makevars | 41 | ||||
-rw-r--r-- | po/POTFILES.in | 9 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/config.c | 103 | ||||
-rw-r--r-- | src/direvent.c | 16 | ||||
-rw-r--r-- | src/direvent.h | 13 | ||||
-rw-r--r-- | src/environ.c | 3 | ||||
-rw-r--r-- | src/gettext.h | 280 | ||||
-rw-r--r-- | src/hashtab.c | 6 | ||||
-rw-r--r-- | src/progman.c | 32 | ||||
-rw-r--r-- | src/watcher.c | 28 | ||||
-rw-r--r-- | tests/re05.at | 2 |
20 files changed, 524 insertions, 105 deletions
@@ -16,2 +16,3 @@ TAGS aclocal.m4 +am autom4te.cache diff --git a/Makefile.am b/Makefile.am index ea87088..9b13324 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,5 +16,5 @@ -ACLOCAL_AMFLAGS = -I grecs/am +ACLOCAL_AMFLAGS = -I am -I grecs/am -SUBDIRS=grecs src tests doc +SUBDIRS= grecs src tests doc po @@ -27 +27,3 @@ ChangeLog: + +EXTRA_DIST = build-aux/config.rpath diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..31651bc --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,44 @@ +# This file is part of Direvent -*- autoconf -*- +# Copyright (C) 2012-2014 Sergey Poznyakoff +# +# Direvent 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 3, or (at your option) +# any later version. +# +# Direvent 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 Direvent. If not, see <http://www.gnu.org/licenses/>. + +AC_DEFUN([DEVT_CC_OPT],[ + m4_pushdef([devt_optname],translit($1,[-],[_])) + AC_MSG_CHECKING(whether $CC accepts $1) + devt_save_cc="$CC" + CC="$CC $1" + AC_TRY_RUN([int main() { return 0; }], + [devt_cv_cc_]devt_optname=yes, + [devt_cv_cc_]devt_optname=no, + [devt_cv_cc_]devt_optname=no) + CC="$devt_save_cc" + AC_MSG_RESULT($[devt_cv_cc_]devt_optname) + + if test $[devt_cv_cc_]devt_optname = yes; then + ifelse([$2],,:,[$2]) + ifelse([$3],,,else + [$3]) + fi + m4_popdef([devt_optname]) + ]) + +AC_DEFUN([DEVT_CC_OPT_CFLAGS],[ + DEVT_CC_OPT([$1],[CFLAGS="$CFLAGS $1"]) +]) + +AC_DEFUN([DEVT_CC_PAREN_QUIRK],[ + DEVT_CC_OPT_CFLAGS([-Wno-parentheses]) +]) + @@ -2,2 +2,3 @@ set -e +test -d am || mkdir am git submodule init diff --git a/configure.ac b/configure.ac index c4060d8..57cda4b 100644 --- a/configure.ac +++ b/configure.ac @@ -30,2 +30,3 @@ AC_PROG_AWK AC_PROG_CC +DEVT_CC_PAREN_QUIRK AC_PROG_RANLIB @@ -67,2 +68,8 @@ AH_TOP([ GRECS_SETUP([grecs],[tree-api git2chg no-preproc getopt tests]) +GRECS_HOST_PROJECT_INCLUDES='-I$(top_srcdir)/src' + +# Gettext. +AM_ICONV +AM_GNU_GETTEXT([external], [need-formatstring-macros]) +AM_GNU_GETTEXT_VERSION([0.18]) @@ -70,3 +77,3 @@ GRECS_SETUP([grecs],[tree-api git2chg no-preproc getopt tests]) AC_CONFIG_TESTDIR(tests) -AC_CONFIG_FILES([tests/Makefile tests/atlocal]) +AC_CONFIG_FILES([tests/Makefile tests/atlocal po/Makefile.in]) AM_MISSING_PROG([AUTOM4TE], [autom4te]) diff --git a/doc/direvent.texi b/doc/direvent.texi index 46b9a35..104ced0 100644 --- a/doc/direvent.texi +++ b/doc/direvent.texi @@ -6,3 +6,3 @@ @c %**end of header -@setchapternewpage odd +@c @setchapternewpage odd @@ -114,3 +114,3 @@ reacts when a file system event occurs in any of them. Directories and events to monitor are specified in the configuration file. When -an event occurs the utility reacts by invoking an external command +an event occurs, the program reacts by invoking an external command configured for that event. @@ -148,3 +148,3 @@ ownership, mode, link count, etc. @cindex handler, introduced -A @dfn{watcher} is a configuration entity which associates a set of +A @dfn{watcher} is a configuration entity that associates a set of directories with a set of events and instructs @command{direvent} to @@ -183,7 +183,8 @@ The following block statement declares a watcher: @example +@group watcher @{ path @var{pathname} [recursive [@var{level}]]; + file @var{pattern-list}; event @var{event-list}; command @var{command-line}; - file @var{pattern-list}; user @var{name}; @@ -193,2 +194,3 @@ watcher @{ @} +@end group @end example @@ -238,3 +240,3 @@ watcher @{ On this event, the watcher is to invoke @file{/usr/bin/upload} -with the name of created file as an argument. To make it +with the name of the created file as an argument. To make it possible, the @command{direvent} configuration file provides @dfn{macro diff --git a/grecs b/grecs -Subproject 57a00b140954a2c22ba2fdebc93e8e6eda41b2a +Subproject 477701c059d73e47aa1bac97e96d801542f2bd8 diff --git a/po/.gitignore b/po/.gitignore new file mode 100644 index 0000000..32545fd --- /dev/null +++ b/po/.gitignore @@ -0,0 +1,20 @@ +*.gmo +*.po +*.po~ +.pot +.reference/ +LINGUAS +Makefile.in.in +Makevars.template +POTFILES +Rules-quot +boldquot.sed +en@boldquot.header +en@quot.header +insert-header.sed +insert-header.sin +direvent.pot +quot.sed +remove-potcdate.sed +remove-potcdate.sin +stamp-po diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..33b0663 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,41 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Sergey Poznyakoff + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = bug-direvent@gnu.org.ua + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..5029ee6 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,9 @@ +# List of source files which contain translatable strings. + +src/cmdline.h +src/config.c +src/direvent.c +src/environ.c +src/hashtab.c +src/progman.c +src/watcher.c diff --git a/src/Makefile.am b/src/Makefile.am index c7f1439..8bdf610 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,3 +43,3 @@ endif -LDADD=@GRECS_LDADD@ +LDADD=@GRECS_LDADD@ @LIBINTL@ AM_CPPFLAGS=-I$(top_srcdir)/grecs/src/ @@ -48,2 +48,3 @@ BUILT_SOURCES=cmdline.h EXTRA_DIST=cmdline.opt +noinst_HEADERS=gettext.h diff --git a/src/config.c b/src/config.c index 9c17124..82262a8 100644 --- a/src/config.c +++ b/src/config.c @@ -62,3 +62,3 @@ get_facility(const char *arg) if (trans_strtotok(kwfac, arg, &f)) { - diag(LOG_CRIT, "unknown syslog facility: %s", arg); + diag(LOG_CRIT, _("unknown syslog facility: %s"), arg); exit(1); @@ -79,3 +79,3 @@ get_priority(const char *arg) if (trans_strtotok(kwpri, arg, &f)) { - diag(LOG_CRIT, "unknown syslog priority: %s", arg); + diag(LOG_CRIT, _("unknown syslog priority: %s"), arg); exit(1); @@ -87,3 +87,3 @@ get_priority(const char *arg) if ((cmd) != grecs_callback_set_value) { \ - grecs_error(locus, 0, "Unexpected block statement"); \ + grecs_error(locus, 0, _("unexpected block statement")); \ return 1; \ @@ -96,3 +96,3 @@ assert_grecs_value_type(grecs_locus_t *locus, if (GRECS_VALUE_EMPTY_P(value)) { - grecs_error(locus, 0, "expected %s", + grecs_error(locus, 0, _("expected %s"), grecs_data_type_string(type)); @@ -101,3 +101,3 @@ assert_grecs_value_type(grecs_locus_t *locus, if (value->type != type) { - grecs_error(locus, 0, "expected %s, but found %s", + grecs_error(locus, 0, _("expected %s, but found %s"), grecs_data_type_string(type), @@ -123,3 +123,3 @@ cb_syslog_facility(enum grecs_callback_command cmd, grecs_node_t *node, grecs_error(&value->locus, 0, - "Unknown syslog facility `%s'", + _("unknown syslog facility `%s'"), value->v.string); @@ -132,13 +132,13 @@ static struct grecs_keyword syslog_kw[] = { { "facility", - "name", - "Set syslog facility. Arg is one of the following: user, daemon, " - "auth, authpriv, mail, cron, local0 through local7 " - "(case-insensitive), or a facility number.", + N_("name"), + N_("Set syslog facility. Arg is one of the following: user, daemon, " + "auth, authpriv, mail, cron, local0 through local7 " + "(case-insensitive), or a facility number."), grecs_type_string, GRECS_DFLT, &facility, 0, cb_syslog_facility }, - { "tag", "string", "Tag syslog messages with this string", + { "tag", N_("string"), N_("Tag syslog messages with this string"), grecs_type_string, GRECS_DFLT, &tag }, - { "print-priority", "arg", - "Prefix each message with its priority", + { "print-priority", N_("arg"), + N_("Prefix each message with its priority"), grecs_type_bool, GRECS_DFLT, @@ -209,3 +209,3 @@ eventconf_flush(grecs_locus_t *loc) grecs_error(loc, 0, - "ignoring duplicate definition"); + _("ignoring duplicate definition")); return; @@ -243,3 +243,3 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, case grecs_callback_section_begin: - eventconf_init(&node->locus); + eventconf_init(); break; @@ -247,3 +247,3 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, if (!eventconf.pathlist) { - grecs_error(&node->locus, 0, "no paths configured"); + grecs_error(&node->locus, 0, _("no paths configured")); ++err; @@ -251,3 +251,4 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, if (!eventconf.command) { - grecs_error(&node->locus, 0, "no command configured"); + grecs_error(&node->locus, 0, + _("no command configured")); ++err; @@ -262,3 +263,4 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node, case grecs_callback_set_value: - grecs_error(&node->locus, 0, "invalid use of block statement"); + grecs_error(&node->locus, 0, + _("invalid use of block statement")); } @@ -307,3 +309,3 @@ cb_path(enum grecs_callback_command cmd, grecs_node_t *node, grecs_error(&val->v.arg.v[1]->locus, 0, - "expected \"recursive\" or end of statement"); + _("expected \"recursive\" or end of statement")); return 1; @@ -322,3 +324,3 @@ cb_path(enum grecs_callback_command cmd, grecs_node_t *node, grecs_error(&val->v.arg.v[3]->locus, 0, - "surplus argument"); + _("surplus argument")); return 1; @@ -328,3 +330,3 @@ cb_path(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_LIST: - grecs_error(locus, 0, "unexpected list"); + grecs_error(locus, 0, _("unexpected list")); return 1; @@ -359,3 +361,3 @@ cb_eventlist(enum grecs_callback_command cmd, grecs_node_t *node, grecs_error(&val->locus, 0, - "unrecognized event code"); + _("unrecognized event code")); return 1; @@ -374,3 +376,3 @@ cb_eventlist(enum grecs_callback_command cmd, grecs_node_t *node, grecs_error(&val->v.arg.v[i]->locus, 0, - "unrecognized event code"); + _("unrecognized event code")); return 1; @@ -389,3 +391,3 @@ cb_eventlist(enum grecs_callback_command cmd, grecs_node_t *node, grecs_error(&vp->locus, 0, - "unrecognized event code"); + _("unrecognized event code")); return 1; @@ -471,3 +473,3 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node, loc.end = val->v.arg.v[val->v.arg.c - 1]->locus.end; - grecs_error(&loc, 0, "surplus arguments"); + grecs_error(&loc, 0, _("surplus arguments")); return 1; @@ -479,3 +481,3 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node, case GRECS_TYPE_LIST: - grecs_error(locus, 0, "unexpected list"); + grecs_error(locus, 0, _("unexpected list")); return 1; @@ -485,3 +487,3 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node, if (!pw) { - grecs_error(&uv->locus, 0, "no such user"); + grecs_error(&uv->locus, 0, _("no such user")); return 1; @@ -492,3 +494,3 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node, if (!gr) { - grecs_error(&gv->locus, 0, "no such group"); + grecs_error(&gv->locus, 0, _("no such group")); return 1; @@ -531,3 +533,3 @@ cb_option(enum grecs_callback_command cmd, grecs_node_t *node, else - grecs_error(&vp->locus, 0, "unrecognized flag"); + grecs_error(&vp->locus, 0, _("unrecognized flag")); } @@ -609,3 +611,3 @@ file_name_pattern(struct grecs_list *lp, grecs_value_t *val) if (!p) { - grecs_error(&val->locus, 0, "Unterminated regexp"); + grecs_error(&val->locus, 0, _("unterminated regexp")); free(pat); @@ -623,3 +625,3 @@ file_name_pattern(struct grecs_list *lp, grecs_value_t *val) grecs_error(&val->locus, 0, - "Unrecognized flag: %c", *q); + _("unrecognized flag: %c"), *q); free(pat); @@ -691,22 +693,23 @@ cb_file_pattern(enum grecs_callback_command cmd, grecs_node_t *node, static struct grecs_keyword watcher_kw[] = { - { "path", NULL, "Pathname to watch", + { "path", NULL, N_("Pathname to watch"), grecs_type_string, GRECS_DFLT, &eventconf.pathlist, 0, cb_path }, - { "event", NULL, "Events to watch for", + { "event", NULL, N_("Events to watch for"), grecs_type_string, GRECS_LIST, &eventconf.eventmask, 0, cb_eventlist }, - { "file", "regexp", "Files to watch for", + { "file", N_("regexp"), N_("Files to watch for"), grecs_type_string, GRECS_LIST, &eventconf.fnames, 0, cb_file_pattern }, - { "command", NULL, "Command to execute on event", + { "command", NULL, N_("Command to execute on event"), grecs_type_string, GRECS_DFLT, &eventconf.command }, - { "user", "name", "Run command as this user", + { "user", N_("name"), N_("Run command as this user"), grecs_type_string, GRECS_DFLT, NULL, 0, cb_user }, - { "timeout", "seconds", "Timeout for the command", + { "timeout", N_("seconds"), N_("Timeout for the command"), grecs_type_uint, GRECS_DFLT, &eventconf.timeout }, - { "option", NULL, "List of additional options", + { "option", NULL, N_("List of additional options"), grecs_type_string, GRECS_LIST, NULL, 0, cb_option }, - { "environ", "<arg: string> <arg: string>...", "Modify environment", + { "environ", N_("<arg: string> <arg: string>..."), + N_("Modify environment"), grecs_type_string, GRECS_DFLT, NULL, 0, @@ -717,13 +720,13 @@ static struct grecs_keyword watcher_kw[] = { static struct grecs_keyword direvent_kw[] = { - { "user", NULL, "Run as this user", + { "user", NULL, N_("Run as this user"), grecs_type_string, GRECS_DFLT, &user }, - { "foreground", NULL, "Run in foreground", + { "foreground", NULL, N_("Run in foreground"), grecs_type_bool, GRECS_DFLT, &foreground }, - { "pidfile", "file", "Set pid file name", + { "pidfile", N_("file"), N_("Set pid file name"), grecs_type_string, GRECS_DFLT, &pidfile }, - { "syslog", NULL, "Configure syslog logging", + { "syslog", NULL, N_("Configure syslog logging"), grecs_type_section, GRECS_DFLT, NULL, 0, NULL, NULL, syslog_kw }, - { "debug", "level", "Set debug level", + { "debug", N_("level"), N_("Set debug level"), grecs_type_int, GRECS_DFLT, &debug_level }, - { "watcher", NULL, "Configure event watcher", + { "watcher", NULL, N_("Configure event watcher"), grecs_type_section, GRECS_DFLT, NULL, 0, @@ -738,4 +741,4 @@ config_help() static char docstring[] = - "Configuration file structure for direvent.\n" - "For more information, use `info direvent configuration'."; + N_("Configuration file structure for direvent.\n" + "For more information, use `info direvent configuration'."); grecs_print_docstring(docstring, 0, stdout); @@ -745,8 +748,2 @@ config_help() void -config_init() -{ - grecs_log_to_stderr = 1; -} - -void config_finish(struct grecs_node *tree) diff --git a/src/direvent.c b/src/direvent.c index 7cdd2c1..9dca000 100644 --- a/src/direvent.c +++ b/src/direvent.c @@ -140,3 +140,3 @@ emalloc(size_t size) if (!p) { - diag(LOG_CRIT, "not enough memory"); + diag(LOG_CRIT, _("not enough memory")); exit(2); @@ -162,3 +162,3 @@ erealloc(void *ptr, size_t size) if (!p) { - diag(LOG_CRIT, "not enough memory"); + diag(LOG_CRIT, _("not enough memory")); exit(2); @@ -270,3 +270,3 @@ storepid(const char *pidfile) if (!fp) { - diag(LOG_ERR, "cannot open pidfile %s for writing: %s", + diag(LOG_ERR, _("cannot open pidfile %s for writing: %s"), pidfile, strerror(errno)); @@ -298,3 +298,3 @@ get_user_groups(uid_t uid, size_t *pgidc, gid_t **pgidv) if (!pw) { - diag(LOG_ERR, 0, "no used with UID %lu", + diag(LOG_ERR, 0, _("no used with UID %lu"), (unsigned long)uid); @@ -425,3 +425,3 @@ self_test() diag(LOG_CRIT, - "cannot run `%s': fork failed: %s", + _("cannot run `%s': fork failed: %s"), self_test_prog, strerror(errno)); @@ -475,3 +475,3 @@ main(int argc, char **argv) default: - diag(LOG_CRIT, "too many arguments"); + diag(LOG_CRIT, _("too many arguments")); exit(1); @@ -521,3 +521,3 @@ main(int argc, char **argv) - diag(LOG_INFO, "%s %s started", program_name, VERSION); + diag(LOG_INFO, _("%s %s started"), program_name, VERSION); @@ -542,3 +542,3 @@ main(int argc, char **argv) - diag(LOG_INFO, "%s %s stopped", program_name, VERSION); + diag(LOG_INFO, _("%s %s stopped"), program_name, VERSION); diff --git a/src/direvent.h b/src/direvent.h index 33fa768..069d3d8 100644 --- a/src/direvent.h +++ b/src/direvent.h @@ -27,2 +27,7 @@ +#include "gettext.h" + +#define _(s) gettext(s) +#define N_(s) s + /* Generic (system-independent) event codes */ @@ -191,3 +196,6 @@ struct pathent { }; - + +void config_help(void); +struct grecs_node; +void config_finish(struct grecs_node *tree); void config_parse(const char *file); @@ -209,2 +217,5 @@ void unsplit_pathname(struct dirwatcher *dp); void ev_log(int flags, struct dirwatcher *dp); +void deliver_ev_create(struct dirwatcher *dp, const char *name); +int subwatcher_create(struct dirwatcher *parent, const char *dirname, + int isdir, int notify); diff --git a/src/environ.c b/src/environ.c index 5fbd0ac..f0fcce7 100644 --- a/src/environ.c +++ b/src/environ.c @@ -18,2 +18,3 @@ #include "wordsplit.h" +#include <ctype.h> @@ -23,3 +24,3 @@ extern char **environ; /* Environment */ if (debug_level >= (l)) { \ - diag(LOG_DEBUG, "environment: "); \ + diag(LOG_DEBUG, _("environment: ")); \ for (i = 0; (env)[i]; i++) \ diff --git a/src/gettext.h b/src/gettext.h new file mode 100644 index 0000000..e76b592 --- /dev/null +++ b/src/gettext.h @@ -0,0 +1,280 @@ +/* Convenience header for conditional use of GNU <libintl.h>. + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009 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 3, 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 + Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include <libintl.h> + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of <locale.h> a NOP. We don't include <libintl.h> + as well because people using "gettext.h" will not include <libintl.h>, + and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> + is OK. */ +#if defined(__sun) +# include <locale.h> +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + <libintl.h>, which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of <libintl.h> a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include <cstdlib> +# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H +# include <libintl.h> +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include <string.h> + +#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ + (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ + /* || __STDC_VERSION__ >= 199901L */ ) + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include <stdlib.h> +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (translation != msg_ctxt_id) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (!(translation == msg_ctxt_id || translation == msgid_plural)) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/src/hashtab.c b/src/hashtab.c index 0649ead..77edb95 100644 --- a/src/hashtab.c +++ b/src/hashtab.c @@ -139,7 +139,7 @@ hashtab_strerror(int rc) case ENOENT: - return "element not found in table"; + return _("element not found in table"); case E2BIG: - return "symbol table is full"; + return _("symbol table is full"); case ENOMEM: - return "out of memory"; + return _("out of memory"); } |