* i18n.c: Handle --disable-nls (thanks Bruno).
authorMarius Vollmer <mvo@zagadka.de>
Wed, 22 Sep 2004 21:54:50 +0000 (21:54 +0000)
committerMarius Vollmer <mvo@zagadka.de>
Wed, 22 Sep 2004 21:54:50 +0000 (21:54 +0000)
* posix.c (scm_init_posix): Add LC_PAPER, LC_NAME, LC_ADDRESS,
LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION.

* i18n.c (scm_i_to_lc_category): New name and export.  Support all
LC categories.

* posix.c (s_scm_setlocale): Use it.

* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
scm_bind_textdomain_codeset): Make wrappers similar to C function
they wrap.

* i18n.h: New file.
* i18n.c: New file.
* gettext.h: New file, taken from GNU gettext.
* init.c: Include libguile/i18n.h.
(scm_init_guile_1): Add call to scm_init_i18n().
* Makefile.am (libguile_la_SOURCES): Add i18n.c.
(DOT_X_FILES): Add i18n.x.
(DOT_DOC_FILES): Add i18n.doc.
(libguile_la_LDFLAGS): Add @LTLIBINTL@.
(modinclude_HEADERS): Add i18n.h.

libguile/gettext.h [new file with mode: 0644]
libguile/i18n.c [new file with mode: 0644]
libguile/i18n.h [new file with mode: 0644]
libguile/init.c
libguile/posix.c

