4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include <sys/types.h>
38 #include "_loc_path.h"
43 #include "plural_parser.h"
47 static const char *category_name
[] = {
56 static const int category_name_len
[] = {
69 * mp - uses the following members:
70 * msgfile - buffer to store the pathname to the message file
71 * binding - directory pathname bound to specified domain
72 * cblen - length of binding
73 * locale - locale name
74 * domain - domain name
76 * domain_len - length of domain name
79 * mp->msgfile - pathname to the message file is stored
82 * mp->msgfile is returned
85 mk_msgfile(struct msg_pack
*mp
)
90 uint32_t cblen
, loclen
, catlen
, totallen
;
93 gprintf(0, "*************** mk_msgfile(0x%p)\n", (void *)mp
);
101 cblen
= (uint32_t)(p
- mp
->msgfile
);
102 if (*(p
- 1) != '/') {
104 * if the last character of binding
105 * isn't a '/', adding '/'.
107 if (cblen
+ 1 >= MAXPATHLEN
) {
108 /* MAXPATHLEN includes a null termination */
115 loclen
= strlen(mp
->locale
);
116 catstr
= category_name
[mp
->category
];
117 catlen
= (uint32_t)category_name_len
[mp
->category
];
119 * totallen is the length of the msgfile
120 * pathname excluding a null termination.
123 totallen
= cblen
+ loclen
+ 1 + catlen
+ 1 +
124 mp
->domain_len
+ MSGFILESUFFIXLEN
;
125 if (totallen
>= MAXPATHLEN
)
132 while (*p
++ = *catstr
++)
143 gprintf(0, "*************** Exiting mk_msgfile\n");
144 gprintf(0, "mp->msgfile: \"%s\"\n", mp
->msgfile
);
147 return (mp
->msgfile
);
154 * mp - may use the following members:
155 * msgfile - pathname to the message catalog file
156 * hash_domain - hash id of this domain
160 * pointer to the Msg_node object of the current message catalog
164 * this message catalog does not exist in the cache
167 check_cache(struct msg_pack
*mp
)
169 Msg_node
*cur_msg
, *mnp
;
170 Gettext_t
*gt
= global_gt
;
173 gprintf(0, "*************** check_cache(0x%p)\n", mp
);
177 cur_msg
= gt
->c_m_node
; /* current Msg_node */
179 cur_msg
->hashid
== mp
->hash_domain
&&
180 strcmp(cur_msg
->path
, mp
->msgfile
) == 0) {
182 * msgfile is the same as the previous message file
185 gprintf(0, "*** cache found\n");
186 gprintf(0, "************* exiting check_cache\n");
187 printmnp(cur_msg
, 1);
194 gprintf(0, "========== descending the list\n");
195 gprintf(0, " hashid: %d, hash_domain: %d\n",
196 mnp
->hashid
, mp
->hash_domain
);
199 if (mnp
->hashid
== mp
->hash_domain
&&
200 strcmp(mnp
->path
, mp
->msgfile
) == 0) {
202 gprintf(0, "*** cache found\n");
203 gprintf(0, "******* exiting check_cache\n");
213 gprintf(0, "*** cache not found\n");
214 gprintf(0, "******* exiting check_cache\n");
220 get_codeset(const char *domain
)
225 gprintf(0, "*************** get_codeset(\"%s\")\n",
226 domain
? domain
: "(null)");
229 codeset
= _real_bindtextdomain_u(domain
, NULL
, TP_CODESET
);
230 if (codeset
== NULL
) {
231 /* no codeset is bound to this domain */
232 codeset
= nl_langinfo(CODESET
);
235 gprintf(0, "*************** existing get_codeset(\"%s\")\n",
236 domain
? domain
: "(null)");
237 gprintf(0, " = \"%s\"\n", codeset
);
244 * get_hashid (hashpjw)
246 * Calculates the hash value from the specified string.
247 * Actual hashid will be mod(hash value, PRIME_NUMBER).
249 * Ref: Compilers - Principles, Techniques, and Tools
250 * Aho, Sethi, and Ullman
253 get_hashid(const char *str
, uint32_t *len
)
255 const unsigned char *p
= (unsigned char *)str
;
269 *len
= (uint32_t)(p
- (unsigned char *)str
);
278 r
= (n
<< 24) | ((n
& 0xff00) << 8) |
279 ((n
>> 8) & 0xff00) | (n
>> 24);
285 search_msg(Msg_g_node
*p
, const char *id
, uint32_t hash_val
,
286 struct gnu_msg_ent
*m
)
288 char *base
= (char *)p
->msg_file_info
;
289 uint32_t hash_size
, num_of_str
, i
, idx
, inc
;
292 num_of_str
= p
->num_of_str
;
293 hash_size
= p
->hash_size
;
294 idx
= hash_val
% hash_size
;
295 inc
= 1 + (hash_val
% (hash_size
- 2));
297 while ((i
= p
->hash_table
[idx
]) != 0) {
298 ms
= (i
<= num_of_str
) ?
299 base
+ SWAP(p
, m
[i
-1].offset
) :
300 p
->mchunk
+ p
->d_msg
[MSGID
][i
-num_of_str
-1].offset
;
301 if (strcmp(id
, ms
) == 0) {
305 idx
= (idx
+ inc
) % hash_size
;
312 print_rev1_info(Msg_g_node
*p
)
314 char *base
= (char *)p
->msg_file_info
;
315 struct gnu_msg_info
*header
= p
->msg_file_info
;
316 struct gnu_msg_ent
*m
;
322 #ifdef GETTEXT_DEBUG_DYMMSG
323 gprintf(0, "******** dynamic msgid/msgstr\n");
324 for (v
= MSGID
; v
<= MSGSTR
; v
++) {
325 for (x
= 0; x
< p
->num_of_d_str
; x
++) {
326 gprintf(0, "len: %u\n", p
->d_msg
[v
][x
].len
);
327 gprintf(0, "str: \"%s\"\n",
328 p
->mchunk
+ p
->d_msg
[v
][x
].offset
);
332 #ifdef GETTEXT_DEBUG_HASHTBL
333 gprintf(0, "******** dynamic hash table\n");
334 for (x
= 0; x
< p
->hash_size
; x
++) {
335 gprintf(0, "%d: %u\n", x
, p
->hash_table
[x
]);
338 #ifdef GETTEXT_DEBUG_CHECK_STMSGID
339 gprintf(0, "******** sanity check of static msgid\n");
340 m
= (struct gnu_msg_ent
*)(uintptr_t)
341 (base
+ SWAP(p
, header
->off_msgid_tbl
));
342 for (x
= 0; x
< p
->num_of_str
; x
++) {
343 ms
= base
+ SWAP(p
, m
[x
].offset
);
344 gprintf(0, "\"%s\"\n", ms
);
345 hv
= get_hashid(ms
, NULL
);
346 hidx
= search_msg(p
, ms
, hv
, m
);
349 "failed to find this msg in the hash table\n");
352 gprintf(0, "hash table mismatch\n");
357 #ifdef GETTEXT_DEBUG_CHECK_DYMMSGID
358 gprintf(0, "******* sanity check of dynamic msgid\n");
359 m
= (struct gnu_msg_ent
*)(uintptr_t)
360 (base
+ SWAP(p
, header
->off_msgid_tbl
));
361 for (x
= 0; x
< p
->num_of_d_str
; x
++) {
362 ms
= p
->mchunk
+ p
->d_msg
[MSGID
][x
].offset
;
363 gprintf(0, "\"%s\"\n", ms
);
364 hv
= get_hashid(ms
, NULL
);
365 hidx
= search_msg(p
, ms
, hv
, m
);
368 "failed to find this msg in the hash table\n");
370 if (hidx
!= x
+ p
->num_of_str
+ 1) {
371 gprintf(0, "hash table mismatch\n");
379 gprintf(int level
, const char *format
, ...)
383 va_start(ap
, format
);
385 while (level
-- > 0) {
386 (void) fputs(" ", stdout
);
388 (void) vprintf(format
, ap
);
391 (void) fflush(stdout
);
397 struct domain_binding
*ppp
;
398 Gettext_t
*gt
= global_gt
;
400 gprintf(0, "=== Printing default list and regural list\n");
401 gprintf(0, " Default domain=<%s>, binding=<%s>\n",
402 DEFAULT_DOMAIN
, defaultbind
);
406 gprintf(0, " domain=<%s>, binding=<%s>, codeset=<%s>\n",
407 ppp
->domain
? ppp
->domain
: "(null)",
408 ppp
->binding
? ppp
->binding
: "(null)",
409 ppp
->codeset
? ppp
->codeset
: "(null)");
412 (void) fflush(stdout
);
416 printmp(struct msg_pack
*mp
, int level
)
418 gprintf(level
, "=== mp ===\n");
419 gprintf(level
, " msgid1: \"%s\"\n",
420 mp
->msgid1
? mp
->msgid1
: "(null)");
421 gprintf(level
, " msgid2: \"%s\"\n",
422 mp
->msgid2
? mp
->msgid2
: "(null)");
423 gprintf(level
, " msgfile: \"%s\"\n",
424 mp
->msgfile
? mp
->msgfile
: "(null)");
425 gprintf(level
, " domain: \"%s\"\n",
426 mp
->domain
? mp
->domain
: "(null)");
427 gprintf(level
, " binding: \"%s\"\n",
428 mp
->binding
? mp
->binding
: "(null)");
429 gprintf(level
, " locale: \"%s\"\n",
430 mp
->locale
? mp
->locale
: "(null)");
431 gprintf(level
, " language: \"%s\"\n",
432 mp
->language
? mp
->language
: "(null)");
433 gprintf(level
, " addr: 0x%p\n", mp
->addr
);
434 gprintf(level
, " fsz: %d\n", mp
->fsz
);
435 gprintf(level
, " hash_domain: %d\n", mp
->hash_domain
);
436 gprintf(level
, " domain_len: %d\n", mp
->domain_len
);
437 gprintf(level
, " n: %d\n", mp
->n
);
438 gprintf(level
, " category: \"%s\"\n",
439 category_name
[mp
->category
]);
440 gprintf(level
, " plural: %d\n", mp
->plural
);
441 gprintf(level
, " nlsp: %d\n", mp
->nlsp
);
442 gprintf(level
, " trusted: %d\n", mp
->trusted
);
443 gprintf(level
, " status: %d\n", mp
->status
);
447 printsunmsg(Msg_s_node
*smnp
, int level
)
449 gprintf(level
, "=== sunmsg ===\n");
450 gprintf(level
, " msg_file_info: 0x%p\n",
451 (void *)smnp
->msg_file_info
);
452 gprintf(level
, " msg_mid: %d\n",
453 smnp
->msg_file_info
->msg_mid
);
454 gprintf(level
, " msg_count: %d\n",
455 smnp
->msg_file_info
->msg_count
);
456 gprintf(level
, " str_count_msgid: %d\n",
457 smnp
->msg_file_info
->str_count_msgid
);
458 gprintf(level
, " str_count_msgstr: %d\n",
459 smnp
->msg_file_info
->str_count_msgstr
);
460 gprintf(level
, " msg_struct_size: %d\n",
461 smnp
->msg_file_info
->msg_struct_size
);
462 gprintf(level
, " msg_list: 0x%p\n",
463 (void *)smnp
->msg_list
);
464 gprintf(level
, " msg_ids: 0x%p\n",
465 (void *)smnp
->msg_ids
);
466 gprintf(level
, " msg_strs: 0x%p\n",
467 (void *)smnp
->msg_strs
);
471 printgnumsg(Msg_g_node
*gmnp
, int level
)
473 gprintf(level
, "=== gnumsg ===\n");
474 gprintf(level
, " msg_file_info: 0x%p\n", gmnp
->msg_file_info
);
475 gprintf(level
, " magic: 0x%x\n",
476 gmnp
->msg_file_info
->magic
);
477 gprintf(level
, " revision: %d\n",
478 SWAP(gmnp
, gmnp
->msg_file_info
->revision
));
479 gprintf(level
, " num_of_str: %d\n",
480 SWAP(gmnp
, gmnp
->msg_file_info
->num_of_str
));
481 gprintf(level
, " off_msgid_tbl: %d\n",
482 SWAP(gmnp
, gmnp
->msg_file_info
->off_msgid_tbl
));
483 gprintf(level
, " off_msgstr_tbl: %d\n",
484 SWAP(gmnp
, gmnp
->msg_file_info
->off_msgstr_tbl
));
485 gprintf(level
, " sz_hashtbl: %d\n",
486 SWAP(gmnp
, gmnp
->msg_file_info
->sz_hashtbl
));
487 gprintf(level
, " off_hashtbl: %d\n",
488 SWAP(gmnp
, gmnp
->msg_file_info
->off_hashtbl
));
489 if (gmnp
->flag
& ST_REV1
) {
490 struct gnu_msg_rev1_info
*a
=
491 (struct gnu_msg_rev1_info
*)(uintptr_t)
492 ((char *)gmnp
->msg_file_info
+
493 sizeof (struct gnu_msg_info
));
494 gprintf(level
, " num_of_dynamic_macro: %d\n",
495 SWAP(gmnp
, a
->num_of_dynamic_macro
));
496 gprintf(level
, " off_dynamic_macro: %d\n",
497 SWAP(gmnp
, a
->off_dynamic_macro
));
498 gprintf(level
, " num_of_dynamic_str: %d\n",
499 SWAP(gmnp
, a
->num_of_dynamic_str
));
500 gprintf(level
, " off_dynamic_msgid_tbl: %d\n",
501 SWAP(gmnp
, a
->off_dynamic_msgid_tbl
));
502 gprintf(level
, " off_dynamic_msgstr_tbl: %d\n",
503 SWAP(gmnp
, a
->off_dynamic_msgstr_tbl
));
505 gprintf(level
, " fsize: %lu\n", gmnp
->fsize
);
506 gprintf(level
, " flag: %08x\n", gmnp
->flag
);
507 gprintf(level
, " num_of_str: %u\n", gmnp
->num_of_str
);
508 gprintf(level
, " num_of_d_str: %u\n", gmnp
->num_of_d_str
);
509 gprintf(level
, " hash_size: %u\n", gmnp
->hash_size
);
510 gprintf(level
, " hash_table: 0x%p\n", (void *)gmnp
->hash_table
);
511 gprintf(level
, " d_msgid: 0x%p\n", (void *)gmnp
->d_msg
[MSGID
]);
512 gprintf(level
, " d_msgstr: 0x%p\n", (void *)gmnp
->d_msg
[MSGSTR
]);
513 gprintf(level
, " mchunk: 0x%p\n", (void *)gmnp
->mchunk
);
515 gprintf(level
, " src_encoding: \"%s\"\n",
516 gmnp
->src_encoding
? gmnp
->src_encoding
: "(null)");
517 gprintf(level
, " dst_encoding: \"%s\"\n",
518 gmnp
->dst_encoding
? gmnp
->dst_encoding
: "(null)");
519 gprintf(level
, " nplurals: %d\n",
521 gprintf(level
, " plural: 0x%p\n",
522 (void *)gmnp
->plural
);
524 printexpr(gmnp
->plural
, level
+1);
525 gprintf(level
, " fd: 0x%p\n", (void *)gmnp
->fd
);
526 gprintf(level
, " conv_msgstr: 0x%p\n",
527 (void *)gmnp
->conv_msgstr
);
531 printexpr(struct expr
*e
, int level
)
533 static const char *op_name
[] = {
534 "NULL", "INIT", "EXP",
535 "NUM", "VAR", "?", ":", "||",
536 "&&", "==", "!=", ">", "<",
537 ">=", "<=", "+", "-", "*", "/",
538 "%", "!", "(", ")", "ERR"
540 switch (GETOPNUM(e
->op
)) {
542 switch (GETTYPE(e
->op
)) {
544 gprintf(level
, "NUM(%d)\n", e
->num
);
547 gprintf(level
, "VAR(n)\n");
552 gprintf(level
, "OP: !\n");
553 printexpr(e
->nodes
[0], level
+1);
556 gprintf(level
, "OP: %s\n", op_name
[GETTYPE(e
->op
)]);
557 printexpr(e
->nodes
[0], level
+1);
558 printexpr(e
->nodes
[1], level
+1);
561 gprintf(level
, "OP: ?\n");
563 printexpr(e
->nodes
[0], level
+1);
564 printexpr(e
->nodes
[1], level
+1);
565 printexpr(e
->nodes
[2], level
+1);
572 printmnp(Msg_node
*mnp
, int level
)
574 gprintf(level
, "=== mnp ===\n");
576 gprintf(level
, " hashid: %d\n", mnp
->hashid
);
577 gprintf(level
, " type: \"%s\"\n",
578 mnp
->type
== T_ILL_MO
? "T_ILL_MO" :
579 mnp
->type
== T_SUN_MO
? "T_SUN_MO" :
580 mnp
->type
== T_GNU_MO
? "T_GNU_MO" :
582 gprintf(level
, " path: \"%s\"\n",
583 mnp
->path
? mnp
->path
: "(null)");
584 gprintf(level
, " msg_file_trusted: %d\n",
586 if (mnp
->type
== T_SUN_MO
)
587 printsunmsg(mnp
->msg
.sunmsg
, level
+1);
588 else if (mnp
->type
== T_GNU_MO
)
589 printgnumsg(mnp
->msg
.gnumsg
, level
+1);
590 gprintf(level
, " next: 0x%p\n", (void *)mnp
->next
);
594 printnls(Nls_node
*n
, int level
)
596 gprintf(level
, "=== nls ===\n");
597 gprintf(level
, " domain: \"%s\"\n", n
->domain
? n
->domain
: "NULL");
598 gprintf(level
, " locale: \"%s\"\n", n
->locale
? n
->locale
: "NULL");
599 gprintf(level
, " nlspath: \"%s\"\n", n
->nlspath
? n
->nlspath
:
601 gprintf(level
, " next: 0x%p\n", n
->next
);
605 printdbind(Dbinding
*d
, int level
)
607 gprintf(level
, "=== dbind ===\n");
608 gprintf(level
, " domain: \"%s\"\n", d
->domain
? d
->domain
: "NULL");
609 gprintf(level
, " binding: \"%s\"\n", d
->binding
? d
->binding
:
611 gprintf(level
, " codeset: \"%s\"\n", d
->codeset
? d
->codeset
:
613 gprintf(level
, " next: 0x%p\n", d
->next
);
617 printgt(Gettext_t
*gt
, int level
)
619 gprintf(level
, "=== gt ===\n");
620 gprintf(level
, " cur_domain: \"%s\"\n", gt
->cur_domain
);
622 printdbind(gt
->dbind
, level
+1);
624 gprintf(level
, " dbind: NULL\n");
627 printmnp(gt
->m_node
, level
+ 1);
629 gprintf(level
, " m_node: NULL\n");
632 printnls(gt
->n_node
, level
+ 1);
634 gprintf(level
, " n_node: NULL\n");
637 printmnp(gt
->c_m_node
, level
+ 1);
639 gprintf(level
, " c_m_node: NULL\n");
642 printnls(gt
->c_n_node
, level
+ 1);
644 gprintf(level
, " c_n_node: NULL\n");