summary refs log tree commit diff
path: root/intl/loadmsgcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/loadmsgcat.c')
-rw-r--r--intl/loadmsgcat.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
new file mode 100644
index 0000000000..b05c630724
--- /dev/null
+++ b/intl/loadmsgcat.c
@@ -0,0 +1,184 @@
+/* loadmsgcat.c -- load needed message catalogs
+   Copyright (C) 1995 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 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 <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#endif
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP) || defined _LIBC
+# include <sys/mman.h>
+#endif
+
+#include "gettext.h"
+#include "gettextP.h"
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions.  This is required by the standard
+   because some ANSI C functions will require linking with this object
+   file and the name space must not be polluted.  */
+# define fstat  __fstat
+# define open   __open
+# define close  __close
+# define read   __read
+# define mmap   __mmap
+# define munmap __munmap
+#endif
+
+/* We need a sign, whether a new catalog was loaded, which can be associated
+   with all translations.  This is important if the translations are
+   cached by one of GCC's features.  */
+int _nl_msg_cat_cntr;
+
+
+/* Load the message catalogs specified by FILENAME.  If it is no valid
+   message catalog do nothing.  */
+void
+_nl_load_domain (domain)
+     struct loaded_domain *domain;
+{
+  int fd;
+  struct stat st;
+  struct mo_file_header *data = (struct mo_file_header *) -1;
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+    || defined _LIBC
+  int use_mmap = 0;
+#endif
+
+  domain->decided = 1;
+  domain->data = NULL;
+
+  /* Try to open the addressed file.  */
+  fd = open (domain->filename, O_RDONLY);
+  if (fd == -1)
+    return;
+
+  /* We must know about the size of the file.  */
+  if (fstat (fd, &st) != 0
+      && st.st_size < (off_t) sizeof (struct mo_file_header))
+    {
+      /* Something went wrong.  */
+      close (fd);
+      return;
+    }
+
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+    || defined _LIBC
+  /* Now we are ready to load the file.  If mmap() is available we try
+     this first.  If not available or it failed we try to load it.  */
+  data = (struct mo_file_header *) mmap (NULL, st.st_size, PROT_READ,
+					 MAP_PRIVATE, fd, 0);
+
+  if (data != (struct mo_file_header *) -1)
+    {
+      /* mmap() call was successful.  */
+      close (fd);
+      use_mmap = 1;
+    }
+#endif
+
+  /* If the data is not yet available (i.e. mmap'ed) we try to load
+     it manually.  */
+  if (data == (struct mo_file_header *) -1)
+    {
+      off_t to_read;
+      char *read_ptr;
+
+      data = (struct mo_file_header *) malloc (st.st_size);
+      if (data == NULL)
+	return;
+
+      to_read = st.st_size;
+      read_ptr = (char *) data;
+      do
+	{
+	  long int nb = (long int) read (fd, read_ptr, to_read);
+	  if (nb == -1)
+	    {
+	      close (fd);
+	      return;
+	    }
+
+	  read_ptr += nb;
+	  to_read -= nb;
+	}
+      while (to_read > 0);
+
+      close (fd);
+    }
+
+  /* Using the magic number we can test whether it really is a message
+     catalog file.  */
+  if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
+    {
+      /* The magic number is wrong: not a message catalog file.  */
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+    || defined _LIBC
+      if (use_mmap)
+	munmap ((caddr_t) data, st.st_size);
+      else
+#endif
+	free (data);
+      return;
+    }
+
+  domain->data = (char *) data;
+  domain->must_swap = data->magic != _MAGIC;
+
+  /* Fill in the information about the available tables.  */
+  switch (W (domain->must_swap, data->revision))
+    {
+    case 0:
+      domain->nstrings = W (domain->must_swap, data->nstrings);
+      domain->orig_tab = (struct string_desc *)
+	((char *) data + W (domain->must_swap, data->orig_tab_offset));
+      domain->trans_tab = (struct string_desc *)
+	((char *) data + W (domain->must_swap, data->trans_tab_offset));
+      domain->hash_size = W (domain->must_swap, data->hash_tab_size);
+      domain->hash_tab = (nls_uint32 *)
+	((char *) data + W (domain->must_swap, data->hash_tab_offset));
+      break;
+    default:
+      /* This is an illegal revision.  */
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+    || defined _LIBC
+      if (use_mmap)
+	munmap ((caddr_t) data, st.st_size);
+      else
+#endif
+	free (data);
+      domain->data = NULL;
+      return;
+    }
+
+  /* Show that one domain is changed.  This might make some cached
+     translation invalid.  */
+  ++_nl_msg_cat_cntr;
+}