diff --git a/libguile/gettext.h b/libguile/gettext.h
new file mode 100644 (file)
index 0000000..8b262f4
--- /dev/null
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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.  */
+
+#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>
+
+#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
+
+/* 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".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((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
+
+#endif /* _LIBGETTEXT_H */
diff --git a/libguile/i18n.c b/libguile/i18n.c
new file mode 100644 (file)
index 0000000..58c837c
--- /dev/null
@@ -0,0 +1,327 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "libguile/dynwind.h"
+
+#include "gettext.h"
+#include <locale.h>
+
+
+int
+scm_i_to_lc_category (SCM category, int allow_lc_all)
+{
+  int c_category = scm_to_int (category);
+  switch (c_category)
+    {
+#ifdef LC_CTYPE
+    case LC_CTYPE:
+#endif
+#ifdef LC_NUMERIC
+    case LC_NUMERIC:
+#endif
+#ifdef LC_COLLATE
+    case LC_COLLATE:
+#endif
+#ifdef LC_TIME
+    case LC_TIME:
+#endif
+#ifdef LC_MONETARY
+    case LC_MONETARY:
+#endif
+#ifdef LC_MESSAGES
+    case LC_MESSAGES:
+#endif
+#ifdef LC_PAPER
+    case LC_PAPER:
+#endif
+#ifdef LC_NAME
+    case LC_NAME:
+#endif
+#ifdef LC_ADDRESS
+    case LC_ADDRESS:
+#endif
+#ifdef LC_TELEPHONE
+    case LC_TELEPHONE:
+#endif
+#ifdef LC_MEASUREMENT
+    case LC_MEASUREMENT:
+#endif
+#ifdef LC_IDENTIFICATION
+    case LC_IDENTIFICATION:
+#endif
+      return c_category;
+#ifdef LC_ALL
+    case LC_ALL:
+      if (allow_lc_all)
+       return c_category;
+#endif  
+    }
+  scm_wrong_type_arg (0, 0, category);
+}
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+           (SCM msgid, SCM domain, SCM category),
+           "Return the translation of @var{msgid} in the message domain "
+           "@var{domain}. @var{domain} is optional and defaults to the "
+           "domain set through (textdomain).  @var{category} is optional "
+           "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  char const *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  c_msgid = scm_to_locale_string (msgid);
+  scm_frame_free (c_msgid);
+
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      c_result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      c_domain = scm_to_locale_string (domain);
+      scm_frame_free (c_domain);
+
+      if (SCM_UNBNDP (category))
+       {
+         /* 2 argument case.  */
+         c_result = dgettext (c_domain, c_msgid);
+       }
+      else
+       {
+         /* 3 argument case.  */
+         int c_category;
+
+         c_category = scm_i_to_lc_category (category, 0);
+         c_result = dcgettext (c_domain, c_msgid, c_category);
+       }
+    }
+
+  if (c_result == c_msgid)
+    result = msgid;
+  else
+    result = scm_from_locale_string (c_result);
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+           (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+           "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+           "message domain @var{domain}, with the plural form being chosen "
+           "appropriately for the number @var{n}.  @var{domain} is optional "
+           "and defaults to the domain set through (textdomain). "
+           "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  c_msgid = scm_to_locale_string (msgid);
+  scm_frame_free (c_msgid);
+
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  scm_frame_free (c_msgid_plural);
+
+  c_n = scm_to_ulong (n);
+
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      c_result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      c_domain = scm_to_locale_string (domain);
+      scm_frame_free (c_domain);
+
+      if (SCM_UNBNDP (category))
+       {
+         /* 4 argument case.  */
+         c_result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+       }
+      else
+       {
+         /* 5 argument case.  */
+         int c_category;
+
+         c_category = scm_i_to_lc_category (category, 0);
+         c_result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+                                c_category);
+       }
+    }
+
+  if (c_result == c_msgid)
+    result = msgid;
+  else if (c_result == c_msgid_plural)
+    result = msgid_plural;
+  else
+    result = scm_from_locale_string (c_result);
+  
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+           (SCM domainname),
+           "If optional parameter @var{domainname} is supplied, "
+           "set the textdomain.  "
+           "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char const *c_result;
+  char *c_domain;
+  SCM result = SCM_BOOL_F;
+
+  scm_frame_begin (0);
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      c_domain = scm_to_locale_string (domainname);
+      scm_frame_free (c_domain);
+    }
+
+  c_result = textdomain (c_domain);
+  if (c_result != NULL)
+    result = scm_from_locale_string (c_result);
+  else if (!SCM_UNBNDP (domainname))
+    SCM_SYSERROR;
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+           (SCM domainname, SCM directory),
+           "If optional parameter @var{directory} is supplied, "
+           "set message catalogs to directory @{directory}.  "
+           "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      c_directory = scm_to_locale_string (directory);
+      scm_frame_free (c_directory);
+    }
+
+  c_domain = scm_to_locale_string (domainname);
+  scm_frame_free (c_domain);
+
+  c_result = bindtextdomain (c_domain, c_directory);
+
+  if (c_result != NULL)
+    result = scm_from_locale_string (c_result);
+  else if (!SCM_UNBNDP (directory))
+    SCM_SYSERROR;
+  else
+    result = SCM_BOOL_F;
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+           (SCM domainname, SCM encoding),
+           "If optional parameter @var{encoding} is supplied, "
+           "set encoding for message catalogs of @{domainname}.  "
+           "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      c_encoding = scm_to_locale_string (encoding);
+      scm_frame_free (c_encoding);
+    }
+
+  c_domain = scm_to_locale_string (domainname);
+  scm_frame_free (c_domain);
+
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+
+  if (c_result != NULL)
+    result = scm_from_locale_string (c_result);
+  else if (!SCM_UNBNDP (encoding))
+    SCM_SYSERROR;
+  else
+    result = SCM_BOOL_F;
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
diff --git a/libguile/i18n.h b/libguile/i18n.h
new file mode 100644 (file)
index 0000000..07aa1f0
--- /dev/null
@@ -0,0 +1,41 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "libguile/__scm.h"
+
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+
+SCM_API int scm_i_to_lc_category (SCM category, int allow_lc_all);
+
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
index 7e6f3fc..789412f 100644 (file)
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();              /* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
index 3c16b37..0ffd85b 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "libguile/validate.h"
 #include "libguile/posix.h"
+#include "libguile/i18n.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -1365,7 +1366,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
       scm_frame_free (clocale);
     }
 
-  rv = setlocale (scm_to_int (category), clocale);
+  rv = setlocale (scm_i_to_lc_category (category, 1), clocale);
   if (rv == NULL)
     SCM_SYSERROR;
 
@@ -1929,6 +1930,24 @@ scm_init_posix ()
 #ifdef LC_ALL
   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
 #endif
+#ifdef LC_PAPER
+  scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#endif
+#ifdef LC_NAME
+  scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#endif
+#ifdef LC_ADDRESS
+  scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#endif
+#ifdef LC_TELEPHONE
+  scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#endif
+#ifdef LC_MEASUREMENT
+  scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#endif
+#ifdef LC_IDENTIFICATION
+  scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#endif
 #ifdef PIPE_BUF
   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
 #endif