aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2014-08-25 19:13:37 +0300
committerSergey Poznyakoff <gray@gnu.org>2014-08-25 19:20:00 +0300
commite26cb120ffe5f7303ddd8b514246ac6874e83f9f (patch)
tree64ca646b34103a5e8934b42fbbd9ca732a14e034
parent713bc0ca4b4ea3114d33f06c57c117de7f9fef11 (diff)
downloaddirevent-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--.gitignore1
-rw-r--r--Makefile.am6
-rw-r--r--acinclude.m444
-rwxr-xr-xbootstrap1
-rw-r--r--configure.ac9
-rw-r--r--doc/direvent.texi12
m---------grecs0
-rw-r--r--po/.gitignore20
-rw-r--r--po/Makevars41
-rw-r--r--po/POTFILES.in9
-rw-r--r--src/Makefile.am3
-rw-r--r--src/config.c103
-rw-r--r--src/direvent.c16
-rw-r--r--src/direvent.h13
-rw-r--r--src/environ.c3
-rw-r--r--src/gettext.h280
-rw-r--r--src/hashtab.c6
-rw-r--r--src/progman.c32
-rw-r--r--src/watcher.c28
-rw-r--r--tests/re05.at2
20 files changed, 524 insertions, 105 deletions
diff --git a/.gitignore b/.gitignore
index 0417a59..771518c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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])
+])
+
diff --git a/bootstrap b/bootstrap
index ae677ac..8a0292b 100755
--- a/bootstrap
+++ b/bootstrap
@@ -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");
}
diff --git a/src/progman.c b/src/progman.c
index f32e896..7da13b1 100644
--- a/src/progman.c
+++ b/