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