• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Load needed message catalogs.
2    Copyright (C) 1995-2020 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU Lesser General Public License as published by
6    the Free Software Foundation; either version 2.1 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
18    This must come before <config.h> because <config.h> may include
19    <features.h>, and once <features.h> has been included, it's too late.  */
20 #ifndef _GNU_SOURCE
21 # define _GNU_SOURCE    1
22 #endif
23 
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27 
28 #include <assert.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 
35 #ifdef __GNUC__
36 # undef  alloca
37 # define alloca __builtin_alloca
38 # define HAVE_ALLOCA 1
39 #else
40 # ifdef _MSC_VER
41 #  include <malloc.h>
42 #  define alloca _alloca
43 # else
44 #  if defined HAVE_ALLOCA_H || defined _LIBC
45 #   include <alloca.h>
46 #  else
47 #   ifdef _AIX
48  #pragma alloca
49 #   else
50 #    ifndef alloca
51 char *alloca ();
52 #    endif
53 #   endif
54 #  endif
55 # endif
56 #endif
57 
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #if defined HAVE_UNISTD_H || defined _LIBC
62 # include <unistd.h>
63 #endif
64 
65 #ifdef _LIBC
66 # include <langinfo.h>
67 # include <locale.h>
68 #endif
69 
70 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
71     || (defined _LIBC && defined _POSIX_MAPPED_FILES)
72 # include <sys/mman.h>
73 # undef HAVE_MMAP
74 # define HAVE_MMAP	1
75 #else
76 # undef HAVE_MMAP
77 #endif
78 
79 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
80 # include <stdint.h>
81 #endif
82 #if defined HAVE_INTTYPES_H || defined _LIBC
83 # include <inttypes.h>
84 #endif
85 
86 #include "gmo.h"
87 #include "gettextP.h"
88 #include "hash-string.h"
89 #include "plural-exp.h"
90 
91 #ifdef _LIBC
92 # include "../locale/localeinfo.h"
93 # include <not-cancel.h>
94 #endif
95 
96 /* Handle multi-threaded applications.  */
97 #ifdef _LIBC
98 # include <bits/libc-lock.h>
99 #else
100 # include "lock.h"
101 #endif
102 
103 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
104    Note that our fallback values need not be literal strings, because we don't
105    use them with preprocessor string concatenation.  */
106 #if !defined PRId8
107 # define PRId8 "d"
108 #endif
109 #if !defined PRIi8
110 # define PRIi8 "i"
111 #endif
112 #if !defined PRIo8
113 # define PRIo8 "o"
114 #endif
115 #if !defined PRIu8
116 # define PRIu8 "u"
117 #endif
118 #if !defined PRIx8
119 # define PRIx8 "x"
120 #endif
121 #if !defined PRIX8
122 # define PRIX8 "X"
123 #endif
124 #if !defined PRId16
125 # define PRId16 "d"
126 #endif
127 #if !defined PRIi16
128 # define PRIi16 "i"
129 #endif
130 #if !defined PRIo16
131 # define PRIo16 "o"
132 #endif
133 #if !defined PRIu16
134 # define PRIu16 "u"
135 #endif
136 #if !defined PRIx16
137 # define PRIx16 "x"
138 #endif
139 #if !defined PRIX16
140 # define PRIX16 "X"
141 #endif
142 #if !defined PRId32
143 # define PRId32 "d"
144 #endif
145 #if !defined PRIi32
146 # define PRIi32 "i"
147 #endif
148 #if !defined PRIo32
149 # define PRIo32 "o"
150 #endif
151 #if !defined PRIu32
152 # define PRIu32 "u"
153 #endif
154 #if !defined PRIx32
155 # define PRIx32 "x"
156 #endif
157 #if !defined PRIX32
158 # define PRIX32 "X"
159 #endif
160 #if !defined PRId64
161 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
162 #endif
163 #if !defined PRIi64
164 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
165 #endif
166 #if !defined PRIo64
167 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
168 #endif
169 #if !defined PRIu64
170 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
171 #endif
172 #if !defined PRIx64
173 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
174 #endif
175 #if !defined PRIX64
176 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
177 #endif
178 #if !defined PRIdLEAST8
179 # define PRIdLEAST8 "d"
180 #endif
181 #if !defined PRIiLEAST8
182 # define PRIiLEAST8 "i"
183 #endif
184 #if !defined PRIoLEAST8
185 # define PRIoLEAST8 "o"
186 #endif
187 #if !defined PRIuLEAST8
188 # define PRIuLEAST8 "u"
189 #endif
190 #if !defined PRIxLEAST8
191 # define PRIxLEAST8 "x"
192 #endif
193 #if !defined PRIXLEAST8
194 # define PRIXLEAST8 "X"
195 #endif
196 #if !defined PRIdLEAST16
197 # define PRIdLEAST16 "d"
198 #endif
199 #if !defined PRIiLEAST16
200 # define PRIiLEAST16 "i"
201 #endif
202 #if !defined PRIoLEAST16
203 # define PRIoLEAST16 "o"
204 #endif
205 #if !defined PRIuLEAST16
206 # define PRIuLEAST16 "u"
207 #endif
208 #if !defined PRIxLEAST16
209 # define PRIxLEAST16 "x"
210 #endif
211 #if !defined PRIXLEAST16
212 # define PRIXLEAST16 "X"
213 #endif
214 #if !defined PRIdLEAST32
215 # define PRIdLEAST32 "d"
216 #endif
217 #if !defined PRIiLEAST32
218 # define PRIiLEAST32 "i"
219 #endif
220 #if !defined PRIoLEAST32
221 # define PRIoLEAST32 "o"
222 #endif
223 #if !defined PRIuLEAST32
224 # define PRIuLEAST32 "u"
225 #endif
226 #if !defined PRIxLEAST32
227 # define PRIxLEAST32 "x"
228 #endif
229 #if !defined PRIXLEAST32
230 # define PRIXLEAST32 "X"
231 #endif
232 #if !defined PRIdLEAST64
233 # define PRIdLEAST64 PRId64
234 #endif
235 #if !defined PRIiLEAST64
236 # define PRIiLEAST64 PRIi64
237 #endif
238 #if !defined PRIoLEAST64
239 # define PRIoLEAST64 PRIo64
240 #endif
241 #if !defined PRIuLEAST64
242 # define PRIuLEAST64 PRIu64
243 #endif
244 #if !defined PRIxLEAST64
245 # define PRIxLEAST64 PRIx64
246 #endif
247 #if !defined PRIXLEAST64
248 # define PRIXLEAST64 PRIX64
249 #endif
250 #if !defined PRIdFAST8
251 # define PRIdFAST8 "d"
252 #endif
253 #if !defined PRIiFAST8
254 # define PRIiFAST8 "i"
255 #endif
256 #if !defined PRIoFAST8
257 # define PRIoFAST8 "o"
258 #endif
259 #if !defined PRIuFAST8
260 # define PRIuFAST8 "u"
261 #endif
262 #if !defined PRIxFAST8
263 # define PRIxFAST8 "x"
264 #endif
265 #if !defined PRIXFAST8
266 # define PRIXFAST8 "X"
267 #endif
268 #if !defined PRIdFAST16
269 # define PRIdFAST16 "d"
270 #endif
271 #if !defined PRIiFAST16
272 # define PRIiFAST16 "i"
273 #endif
274 #if !defined PRIoFAST16
275 # define PRIoFAST16 "o"
276 #endif
277 #if !defined PRIuFAST16
278 # define PRIuFAST16 "u"
279 #endif
280 #if !defined PRIxFAST16
281 # define PRIxFAST16 "x"
282 #endif
283 #if !defined PRIXFAST16
284 # define PRIXFAST16 "X"
285 #endif
286 #if !defined PRIdFAST32
287 # define PRIdFAST32 "d"
288 #endif
289 #if !defined PRIiFAST32
290 # define PRIiFAST32 "i"
291 #endif
292 #if !defined PRIoFAST32
293 # define PRIoFAST32 "o"
294 #endif
295 #if !defined PRIuFAST32
296 # define PRIuFAST32 "u"
297 #endif
298 #if !defined PRIxFAST32
299 # define PRIxFAST32 "x"
300 #endif
301 #if !defined PRIXFAST32
302 # define PRIXFAST32 "X"
303 #endif
304 #if !defined PRIdFAST64
305 # define PRIdFAST64 PRId64
306 #endif
307 #if !defined PRIiFAST64
308 # define PRIiFAST64 PRIi64
309 #endif
310 #if !defined PRIoFAST64
311 # define PRIoFAST64 PRIo64
312 #endif
313 #if !defined PRIuFAST64
314 # define PRIuFAST64 PRIu64
315 #endif
316 #if !defined PRIxFAST64
317 # define PRIxFAST64 PRIx64
318 #endif
319 #if !defined PRIXFAST64
320 # define PRIXFAST64 PRIX64
321 #endif
322 #if !defined PRIdMAX
323 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
324 #endif
325 #if !defined PRIiMAX
326 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
327 #endif
328 #if !defined PRIoMAX
329 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
330 #endif
331 #if !defined PRIuMAX
332 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
333 #endif
334 #if !defined PRIxMAX
335 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
336 #endif
337 #if !defined PRIXMAX
338 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
339 #endif
340 #if !defined PRIdPTR
341 # define PRIdPTR \
342   (sizeof (void *) == sizeof (long) ? "ld" : \
343    sizeof (void *) == sizeof (int) ? "d" : \
344    "lld")
345 #endif
346 #if !defined PRIiPTR
347 # define PRIiPTR \
348   (sizeof (void *) == sizeof (long) ? "li" : \
349    sizeof (void *) == sizeof (int) ? "i" : \
350    "lli")
351 #endif
352 #if !defined PRIoPTR
353 # define PRIoPTR \
354   (sizeof (void *) == sizeof (long) ? "lo" : \
355    sizeof (void *) == sizeof (int) ? "o" : \
356    "llo")
357 #endif
358 #if !defined PRIuPTR
359 # define PRIuPTR \
360   (sizeof (void *) == sizeof (long) ? "lu" : \
361    sizeof (void *) == sizeof (int) ? "u" : \
362    "llu")
363 #endif
364 #if !defined PRIxPTR
365 # define PRIxPTR \
366   (sizeof (void *) == sizeof (long) ? "lx" : \
367    sizeof (void *) == sizeof (int) ? "x" : \
368    "llx")
369 #endif
370 #if !defined PRIXPTR
371 # define PRIXPTR \
372   (sizeof (void *) == sizeof (long) ? "lX" : \
373    sizeof (void *) == sizeof (int) ? "X" : \
374    "llX")
375 #endif
376 
377 /* @@ end of prolog @@ */
378 
379 #ifdef _LIBC
380 /* Rename the non ISO C functions.  This is required by the standard
381    because some ISO C functions will require linking with this object
382    file and the name space must not be polluted.  */
383 # define open(name, flags)	open_not_cancel_2 (name, flags)
384 # define close(fd)		close_not_cancel_no_status (fd)
385 # define read(fd, buf, n)	read_not_cancel (fd, buf, n)
386 # define mmap(addr, len, prot, flags, fd, offset) \
387   __mmap (addr, len, prot, flags, fd, offset)
388 # define munmap(addr, len)	__munmap (addr, len)
389 #endif
390 
391 /* For those losing systems which don't have `alloca' we have to add
392    some additional code emulating it.  */
393 #ifdef HAVE_ALLOCA
394 # define freea(p) /* nothing */
395 #else
396 # define alloca(n) malloc (n)
397 # define freea(p) free (p)
398 #endif
399 
400 /* For systems that distinguish between text and binary I/O.
401    O_BINARY is usually declared in <fcntl.h>. */
402 #if !defined O_BINARY && defined _O_BINARY
403   /* For MSC-compatible compilers.  */
404 # define O_BINARY _O_BINARY
405 # define O_TEXT _O_TEXT
406 #endif
407 #ifdef __BEOS__
408   /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect.  */
409 # undef O_BINARY
410 # undef O_TEXT
411 #endif
412 /* On reasonable systems, binary I/O is the default.  */
413 #ifndef O_BINARY
414 # define O_BINARY 0
415 #endif
416 
417 
418 /* We need a sign, whether a new catalog was loaded, which can be associated
419    with all translations.  This is important if the translations are
420    cached by one of GCC's features.  */
421 #if defined __APPLE__ && defined __MACH__
422 /* On macOS 10.13 with Apple clang-902.0.39.1 and cctools-895, when linking
423    statically, we need an explicit zero-initialization, in order to avoid a
424    link-time error that __nl_msg_cat_cntr is an undefined symbol.  It could
425    be a compiler bug or a ranlib bug.  */
426 int _nl_msg_cat_cntr = 0;
427 #else
428 int _nl_msg_cat_cntr;
429 #endif
430 
431 
432 /* Expand a system dependent string segment.  Return NULL if unsupported.  */
433 static const char *
get_sysdep_segment_value(const char * name)434 get_sysdep_segment_value (const char *name)
435 {
436   /* Test for an ISO C 99 section 7.8.1 format string directive.
437      Syntax:
438      P R I { d | i | o | u | x | X }
439      { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR }  */
440   /* We don't use a table of 14 times 6 'const char *' strings here, because
441      data relocations cost startup time.  */
442   if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
443     {
444       if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
445 	  || name[3] == 'x' || name[3] == 'X')
446 	{
447 	  if (name[4] == '8' && name[5] == '\0')
448 	    {
449 	      if (name[3] == 'd')
450 		return PRId8;
451 	      if (name[3] == 'i')
452 		return PRIi8;
453 	      if (name[3] == 'o')
454 		return PRIo8;
455 	      if (name[3] == 'u')
456 		return PRIu8;
457 	      if (name[3] == 'x')
458 		return PRIx8;
459 	      if (name[3] == 'X')
460 		return PRIX8;
461 	      abort ();
462 	    }
463 	  if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
464 	    {
465 	      if (name[3] == 'd')
466 		return PRId16;
467 	      if (name[3] == 'i')
468 		return PRIi16;
469 	      if (name[3] == 'o')
470 		return PRIo16;
471 	      if (name[3] == 'u')
472 		return PRIu16;
473 	      if (name[3] == 'x')
474 		return PRIx16;
475 	      if (name[3] == 'X')
476 		return PRIX16;
477 	      abort ();
478 	    }
479 	  if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
480 	    {
481 	      if (name[3] == 'd')
482 		return PRId32;
483 	      if (name[3] == 'i')
484 		return PRIi32;
485 	      if (name[3] == 'o')
486 		return PRIo32;
487 	      if (name[3] == 'u')
488 		return PRIu32;
489 	      if (name[3] == 'x')
490 		return PRIx32;
491 	      if (name[3] == 'X')
492 		return PRIX32;
493 	      abort ();
494 	    }
495 	  if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
496 	    {
497 	      if (name[3] == 'd')
498 		return PRId64;
499 	      if (name[3] == 'i')
500 		return PRIi64;
501 	      if (name[3] == 'o')
502 		return PRIo64;
503 	      if (name[3] == 'u')
504 		return PRIu64;
505 	      if (name[3] == 'x')
506 		return PRIx64;
507 	      if (name[3] == 'X')
508 		return PRIX64;
509 	      abort ();
510 	    }
511 	  if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
512 	      && name[7] == 'S' && name[8] == 'T')
513 	    {
514 	      if (name[9] == '8' && name[10] == '\0')
515 		{
516 		  if (name[3] == 'd')
517 		    return PRIdLEAST8;
518 		  if (name[3] == 'i')
519 		    return PRIiLEAST8;
520 		  if (name[3] == 'o')
521 		    return PRIoLEAST8;
522 		  if (name[3] == 'u')
523 		    return PRIuLEAST8;
524 		  if (name[3] == 'x')
525 		    return PRIxLEAST8;
526 		  if (name[3] == 'X')
527 		    return PRIXLEAST8;
528 		  abort ();
529 		}
530 	      if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
531 		{
532 		  if (name[3] == 'd')
533 		    return PRIdLEAST16;
534 		  if (name[3] == 'i')
535 		    return PRIiLEAST16;
536 		  if (name[3] == 'o')
537 		    return PRIoLEAST16;
538 		  if (name[3] == 'u')
539 		    return PRIuLEAST16;
540 		  if (name[3] == 'x')
541 		    return PRIxLEAST16;
542 		  if (name[3] == 'X')
543 		    return PRIXLEAST16;
544 		  abort ();
545 		}
546 	      if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
547 		{
548 		  if (name[3] == 'd')
549 		    return PRIdLEAST32;
550 		  if (name[3] == 'i')
551 		    return PRIiLEAST32;
552 		  if (name[3] == 'o')
553 		    return PRIoLEAST32;
554 		  if (name[3] == 'u')
555 		    return PRIuLEAST32;
556 		  if (name[3] == 'x')
557 		    return PRIxLEAST32;
558 		  if (name[3] == 'X')
559 		    return PRIXLEAST32;
560 		  abort ();
561 		}
562 	      if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
563 		{
564 		  if (name[3] == 'd')
565 		    return PRIdLEAST64;
566 		  if (name[3] == 'i')
567 		    return PRIiLEAST64;
568 		  if (name[3] == 'o')
569 		    return PRIoLEAST64;
570 		  if (name[3] == 'u')
571 		    return PRIuLEAST64;
572 		  if (name[3] == 'x')
573 		    return PRIxLEAST64;
574 		  if (name[3] == 'X')
575 		    return PRIXLEAST64;
576 		  abort ();
577 		}
578 	    }
579 	  if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
580 	      && name[7] == 'T')
581 	    {
582 	      if (name[8] == '8' && name[9] == '\0')
583 		{
584 		  if (name[3] == 'd')
585 		    return PRIdFAST8;
586 		  if (name[3] == 'i')
587 		    return PRIiFAST8;
588 		  if (name[3] == 'o')
589 		    return PRIoFAST8;
590 		  if (name[3] == 'u')
591 		    return PRIuFAST8;
592 		  if (name[3] == 'x')
593 		    return PRIxFAST8;
594 		  if (name[3] == 'X')
595 		    return PRIXFAST8;
596 		  abort ();
597 		}
598 	      if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
599 		{
600 		  if (name[3] == 'd')
601 		    return PRIdFAST16;
602 		  if (name[3] == 'i')
603 		    return PRIiFAST16;
604 		  if (name[3] == 'o')
605 		    return PRIoFAST16;
606 		  if (name[3] == 'u')
607 		    return PRIuFAST16;
608 		  if (name[3] == 'x')
609 		    return PRIxFAST16;
610 		  if (name[3] == 'X')
611 		    return PRIXFAST16;
612 		  abort ();
613 		}
614 	      if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
615 		{
616 		  if (name[3] == 'd')
617 		    return PRIdFAST32;
618 		  if (name[3] == 'i')
619 		    return PRIiFAST32;
620 		  if (name[3] == 'o')
621 		    return PRIoFAST32;
622 		  if (name[3] == 'u')
623 		    return PRIuFAST32;
624 		  if (name[3] == 'x')
625 		    return PRIxFAST32;
626 		  if (name[3] == 'X')
627 		    return PRIXFAST32;
628 		  abort ();
629 		}
630 	      if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
631 		{
632 		  if (name[3] == 'd')
633 		    return PRIdFAST64;
634 		  if (name[3] == 'i')
635 		    return PRIiFAST64;
636 		  if (name[3] == 'o')
637 		    return PRIoFAST64;
638 		  if (name[3] == 'u')
639 		    return PRIuFAST64;
640 		  if (name[3] == 'x')
641 		    return PRIxFAST64;
642 		  if (name[3] == 'X')
643 		    return PRIXFAST64;
644 		  abort ();
645 		}
646 	    }
647 	  if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
648 	      && name[7] == '\0')
649 	    {
650 	      if (name[3] == 'd')
651 		return PRIdMAX;
652 	      if (name[3] == 'i')
653 		return PRIiMAX;
654 	      if (name[3] == 'o')
655 		return PRIoMAX;
656 	      if (name[3] == 'u')
657 		return PRIuMAX;
658 	      if (name[3] == 'x')
659 		return PRIxMAX;
660 	      if (name[3] == 'X')
661 		return PRIXMAX;
662 	      abort ();
663 	    }
664 	  if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
665 	      && name[7] == '\0')
666 	    {
667 	      if (name[3] == 'd')
668 		return PRIdPTR;
669 	      if (name[3] == 'i')
670 		return PRIiPTR;
671 	      if (name[3] == 'o')
672 		return PRIoPTR;
673 	      if (name[3] == 'u')
674 		return PRIuPTR;
675 	      if (name[3] == 'x')
676 		return PRIxPTR;
677 	      if (name[3] == 'X')
678 		return PRIXPTR;
679 	      abort ();
680 	    }
681 	}
682     }
683   /* Test for a glibc specific printf() format directive flag.  */
684   if (name[0] == 'I' && name[1] == '\0')
685     {
686 #if defined _LIBC \
687     || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) \
688         && !defined __UCLIBC__)
689       /* The 'I' flag, in numeric format directives, replaces ASCII digits
690 	 with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
691 	 used for Farsi (Persian), some Indic languages, and maybe Arabic.  */
692       return "I";
693 #else
694       return "";
695 #endif
696     }
697   /* Other system dependent strings are not valid.  */
698   return NULL;
699 }
700 
701 /* Lock that protects the various 'struct loaded_l10nfile' objects.  */
702 __libc_lock_define_initialized_recursive (static, lock);
703 
704 /* Load the message catalogs specified by FILENAME.  If it is no valid
705    message catalog do nothing.  */
706 void
707 internal_function
_nl_load_domain(struct loaded_l10nfile * domain_file,struct binding * domainbinding)708 _nl_load_domain (struct loaded_l10nfile *domain_file,
709 		 struct binding *domainbinding)
710 {
711   int fd = -1;
712   size_t size;
713 #ifdef _LIBC
714   struct stat64 st;
715 #else
716   struct stat st;
717 #endif
718   struct mo_file_header *data = (struct mo_file_header *) -1;
719   int use_mmap = 0;
720   struct loaded_domain *domain;
721   int revision;
722   const char *nullentry;
723   size_t nullentrylen;
724 
725   __libc_lock_lock_recursive (lock);
726   if (domain_file->decided != 0)
727     {
728       /* There are two possibilities:
729 
730 	 + this is the same thread calling again during this initialization
731 	   via _nl_find_msg.  We have initialized everything this call needs.
732 
733 	 + this is another thread which tried to initialize this object.
734 	   Not necessary anymore since if the lock is available this
735 	   is finished.
736       */
737       goto done;
738     }
739 
740   domain_file->decided = -1;
741   domain_file->data = NULL;
742 
743   /* Note that it would be useless to store domainbinding in domain_file
744      because domainbinding might be == NULL now but != NULL later (after
745      a call to bind_textdomain_codeset).  */
746 
747   /* If the record does not represent a valid locale the FILENAME
748      might be NULL.  This can happen when according to the given
749      specification the locale file name is different for XPG and CEN
750      syntax.  */
751   if (domain_file->filename != NULL)
752     {
753       /* Try to open the addressed file.  */
754       fd = open (domain_file->filename, O_RDONLY | O_BINARY);
755       if (fd == -1)
756         goto out;
757     }
758 #if defined _WIN32 && !defined __CYGWIN__
759   else if (domain_file->wfilename != NULL)
760     {
761       /* Try to open the addressed file.  */
762       fd = _wopen (domain_file->wfilename, O_RDONLY | O_BINARY);
763       if (fd == -1)
764         goto out;
765     }
766 #endif
767   else
768     goto out;
769 
770   /* We must know about the size of the file.  */
771   if (
772 #ifdef _LIBC
773       __builtin_expect (fstat64 (fd, &st) != 0, 0)
774 #else
775       __builtin_expect (fstat (fd, &st) != 0, 0)
776 #endif
777       || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
778       || __builtin_expect (size < sizeof (struct mo_file_header), 0))
779     /* Something went wrong.  */
780     goto out;
781 
782 #ifdef HAVE_MMAP
783   /* Now we are ready to load the file.  If mmap() is available we try
784      this first.  If not available or it failed we try to load it.  */
785   data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
786 					 MAP_PRIVATE, fd, 0);
787 
788   if (__builtin_expect (data != MAP_FAILED, 1))
789     {
790       /* mmap() call was successful.  */
791       close (fd);
792       fd = -1;
793       use_mmap = 1;
794     }
795 
796   assert (MAP_FAILED == (void *) -1);
797 #endif
798 
799   /* If the data is not yet available (i.e. mmap'ed) we try to load
800      it manually.  */
801   if (data == (struct mo_file_header *) -1)
802     {
803       size_t to_read;
804       char *read_ptr;
805 
806       data = (struct mo_file_header *) malloc (size);
807       if (data == NULL)
808 	goto out;
809 
810       to_read = size;
811       read_ptr = (char *) data;
812       do
813 	{
814 	  long int nb = (long int) read (fd, read_ptr, to_read);
815 	  if (nb <= 0)
816 	    {
817 #ifdef EINTR
818 	      if (nb == -1 && errno == EINTR)
819 		continue;
820 #endif
821               free (data);
822 	      goto out;
823 	    }
824 	  read_ptr += nb;
825 	  to_read -= nb;
826 	}
827       while (to_read > 0);
828 
829       close (fd);
830       fd = -1;
831     }
832 
833   /* Using the magic number we can test whether it really is a message
834      catalog file.  */
835   if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
836 			0))
837     {
838       /* The magic number is wrong: not a message catalog file.  */
839 #ifdef HAVE_MMAP
840       if (use_mmap)
841 	munmap ((caddr_t) data, size);
842       else
843 #endif
844 	free (data);
845       goto out;
846     }
847 
848   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
849   if (domain == NULL)
850     {
851 #ifdef HAVE_MMAP
852       if (use_mmap)
853 	munmap ((caddr_t) data, size);
854       else
855 #endif
856 	free (data);
857       goto out;
858     }
859   domain_file->data = domain;
860 
861   domain->data = (char *) data;
862   domain->use_mmap = use_mmap;
863   domain->mmap_size = size;
864   domain->must_swap = data->magic != _MAGIC;
865   domain->malloced = NULL;
866 
867   /* Fill in the information about the available tables.  */
868   revision = W (domain->must_swap, data->revision);
869   /* We support only the major revisions 0 and 1.  */
870   switch (revision >> 16)
871     {
872     case 0:
873     case 1:
874       domain->nstrings = W (domain->must_swap, data->nstrings);
875       domain->orig_tab = (const struct string_desc *)
876 	((char *) data + W (domain->must_swap, data->orig_tab_offset));
877       domain->trans_tab = (const struct string_desc *)
878 	((char *) data + W (domain->must_swap, data->trans_tab_offset));
879       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
880       domain->hash_tab =
881 	(domain->hash_size > 2
882 	 ? (const nls_uint32 *)
883 	   ((char *) data + W (domain->must_swap, data->hash_tab_offset))
884 	 : NULL);
885       domain->must_swap_hash_tab = domain->must_swap;
886 
887       /* Now dispatch on the minor revision.  */
888       switch (revision & 0xffff)
889 	{
890 	case 0:
891 	  domain->n_sysdep_strings = 0;
892 	  domain->orig_sysdep_tab = NULL;
893 	  domain->trans_sysdep_tab = NULL;
894 	  break;
895 	case 1:
896 	default:
897 	  {
898 	    nls_uint32 n_sysdep_strings;
899 
900 	    if (domain->hash_tab == NULL)
901 	      /* This is invalid.  These minor revisions need a hash table.  */
902 	      goto invalid;
903 
904 	    n_sysdep_strings =
905 	      W (domain->must_swap, data->n_sysdep_strings);
906 	    if (n_sysdep_strings > 0)
907 	      {
908 		nls_uint32 n_sysdep_segments;
909 		const struct sysdep_segment *sysdep_segments;
910 		const char **sysdep_segment_values;
911 		const nls_uint32 *orig_sysdep_tab;
912 		const nls_uint32 *trans_sysdep_tab;
913 		nls_uint32 n_inmem_sysdep_strings;
914 		size_t memneed;
915 		char *mem;
916 		struct sysdep_string_desc *inmem_orig_sysdep_tab;
917 		struct sysdep_string_desc *inmem_trans_sysdep_tab;
918 		nls_uint32 *inmem_hash_tab;
919 		unsigned int i, j;
920 
921 		/* Get the values of the system dependent segments.  */
922 		n_sysdep_segments =
923 		  W (domain->must_swap, data->n_sysdep_segments);
924 		sysdep_segments = (const struct sysdep_segment *)
925 		  ((char *) data
926 		   + W (domain->must_swap, data->sysdep_segments_offset));
927 		sysdep_segment_values =
928 		  (const char **)
929 		  alloca (n_sysdep_segments * sizeof (const char *));
930 		for (i = 0; i < n_sysdep_segments; i++)
931 		  {
932 		    const char *name =
933 		      (char *) data
934 		      + W (domain->must_swap, sysdep_segments[i].offset);
935 		    nls_uint32 namelen =
936 		      W (domain->must_swap, sysdep_segments[i].length);
937 
938 		    if (!(namelen > 0 && name[namelen - 1] == '\0'))
939 		      {
940 			freea (sysdep_segment_values);
941 			goto invalid;
942 		      }
943 
944 		    sysdep_segment_values[i] = get_sysdep_segment_value (name);
945 		  }
946 
947 		orig_sysdep_tab = (const nls_uint32 *)
948 		  ((char *) data
949 		   + W (domain->must_swap, data->orig_sysdep_tab_offset));
950 		trans_sysdep_tab = (const nls_uint32 *)
951 		  ((char *) data
952 		   + W (domain->must_swap, data->trans_sysdep_tab_offset));
953 
954 		/* Compute the amount of additional memory needed for the
955 		   system dependent strings and the augmented hash table.
956 		   At the same time, also drop string pairs which refer to
957 		   an undefined system dependent segment.  */
958 		n_inmem_sysdep_strings = 0;
959 		memneed = domain->hash_size * sizeof (nls_uint32);
960 		for (i = 0; i < n_sysdep_strings; i++)
961 		  {
962 		    int valid = 1;
963 		    size_t needs[2];
964 
965 		    for (j = 0; j < 2; j++)
966 		      {
967 			const struct sysdep_string *sysdep_string =
968 			  (const struct sysdep_string *)
969 			  ((char *) data
970 			   + W (domain->must_swap,
971 				j == 0
972 				? orig_sysdep_tab[i]
973 				: trans_sysdep_tab[i]));
974 			size_t need = 0;
975 			const char *static_segments =
976 			  (char *) data
977 			  + W (domain->must_swap, sysdep_string->offset);
978 			const struct segment_pair *p = sysdep_string->segments;
979 
980 			if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
981 			  for (;; p++)
982 			    {
983 			      nls_uint32 segsize;
984 			      nls_uint32 sysdepref;
985 
986 			      segsize = W (domain->must_swap, p->segsize);
987 			      need += segsize;
988 
989 			      sysdepref = W (domain->must_swap, p->sysdepref);
990 			      if (sysdepref == SEGMENTS_END)
991 				break;
992 
993 			      static_segments += segsize;
994 
995 			      if (sysdepref >= n_sysdep_segments)
996 				{
997 				  /* Invalid.  */
998 				  freea (sysdep_segment_values);
999 				  goto invalid;
1000 				}
1001 
1002 			      if (sysdep_segment_values[sysdepref] == NULL)
1003 				{
1004 				  /* This particular string pair is invalid.  */
1005 				  valid = 0;
1006 				}
1007 
1008 			      need += strlen (sysdep_segment_values[sysdepref]);
1009 			    }
1010 
1011 			/* The last static segment must end in a NUL.  */
1012 			{
1013 			  nls_uint32 segsize =
1014 			    W (domain->must_swap, p->segsize);
1015 
1016 			  if (!(segsize > 0
1017 				&& static_segments[segsize - 1] == '\0'))
1018 			    {
1019 			      /* Invalid.  */
1020 			      freea (sysdep_segment_values);
1021 			      goto invalid;
1022 			    }
1023 			}
1024 
1025 			needs[j] = need;
1026 			if (!valid)
1027 			  break;
1028 		      }
1029 
1030 		    if (valid)
1031 		      {
1032 			n_inmem_sysdep_strings++;
1033 			memneed += needs[0] + needs[1];
1034 		      }
1035 		  }
1036 		memneed += 2 * n_inmem_sysdep_strings
1037 			   * sizeof (struct sysdep_string_desc);
1038 
1039 		if (n_inmem_sysdep_strings > 0)
1040 		  {
1041 		    unsigned int k;
1042 
1043 		    /* Allocate additional memory.  */
1044 		    mem = (char *) malloc (memneed);
1045 		    if (mem == NULL)
1046 		      goto invalid;
1047 
1048 		    domain->malloced = mem;
1049 		    inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1050 		    mem += n_inmem_sysdep_strings
1051 			   * sizeof (struct sysdep_string_desc);
1052 		    inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1053 		    mem += n_inmem_sysdep_strings
1054 			   * sizeof (struct sysdep_string_desc);
1055 		    inmem_hash_tab = (nls_uint32 *) mem;
1056 		    mem += domain->hash_size * sizeof (nls_uint32);
1057 
1058 		    /* Compute the system dependent strings.  */
1059 		    k = 0;
1060 		    for (i = 0; i < n_sysdep_strings; i++)
1061 		      {
1062 			int valid = 1;
1063 
1064 			for (j = 0; j < 2; j++)
1065 			  {
1066 			    const struct sysdep_string *sysdep_string =
1067 			      (const struct sysdep_string *)
1068 			      ((char *) data
1069 			       + W (domain->must_swap,
1070 				    j == 0
1071 				    ? orig_sysdep_tab[i]
1072 				    : trans_sysdep_tab[i]));
1073 			    const struct segment_pair *p =
1074 			      sysdep_string->segments;
1075 
1076 			    if (W (domain->must_swap, p->sysdepref)
1077 				!= SEGMENTS_END)
1078 			      for (;; p++)
1079 				{
1080 				  nls_uint32 sysdepref;
1081 
1082 				  sysdepref =
1083 				    W (domain->must_swap, p->sysdepref);
1084 				  if (sysdepref == SEGMENTS_END)
1085 				    break;
1086 
1087 				  if (sysdep_segment_values[sysdepref] == NULL)
1088 				    {
1089 				      /* This particular string pair is
1090 					 invalid.  */
1091 				      valid = 0;
1092 				      break;
1093 				    }
1094 				}
1095 
1096 			    if (!valid)
1097 			      break;
1098 			  }
1099 
1100 			if (valid)
1101 			  {
1102 			    for (j = 0; j < 2; j++)
1103 			      {
1104 				const struct sysdep_string *sysdep_string =
1105 				  (const struct sysdep_string *)
1106 				  ((char *) data
1107 				   + W (domain->must_swap,
1108 					j == 0
1109 					? orig_sysdep_tab[i]
1110 					: trans_sysdep_tab[i]));
1111 				const char *static_segments =
1112 				  (char *) data
1113 				  + W (domain->must_swap, sysdep_string->offset);
1114 				const struct segment_pair *p =
1115 				  sysdep_string->segments;
1116 
1117 				/* Concatenate the segments, and fill
1118 				   inmem_orig_sysdep_tab[k] (for j == 0) and
1119 				   inmem_trans_sysdep_tab[k] (for j == 1).  */
1120 
1121 				struct sysdep_string_desc *inmem_tab_entry =
1122 				  (j == 0
1123 				   ? inmem_orig_sysdep_tab
1124 				   : inmem_trans_sysdep_tab)
1125 				  + k;
1126 
1127 				if (W (domain->must_swap, p->sysdepref)
1128 				    == SEGMENTS_END)
1129 				  {
1130 				    /* Only one static segment.  */
1131 				    inmem_tab_entry->length =
1132 				      W (domain->must_swap, p->segsize);
1133 				    inmem_tab_entry->pointer = static_segments;
1134 				  }
1135 				else
1136 				  {
1137 				    inmem_tab_entry->pointer = mem;
1138 
1139 				    for (;; p++)
1140 				      {
1141 					nls_uint32 segsize =
1142 					  W (domain->must_swap, p->segsize);
1143 					nls_uint32 sysdepref =
1144 					  W (domain->must_swap, p->sysdepref);
1145 					size_t n;
1146 
1147 					if (segsize > 0)
1148 					  {
1149 					    memcpy (mem, static_segments, segsize);
1150 					    mem += segsize;
1151 					    static_segments += segsize;
1152 					  }
1153 
1154 					if (sysdepref == SEGMENTS_END)
1155 					  break;
1156 
1157 					n = strlen (sysdep_segment_values[sysdepref]);
1158 					memcpy (mem, sysdep_segment_values[sysdepref], n);
1159 					mem += n;
1160 				      }
1161 
1162 				    inmem_tab_entry->length =
1163 				      mem - inmem_tab_entry->pointer;
1164 				  }
1165 			      }
1166 
1167 			    k++;
1168 			  }
1169 		      }
1170 		    if (k != n_inmem_sysdep_strings)
1171 		      abort ();
1172 
1173 		    /* Compute the augmented hash table.  */
1174 		    for (i = 0; i < domain->hash_size; i++)
1175 		      inmem_hash_tab[i] =
1176 			W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1177 		    for (i = 0; i < n_inmem_sysdep_strings; i++)
1178 		      {
1179 			const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1180 			nls_uint32 hash_val = __hash_string (msgid);
1181 			nls_uint32 idx = hash_val % domain->hash_size;
1182 			nls_uint32 incr =
1183 			  1 + (hash_val % (domain->hash_size - 2));
1184 
1185 			for (;;)
1186 			  {
1187 			    if (inmem_hash_tab[idx] == 0)
1188 			      {
1189 				/* Hash table entry is empty.  Use it.  */
1190 				inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1191 				break;
1192 			      }
1193 
1194 			    if (idx >= domain->hash_size - incr)
1195 			      idx -= domain->hash_size - incr;
1196 			    else
1197 			      idx += incr;
1198 			  }
1199 		      }
1200 
1201 		    domain->n_sysdep_strings = n_inmem_sysdep_strings;
1202 		    domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1203 		    domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1204 
1205 		    domain->hash_tab = inmem_hash_tab;
1206 		    domain->must_swap_hash_tab = 0;
1207 		  }
1208 		else
1209 		  {
1210 		    domain->n_sysdep_strings = 0;
1211 		    domain->orig_sysdep_tab = NULL;
1212 		    domain->trans_sysdep_tab = NULL;
1213 		  }
1214 
1215 		freea (sysdep_segment_values);
1216 	      }
1217 	    else
1218 	      {
1219 		domain->n_sysdep_strings = 0;
1220 		domain->orig_sysdep_tab = NULL;
1221 		domain->trans_sysdep_tab = NULL;
1222 	      }
1223 	  }
1224 	  break;
1225 	}
1226       break;
1227     default:
1228       /* This is an invalid revision.  */
1229     invalid:
1230       /* This is an invalid .mo file or we ran out of resources.  */
1231       free (domain->malloced);
1232 #ifdef HAVE_MMAP
1233       if (use_mmap)
1234 	munmap ((caddr_t) data, size);
1235       else
1236 #endif
1237 	free (data);
1238       free (domain);
1239       domain_file->data = NULL;
1240       goto out;
1241     }
1242 
1243   /* No caches of converted translations so far.  */
1244   domain->conversions = NULL;
1245   domain->nconversions = 0;
1246 #ifdef _LIBC
1247   __libc_rwlock_init (domain->conversions_lock);
1248 #else
1249   gl_rwlock_init (domain->conversions_lock);
1250 #endif
1251 
1252   /* Get the header entry and look for a plural specification.  */
1253 #ifdef IN_LIBGLOCALE
1254   nullentry =
1255     _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
1256 #else
1257   nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1258 #endif
1259   if (__builtin_expect (nullentry == (char *) -1, 0))
1260     {
1261 #ifdef _LIBC
1262       __libc_rwlock_fini (domain->conversions_lock);
1263 #else
1264       gl_rwlock_destroy (domain->conversions_lock);
1265 #endif
1266       goto invalid;
1267     }
1268   EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1269 
1270  out:
1271   if (fd != -1)
1272     close (fd);
1273 
1274   domain_file->decided = 1;
1275 
1276  done:
1277   __libc_lock_unlock_recursive (lock);
1278 }
1279 
1280 
1281 #ifdef _LIBC
1282 void
1283 internal_function __libc_freeres_fn_section
_nl_unload_domain(struct loaded_domain * domain)1284 _nl_unload_domain (struct loaded_domain *domain)
1285 {
1286   size_t i;
1287 
1288   if (domain->plural != &__gettext_germanic_plural)
1289     __gettext_free_exp ((struct expression *) domain->plural);
1290 
1291   for (i = 0; i < domain->nconversions; i++)
1292     {
1293       struct converted_domain *convd = &domain->conversions[i];
1294 
1295       free ((char *) convd->encoding);
1296       if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
1297 	free (convd->conv_tab);
1298       if (convd->conv != (__gconv_t) -1)
1299 	__gconv_close (convd->conv);
1300     }
1301   free (domain->conversions);
1302   __libc_rwlock_fini (domain->conversions_lock);
1303 
1304   free (domain->malloced);
1305 
1306 # ifdef _POSIX_MAPPED_FILES
1307   if (domain->use_mmap)
1308     munmap ((caddr_t) domain->data, domain->mmap_size);
1309   else
1310 # endif	/* _POSIX_MAPPED_FILES */
1311     free ((void *) domain->data);
1312 
1313   free (domain);
1314 }
1315 #endif
1316