• 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
4This file is part of the KDE libraries, but it's derived work out
5of 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
23which are part of glibc. The license is the same as in GLIBC, which
24is the GNU Library General Public License. See COPYING.LIB for more
25details.
26
27*/
28
29/* gettext.c -- implementation of gettext(3) function
30 Copyright (C) 1995 Software Foundation, Inc.
31
32This file is part of the GNU C Library. Its master source is NOT part of
33the C library, however. The master source lives in /gd/gnu/lib.
34
35The GNU C Library is free software; you can redistribute it and/or
36modify it under the terms of the GNU Library General Public License as
37published by the Free Software Foundation; either version 2 of the
38License, or (at your option) any later version.
39
40The GNU C Library is distributed in the hope that it will be useful,
41but WITHOUT ANY WARRANTY; without even the implied warranty of
42MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43Library General Public License for more details.
44
45You should have received a copy of the GNU Library General Public
46License along with the GNU C Library; see the file COPYING.LIB. If
47not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
48Boston, 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
80typedef TQ_UINT32 nls_uint32;
81
82struct 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
97struct 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
107void k_nl_load_domain(struct kde_loaded_l10nfile *__domain);
108
109static inline nls_uint32
110SWAP (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.] */
128static inline unsigned long hash_string (const char *__str_param);
129
130/* @@ end of prolog @@ */
131
132/* Header for binary .mo file format. */
133struct 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
151struct 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. */
160char *k_nl_find_msg (struct kde_loaded_l10nfile *domain_file,
161 const char *msgid);
162
163char *
164k_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
252static inline unsigned long
253hash_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. */
276void
277k_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
409void
410k_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.4
This website is maintained by Timothy Pearson.