• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
libintl.cpp
1 /* libintl.cpp -- gettext related functions from glibc-2.0.5
2  Copyright (C) 1995 Software Foundation, Inc.
3 
4 This file is part of the KDE libraries, but it's derived work out
5 of glibc. The master sources can be found in
6 
7  bindtextdom.c
8  dcgettext.c
9  dgettext.c
10  explodename.c
11  finddomain.c
12  gettext.c
13  gettext.h
14  gettextP.h
15  hash-string.h
16  l10nflist.c
17  libintl.h
18  loadinfo.h
19  loadmsgcat.c
20  localealias.c
21  textdomain.c
22 
23 which are part of glibc. The license is the same as in GLIBC, which
24 is the GNU Library General Public License. See COPYING.LIB for more
25 details.
26 
27 */
28 
29 /* gettext.c -- implementation of gettext(3) function
30  Copyright (C) 1995 Software Foundation, Inc.
31 
32 This file is part of the GNU C Library. Its master source is NOT part of
33 the C library, however. The master source lives in /gd/gnu/lib.
34 
35 The GNU C Library is free software; you can redistribute it and/or
36 modify it under the terms of the GNU Library General Public License as
37 published by the Free Software Foundation; either version 2 of the
38 License, or (at your option) any later version.
39 
40 The GNU C Library is distributed in the hope that it will be useful,
41 but WITHOUT ANY WARRANTY; without even the implied warranty of
42 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43 Library General Public License for more details.
44 
45 You should have received a copy of the GNU Library General Public
46 License along with the GNU C Library; see the file COPYING.LIB. If
47 not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
48 Boston, MA 02110-1301, USA. */
49 
50 #include "tdelibs_export.h"
51 #include "kde_file.h"
52 #include <config.h>
53 
54 #include <tqglobal.h>
55 
56 #include <stdlib.h>
57 
58 #if defined HAVE_STRING_H
59 # include <string.h>
60 #else
61 # include <strings.h>
62 #endif
63 
64 #include <sys/types.h>
65 #include <fcntl.h>
66 #include <sys/stat.h>
67 
68 #if defined HAVE_UNISTD_H
69 # include <unistd.h>
70 #endif
71 
72 #if (defined HAVE_MMAP && defined HAVE_MUNMAP)
73 # include <sys/mman.h>
74 #endif
75 
76 #ifndef W
77 # define W(flag, data) ((flag) ? SWAP (data) : (data))
78 #endif
79 
80 typedef TQ_UINT32 nls_uint32;
81 
82 struct loaded_domain
83 {
84  const char *data;
85 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
86  int use_mmap;
87  size_t mmap_size;
88 #endif
89  int must_swap;
90  nls_uint32 nstrings;
91  struct string_desc *orig_tab;
92  struct string_desc *trans_tab;
93  nls_uint32 hash_size;
94  nls_uint32 *hash_tab;
95 };
96 
97 struct kde_loaded_l10nfile
98 {
99  const char *filename;
100  int decided;
101 
102  const void *data;
103 
104  kde_loaded_l10nfile() : filename(0), decided(0), data(0) {}
105 };
106 
107 void k_nl_load_domain(struct kde_loaded_l10nfile *__domain);
108 
109 static inline nls_uint32
110 SWAP (nls_uint32 i)
111 {
112  return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
113 }
114 
115 /* @@ end of prolog @@ */
116 
117 /* The magic number of the GNU message catalog format. */
118 #define _MAGIC 0x950412de
119 #define _MAGIC_SWAPPED 0xde120495
120 
121 /* Revision number of the currently used .mo (binary) file format. */
122 #define MO_REVISION_NUMBER 0
123 
124 
125 /* Defines the so called `hashpjw' function by P.J. Weinberger
126  [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
127  1986, 1987 Bell Telephone Laboratories, Inc.] */
128 static inline unsigned long hash_string (const char *__str_param);
129 
130 /* @@ end of prolog @@ */
131 
132 /* Header for binary .mo file format. */
133 struct mo_file_header
134 {
135  /* The magic number. */
136  nls_uint32 magic;
137  /* The revision number of the file format. */
138  nls_uint32 revision;
139  /* The number of strings pairs. */
140  nls_uint32 nstrings;
141  /* Offset of table with start offsets of original strings. */
142  nls_uint32 orig_tab_offset;
143  /* Offset of table with start offsets of translation strings. */
144  nls_uint32 trans_tab_offset;
145  /* Size of hashing table. */
146  nls_uint32 hash_tab_size;
147  /* Offset of first hashing entry. */
148  nls_uint32 hash_tab_offset;
149 };
150 
151 struct string_desc
152 {
153  /* Length of addressed string. */
154  nls_uint32 length;
155  /* Offset of string in file. */
156  nls_uint32 offset;
157 };
158 
159 /* Prototypes for local functions. */
160 char *k_nl_find_msg (struct kde_loaded_l10nfile *domain_file,
161  const char *msgid);
162 
163 char *
164 k_nl_find_msg (struct kde_loaded_l10nfile *domain_file, const char *msgid)
165 {
166  size_t top, act, bottom;
167  struct loaded_domain *domain;
168 
169  if (domain_file->decided == 0)
170  k_nl_load_domain (domain_file);
171 
172  if (domain_file->data == NULL)
173  return NULL;
174 
175  domain = (struct loaded_domain *) domain_file->data;
176 
177  /* Locate the MSGID and its translation. */
178  if (domain->hash_size > 2 && domain->hash_tab != NULL)
179  {
180  /* Use the hashing table. */
181  nls_uint32 len = strlen (msgid);
182  nls_uint32 hash_val = hash_string (msgid);
183  nls_uint32 idx = hash_val % domain->hash_size;
184  nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
185  nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
186 
187  if (nstr == 0)
188  /* Hash table entry is empty. */
189  return NULL;
190 
191  if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
192  && strcmp (msgid,
193  domain->data + W (domain->must_swap,
194  domain->orig_tab[nstr - 1].offset)) == 0)
195  return (char *) domain->data + W (domain->must_swap,
196  domain->trans_tab[nstr - 1].offset);
197 
198  while (1)
199  {
200  if (idx >= domain->hash_size - incr)
201  idx -= domain->hash_size - incr;
202  else
203  idx += incr;
204 
205  nstr = W (domain->must_swap, domain->hash_tab[idx]);
206  if (nstr == 0)
207  /* Hash table entry is empty. */
208  return NULL;
209 
210  if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
211  && strcmp (msgid,
212  domain->data + W (domain->must_swap,
213  domain->orig_tab[nstr - 1].offset))
214  == 0)
215  return (char *) domain->data
216  + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
217  }
218  /* NOTREACHED */
219  }
220 
221  /* Now we try the default method: binary search in the sorted
222  array of messages. */
223  bottom = 0;
224  top = domain->nstrings;
225  act = top;
226  while (bottom < top)
227  {
228  int cmp_val;
229 
230  act = (bottom + top) / 2;
231  cmp_val = strcmp (msgid, domain->data
232  + W (domain->must_swap,
233  domain->orig_tab[act].offset));
234  if (cmp_val < 0)
235  top = act;
236  else if (cmp_val > 0)
237  bottom = act + 1;
238  else
239  break;
240  }
241 
242  /* If an translation is found return this. */
243  return bottom >= top ? NULL : (char *) domain->data
244  + W (domain->must_swap,
245  domain->trans_tab[act].offset);
246 }
247 
248 /* @@ begin of epilog @@ */
249 /* We assume to have `unsigned long int' value with at least 32 bits. */
250 #define HASHWORDBITS 32
251 
252 static inline unsigned long
253 hash_string (const char *str_param)
254 {
255  unsigned long int hval, g;
256  const char *str = str_param;
257 
258  /* Compute the hash value for the given string. */
259  hval = 0;
260  while (*str != '\0')
261  {
262  hval <<= 4;
263  hval += (unsigned char) *str++;
264  g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
265  if (g != 0)
266  {
267  hval ^= g >> (HASHWORDBITS - 8);
268  hval ^= g;
269  }
270  }
271  return hval;
272 }
273 
274 /* Load the message catalogs specified by FILENAME. If it is no valid
275  message catalog do nothing. */
276 void
277 k_nl_load_domain (struct kde_loaded_l10nfile *domain_file)
278 {
279  int fd;
280  struct stat st;
281  struct mo_file_header *data = (struct mo_file_header *) -1;
282 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
283  int use_mmap = 0;
284 #endif
285  struct loaded_domain *domain;
286 
287  domain_file->decided = 1;
288  domain_file->data = NULL;
289 
290  /* If the record does not represent a valid locale the FILENAME
291  might be NULL. This can happen when according to the given
292  specification the locale file name is different for XPG and CEN
293  syntax. */
294  if (domain_file->filename == NULL)
295  return;
296 
297  /* Try to open the addressed file. */
298  fd = KDE_open (domain_file->filename, O_RDONLY);
299  if (fd == -1)
300  return;
301 
302  /* We must know about the size of the file. */
303  if (fstat (fd, &st) != 0
304  || st.st_size < (off_t) sizeof (struct mo_file_header))
305  {
306  /* Something went wrong. */
307  close (fd);
308  return;
309  }
310 
311 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
312  /* Now we are ready to load the file. If mmap() is available we try
313  this first. If not available or it failed we try to load it. */
314  data = (struct mo_file_header *) mmap (NULL, st.st_size, PROT_READ,
315  MAP_PRIVATE, fd, 0);
316 
317  if (data != (struct mo_file_header *) -1)
318  {
319  /* mmap() call was successful. */
320  close (fd);
321  use_mmap = 1;
322  }
323 #endif
324 
325  /* If the data is not yet available (i.e. mmap'ed) we try to load
326  it manually. */
327  if (data == (struct mo_file_header *) -1)
328  {
329  off_t to_read;
330  char *read_ptr;
331 
332  data = (struct mo_file_header *) malloc (st.st_size);
333  if (data == NULL)
334  return;
335 
336  to_read = st.st_size;
337  read_ptr = (char *) data;
338  do
339  {
340  long int nb = (long int) read (fd, read_ptr, to_read);
341  if (nb == -1)
342  {
343  close (fd);
344  return;
345  }
346 
347  read_ptr += nb;
348  to_read -= nb;
349  }
350  while (to_read > 0);
351 
352  close (fd);
353  }
354 
355  /* Using the magic number we can test whether it really is a message
356  catalog file. */
357  if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
358  {
359  /* The magic number is wrong: not a message catalog file. */
360 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
361  if (use_mmap)
362  munmap ((char *) data, st.st_size);
363  else
364 #endif
365  free (data);
366  return;
367  }
368 
369  domain_file->data
370  = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
371  if (domain_file->data == NULL)
372  return;
373 
374  domain = (struct loaded_domain *) domain_file->data;
375  domain->data = (char *) data;
376 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
377  domain->use_mmap = use_mmap;
378  domain->mmap_size = st.st_size;
379 #endif
380  domain->must_swap = data->magic != _MAGIC;
381 
382  /* Fill in the information about the available tables. */
383  switch (W (domain->must_swap, data->revision))
384  {
385  case 0:
386  domain->nstrings = W (domain->must_swap, data->nstrings);
387  domain->orig_tab = (struct string_desc *)
388  ((char *) data + W (domain->must_swap, data->orig_tab_offset));
389  domain->trans_tab = (struct string_desc *)
390  ((char *) data + W (domain->must_swap, data->trans_tab_offset));
391  domain->hash_size = W (domain->must_swap, data->hash_tab_size);
392  domain->hash_tab = (nls_uint32 *)
393  ((char *) data + W (domain->must_swap, data->hash_tab_offset));
394  break;
395  default:
396  /* This is an illegal revision. */
397 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
398  if (use_mmap)
399  munmap ((char *) data, st.st_size);
400  else
401 #endif
402  free (data);
403  free (domain);
404  domain_file->data = NULL;
405  return;
406  }
407 }
408 
409 void
410 k_nl_unload_domain (struct loaded_domain *domain)
411 {
412 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP)
413  if (domain->use_mmap)
414  munmap ((caddr_t) domain->data, domain->mmap_size);
415  else
416 # endif
417  free ((void *) domain->data);
418 
419  free (domain);
420 }
KStdAction::close
TDEAction * close(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.1
This website is maintained by Timothy Pearson.