xref: /onnv-gate/usr/src/lib/libc/port/i18n/gettext_util.c (revision 6812:febeba71273d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56793Smuffin  * Common Development and Distribution License (the "License").
66793Smuffin  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
216793Smuffin 
220Sstevel@tonic-gate /*
236793Smuffin  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
29*6812Sraf #include "lint.h"
300Sstevel@tonic-gate #include "mtlib.h"
310Sstevel@tonic-gate #include <ctype.h>
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <unistd.h>
370Sstevel@tonic-gate #include <sys/mman.h>
380Sstevel@tonic-gate #include <langinfo.h>
390Sstevel@tonic-gate #include "libc.h"
400Sstevel@tonic-gate #include "_loc_path.h"
410Sstevel@tonic-gate #include "msgfmt.h"
420Sstevel@tonic-gate #include "gettext.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
450Sstevel@tonic-gate #include "plural_parser.h"
460Sstevel@tonic-gate #include <stdarg.h>
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static const char	*category_name[] = {
500Sstevel@tonic-gate 	"LC_CTYPE",
510Sstevel@tonic-gate 	"LC_NUMERIC",
520Sstevel@tonic-gate 	"LC_TIME",
530Sstevel@tonic-gate 	"LC_COLLATE",
540Sstevel@tonic-gate 	"LC_MONETARY",
550Sstevel@tonic-gate 	"LC_MESSAGES"
560Sstevel@tonic-gate };
570Sstevel@tonic-gate 
580Sstevel@tonic-gate static const int	category_name_len[] = {
590Sstevel@tonic-gate 	8,
600Sstevel@tonic-gate 	10,
610Sstevel@tonic-gate 	7,
620Sstevel@tonic-gate 	10,
630Sstevel@tonic-gate 	11,
640Sstevel@tonic-gate 	11
650Sstevel@tonic-gate };
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate  * mk_msgfile
690Sstevel@tonic-gate  *
700Sstevel@tonic-gate  * INPUT
710Sstevel@tonic-gate  * mp -	uses the following members:
720Sstevel@tonic-gate  * 	msgfile  - buffer to store the pathname to the message file
730Sstevel@tonic-gate  *	binding  - directory pathname bound to specified domain
740Sstevel@tonic-gate  *	cblen    - length of binding
750Sstevel@tonic-gate  *	locale   - locale name
760Sstevel@tonic-gate  *	domain   - domain name
770Sstevel@tonic-gate  *	category - category
780Sstevel@tonic-gate  *	domain_len - length of domain name
790Sstevel@tonic-gate  *
800Sstevel@tonic-gate  * OUTPUT
810Sstevel@tonic-gate  * mp->msgfile - pathname to the message file is stored
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * RETURN
840Sstevel@tonic-gate  * mp->msgfile is returned
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate char *
mk_msgfile(struct msg_pack * mp)870Sstevel@tonic-gate mk_msgfile(struct msg_pack *mp)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	char	*p, *q;
900Sstevel@tonic-gate 	const char	*catstr;
916793Smuffin 	uint32_t	cblen, loclen, catlen, totallen;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
946793Smuffin 	gprintf(0, "*************** mk_msgfile(0x%p)\n", (void *)mp);
956793Smuffin 	printmp(mp, 1);
960Sstevel@tonic-gate #endif
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	p = mp->msgfile;
990Sstevel@tonic-gate 	q = mp->binding;
1000Sstevel@tonic-gate 	while (*p = *q++)
1010Sstevel@tonic-gate 		p++;
1026793Smuffin 	cblen = (uint32_t)(p - mp->msgfile);
1030Sstevel@tonic-gate 	if (*(p - 1) != '/') {
1040Sstevel@tonic-gate 		/*
1050Sstevel@tonic-gate 		 * if the last character of binding
1060Sstevel@tonic-gate 		 * isn't a '/', adding '/'.
1070Sstevel@tonic-gate 		 */
1080Sstevel@tonic-gate 		if (cblen + 1 >= MAXPATHLEN) {
1090Sstevel@tonic-gate 			/* MAXPATHLEN includes a null termination */
1100Sstevel@tonic-gate 			return (NULL);
1110Sstevel@tonic-gate 		}
1120Sstevel@tonic-gate 		*p++ = '/';
1130Sstevel@tonic-gate 		cblen++;
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 
1166793Smuffin 	loclen = strlen(mp->locale);
1170Sstevel@tonic-gate 	catstr = category_name[mp->category];
1186793Smuffin 	catlen = (uint32_t)category_name_len[mp->category];
1190Sstevel@tonic-gate 	/*
1200Sstevel@tonic-gate 	 * totallen is the length of the msgfile
1210Sstevel@tonic-gate 	 * pathname excluding a null termination.
1220Sstevel@tonic-gate 	 */
1230Sstevel@tonic-gate 
1246793Smuffin 	totallen = cblen + loclen + 1 + catlen + 1 +
1256793Smuffin 	    mp->domain_len + MSGFILESUFFIXLEN;
1260Sstevel@tonic-gate 	if (totallen >= MAXPATHLEN)
1270Sstevel@tonic-gate 		return (NULL);
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	q = mp->locale;
1300Sstevel@tonic-gate 	while (*p++ = *q++)
1310Sstevel@tonic-gate 		;
1320Sstevel@tonic-gate 	*(p - 1) = '/';
1330Sstevel@tonic-gate 	while (*p++ = *catstr++)
1340Sstevel@tonic-gate 		;
1350Sstevel@tonic-gate 	*(p - 1) = '/';
1360Sstevel@tonic-gate 	q = mp->domain;
1376793Smuffin 	while (*p = *q++)
1386793Smuffin 		p++;
1396793Smuffin 	q = MSGFILESUFFIX;
1400Sstevel@tonic-gate 	while (*p++ = *q++)
1410Sstevel@tonic-gate 		;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
1446793Smuffin 	gprintf(0, "*************** Exiting mk_msgfile\n");
1456793Smuffin 	gprintf(0, "mp->msgfile: \"%s\"\n", mp->msgfile);
1460Sstevel@tonic-gate #endif
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	return (mp->msgfile);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate  * check_cache
1530Sstevel@tonic-gate  *
1540Sstevel@tonic-gate  * INPUT
1550Sstevel@tonic-gate  * mp - may use the following members:
1560Sstevel@tonic-gate  *	msgfile - pathname to the message catalog file
1576793Smuffin  *	hash_domain - hash id of this domain
1580Sstevel@tonic-gate  *
1590Sstevel@tonic-gate  * RETURN
1606793Smuffin  * non-NULL
1616793Smuffin  *	pointer to the Msg_node object of the current message catalog
1626793Smuffin  *	found in the cache
1636793Smuffin  *
1646793Smuffin  * NULL
1656793Smuffin  *	this message catalog does not exist in the cache
1660Sstevel@tonic-gate  */
1676793Smuffin Msg_node *
check_cache(struct msg_pack * mp)1686793Smuffin check_cache(struct msg_pack *mp)
1690Sstevel@tonic-gate {
1706793Smuffin 	Msg_node	*cur_msg, *mnp;
1710Sstevel@tonic-gate 	Gettext_t	*gt = global_gt;
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
1746793Smuffin 	gprintf(0, "*************** check_cache(0x%p)\n", mp);
1756793Smuffin 	printmp(mp, 1);
1760Sstevel@tonic-gate #endif
1770Sstevel@tonic-gate 
1786793Smuffin 	cur_msg = gt->c_m_node;		/* current Msg_node */
1790Sstevel@tonic-gate 	if (cur_msg &&
1806793Smuffin 	    cur_msg->hashid == mp->hash_domain &&
1816793Smuffin 	    strcmp(cur_msg->path, mp->msgfile) == 0) {
1820Sstevel@tonic-gate 		/*
1830Sstevel@tonic-gate 		 * msgfile is the same as the previous message file
1840Sstevel@tonic-gate 		 */
1850Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
1866793Smuffin 		gprintf(0, "*** cache found\n");
1876793Smuffin 		gprintf(0, "************* exiting check_cache\n");
1886793Smuffin 		printmnp(cur_msg, 1);
1890Sstevel@tonic-gate #endif
1906793Smuffin 		return (cur_msg);
1910Sstevel@tonic-gate 	}
1926793Smuffin 	mnp = gt->m_node;
1936793Smuffin 	while (mnp) {
1940Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
1956793Smuffin 		gprintf(0, "========== descending the list\n");
1966793Smuffin 		gprintf(0, "  hashid: %d, hash_domain: %d\n",
1976793Smuffin 		    mnp->hashid, mp->hash_domain);
1986793Smuffin 		printmnp(mnp, 1);
1990Sstevel@tonic-gate #endif
2006793Smuffin 		if (mnp->hashid == mp->hash_domain &&
2016793Smuffin 		    strcmp(mnp->path, mp->msgfile) == 0) {
2020Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
2036793Smuffin 			gprintf(0, "*** cache found\n");
2046793Smuffin 			gprintf(0, "******* exiting check_cache\n");
2056793Smuffin 			printmnp(mnp, 1);
2060Sstevel@tonic-gate #endif
2076793Smuffin 			gt->c_m_node = mnp;
2086793Smuffin 			return (mnp);
2090Sstevel@tonic-gate 		}
2106793Smuffin 		mnp = mnp->next;
2110Sstevel@tonic-gate 	}
2126793Smuffin 
2130Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
2146793Smuffin 	gprintf(0, "*** cache not found\n");
2156793Smuffin 	gprintf(0, "******* exiting check_cache\n");
2160Sstevel@tonic-gate #endif
2176793Smuffin 	return (NULL);
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate char *
get_codeset(const char * domain)2210Sstevel@tonic-gate get_codeset(const char *domain)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate 	char	*codeset;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
2266793Smuffin 	gprintf(0, "*************** get_codeset(\"%s\")\n",
2276793Smuffin 	    domain ? domain : "(null)");
2280Sstevel@tonic-gate #endif
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	codeset = _real_bindtextdomain_u(domain, NULL, TP_CODESET);
2316793Smuffin 	if (codeset == NULL) {
2320Sstevel@tonic-gate 		/* no codeset is bound to this domain */
2330Sstevel@tonic-gate 		codeset = nl_langinfo(CODESET);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
2366793Smuffin 	gprintf(0, "*************** existing get_codeset(\"%s\")\n",
2376793Smuffin 	    domain ? domain : "(null)");
2386793Smuffin 	gprintf(0, "                = \"%s\"\n", codeset);
2390Sstevel@tonic-gate #endif
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	return (codeset);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate /*
2456793Smuffin  * get_hashid (hashpjw)
2460Sstevel@tonic-gate  *
2470Sstevel@tonic-gate  * Calculates the hash value from the specified string.
2480Sstevel@tonic-gate  * Actual hashid will be mod(hash value, PRIME_NUMBER).
2490Sstevel@tonic-gate  *
2500Sstevel@tonic-gate  * Ref: Compilers - Principles, Techniques, and Tools
2510Sstevel@tonic-gate  * Aho, Sethi, and Ullman
2520Sstevel@tonic-gate  */
2536793Smuffin uint32_t
get_hashid(const char * str,uint32_t * len)2546793Smuffin get_hashid(const char *str, uint32_t *len)
2550Sstevel@tonic-gate {
2566793Smuffin 	const unsigned char	*p = (unsigned char *)str;
2576793Smuffin 	uint32_t	h = 0;
2586793Smuffin 	uint32_t	g;
2590Sstevel@tonic-gate 
2606793Smuffin 	for (; *p; p++) {
2610Sstevel@tonic-gate 		h = (h << 4) + *p;
2620Sstevel@tonic-gate 		g = h & 0xf0000000;
2630Sstevel@tonic-gate 		if (g) {
2640Sstevel@tonic-gate 			h = h ^ (g >> 24);
2650Sstevel@tonic-gate 			h = h ^ g;
2660Sstevel@tonic-gate 		}
2670Sstevel@tonic-gate 	}
2686793Smuffin 
2690Sstevel@tonic-gate 	if (len)
2706793Smuffin 		*len = (uint32_t)(p - (unsigned char *)str);
2710Sstevel@tonic-gate 	return (h);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate 
2746793Smuffin uint32_t
doswap32(uint32_t n)2756793Smuffin doswap32(uint32_t n)
2760Sstevel@tonic-gate {
2776793Smuffin 	uint32_t	r;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	r = (n << 24) | ((n & 0xff00) << 8) |
2806793Smuffin 	    ((n >> 8) & 0xff00) | (n >> 24);
2810Sstevel@tonic-gate 	return (r);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
2856793Smuffin static uint32_t
search_msg(Msg_g_node * p,const char * id,uint32_t hash_val,struct gnu_msg_ent * m)2866793Smuffin search_msg(Msg_g_node *p, const char *id, uint32_t hash_val,
2876793Smuffin     struct gnu_msg_ent *m)
2886793Smuffin {
2896793Smuffin 	char	*base = (char *)p->msg_file_info;
2906793Smuffin 	uint32_t	hash_size, num_of_str, i, idx, inc;
2916793Smuffin 	char	*ms;
2926793Smuffin 
2936793Smuffin 	num_of_str = p->num_of_str;
2946793Smuffin 	hash_size = p->hash_size;
2956793Smuffin 	idx = hash_val % hash_size;
2966793Smuffin 	inc = 1 + (hash_val % (hash_size - 2));
2976793Smuffin 
2986793Smuffin 	while ((i = p->hash_table[idx]) != 0) {
2996793Smuffin 		ms = (i <= num_of_str) ?
3006793Smuffin 		    base + SWAP(p, m[i-1].offset) :
3016793Smuffin 		    p->mchunk + p->d_msg[MSGID][i-num_of_str-1].offset;
3026793Smuffin 		if (strcmp(id, ms) == 0) {
3036793Smuffin 			/* found */
3046793Smuffin 			return (i);
3056793Smuffin 		}
3066793Smuffin 		idx = (idx + inc) % hash_size;
3076793Smuffin 	}
3086793Smuffin 	/* not found */
3096793Smuffin 	return (0);
3106793Smuffin }
3116793Smuffin 
3126793Smuffin void
print_rev1_info(Msg_g_node * p)3136793Smuffin print_rev1_info(Msg_g_node *p)
3146793Smuffin {
3156793Smuffin 	char	*base = (char *)p->msg_file_info;
3166793Smuffin 	struct gnu_msg_info	*header = p->msg_file_info;
3176793Smuffin 	struct gnu_msg_ent	*m;
3186793Smuffin 	uint32_t	hv, hidx;
3196793Smuffin 	char	*ms;
3206793Smuffin 	enum gnu_msgidstr	v;
3216793Smuffin 	int	x;
3226793Smuffin 
3236793Smuffin #ifdef	GETTEXT_DEBUG_DYMMSG
3246793Smuffin 	gprintf(0, "******** dynamic msgid/msgstr\n");
3256793Smuffin 	for (v = MSGID; v <= MSGSTR; v++) {
3266793Smuffin 		for (x = 0; x < p->num_of_d_str; x++) {
3276793Smuffin 			gprintf(0, "len: %u\n", p->d_msg[v][x].len);
3286793Smuffin 			gprintf(0, "str: \"%s\"\n",
3296793Smuffin 			    p->mchunk + p->d_msg[v][x].offset);
3306793Smuffin 		}
3316793Smuffin 	}
3326793Smuffin #endif
3336793Smuffin #ifdef	GETTEXT_DEBUG_HASHTBL
3346793Smuffin 	gprintf(0, "******** dynamic hash table\n");
3356793Smuffin 	for (x = 0; x < p->hash_size; x++) {
3366793Smuffin 		gprintf(0, "%d: %u\n", x, p->hash_table[x]);
3376793Smuffin 	}
3386793Smuffin #endif
3396793Smuffin #ifdef	GETTEXT_DEBUG_CHECK_STMSGID
3406793Smuffin 	gprintf(0, "******** sanity check of static msgid\n");
3416793Smuffin 	m = (struct gnu_msg_ent *)(uintptr_t)
3426793Smuffin 	    (base + SWAP(p, header->off_msgid_tbl));
3436793Smuffin 	for (x = 0; x < p->num_of_str; x++) {
3446793Smuffin 		ms = base + SWAP(p, m[x].offset);
3456793Smuffin 		gprintf(0, "\"%s\"\n", ms);
3466793Smuffin 		hv = get_hashid(ms, NULL);
3476793Smuffin 		hidx = search_msg(p, ms, hv, m);
3486793Smuffin 		if (hidx == 0) {
3496793Smuffin 			gprintf(0,
3506793Smuffin 			    "failed to find this msg in the hash table\n");
3516793Smuffin 		} else {
3526793Smuffin 			if (hidx != x + 1) {
3536793Smuffin 				gprintf(0, "hash table mismatch\n");
3546793Smuffin 			}
3556793Smuffin 		}
3566793Smuffin 	}
3576793Smuffin #endif
3586793Smuffin #ifdef	GETTEXT_DEBUG_CHECK_DYMMSGID
3596793Smuffin 	gprintf(0, "******* sanity check of dynamic msgid\n");
3606793Smuffin 	m = (struct gnu_msg_ent *)(uintptr_t)
3616793Smuffin 	    (base + SWAP(p, header->off_msgid_tbl));
3626793Smuffin 	for (x = 0; x < p->num_of_d_str; x++) {
3636793Smuffin 		ms = p->mchunk + p->d_msg[MSGID][x].offset;
3646793Smuffin 		gprintf(0, "\"%s\"\n", ms);
3656793Smuffin 		hv = get_hashid(ms, NULL);
3666793Smuffin 		hidx = search_msg(p, ms, hv, m);
3676793Smuffin 		if (hidx == 0) {
3686793Smuffin 			gprintf(0,
3696793Smuffin 			    "failed to find this msg in the hash table\n");
3706793Smuffin 		} else {
3716793Smuffin 			if (hidx != x + p->num_of_str + 1) {
3726793Smuffin 				gprintf(0, "hash table mismatch\n");
3736793Smuffin 			}
3746793Smuffin 		}
3756793Smuffin 	}
3766793Smuffin #endif
3776793Smuffin }
3786793Smuffin 
3790Sstevel@tonic-gate void
gprintf(int level,const char * format,...)3800Sstevel@tonic-gate gprintf(int level, const char *format, ...)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate 	va_list	ap;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	va_start(ap, format);
3850Sstevel@tonic-gate 
3866793Smuffin 	while (level-- > 0) {
3870Sstevel@tonic-gate 		(void) fputs("   ", stdout);
3880Sstevel@tonic-gate 	}
3890Sstevel@tonic-gate 	(void) vprintf(format, ap);
3900Sstevel@tonic-gate 	va_end(ap);
3916793Smuffin 
3926793Smuffin 	(void) fflush(stdout);
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate void
printlist(void)3960Sstevel@tonic-gate printlist(void)
3970Sstevel@tonic-gate {
3980Sstevel@tonic-gate 	struct domain_binding	*ppp;
3990Sstevel@tonic-gate 	Gettext_t	*gt = global_gt;
4000Sstevel@tonic-gate 
4016793Smuffin 	gprintf(0, "=== Printing default list and regural list\n");
4026793Smuffin 	gprintf(0, "   Default domain=<%s>, binding=<%s>\n",
4030Sstevel@tonic-gate 	    DEFAULT_DOMAIN, defaultbind);
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	ppp = FIRSTBIND(gt);
4060Sstevel@tonic-gate 	while (ppp) {
4076793Smuffin 		gprintf(0, "   domain=<%s>, binding=<%s>, codeset=<%s>\n",
4080Sstevel@tonic-gate 		    ppp->domain ? ppp->domain : "(null)",
4096793Smuffin 		    ppp->binding ? ppp->binding : "(null)",
4106793Smuffin 		    ppp->codeset ? ppp->codeset : "(null)");
4110Sstevel@tonic-gate 		ppp = ppp->next;
4120Sstevel@tonic-gate 	}
4136793Smuffin 	(void) fflush(stdout);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate void
printmp(struct msg_pack * mp,int level)4170Sstevel@tonic-gate printmp(struct msg_pack *mp, int level)
4180Sstevel@tonic-gate {
4190Sstevel@tonic-gate 	gprintf(level, "=== mp ===\n");
4200Sstevel@tonic-gate 	gprintf(level, "   msgid1: \"%s\"\n",
4216793Smuffin 	    mp->msgid1 ? mp->msgid1 : "(null)");
4220Sstevel@tonic-gate 	gprintf(level, "   msgid2: \"%s\"\n",
4236793Smuffin 	    mp->msgid2 ? mp->msgid2 : "(null)");
4246793Smuffin 	gprintf(level, "   msgfile: \"%s\"\n",
4256793Smuffin 	    mp->msgfile ? mp->msgfile : "(null)");
4260Sstevel@tonic-gate 	gprintf(level, "   domain: \"%s\"\n",
4276793Smuffin 	    mp->domain ? mp->domain : "(null)");
4280Sstevel@tonic-gate 	gprintf(level, "   binding: \"%s\"\n",
4296793Smuffin 	    mp->binding ? mp->binding : "(null)");
4300Sstevel@tonic-gate 	gprintf(level, "   locale: \"%s\"\n",
4316793Smuffin 	    mp->locale ? mp->locale : "(null)");
4320Sstevel@tonic-gate 	gprintf(level, "   language: \"%s\"\n",
4336793Smuffin 	    mp->language ? mp->language : "(null)");
4340Sstevel@tonic-gate 	gprintf(level, "   addr: 0x%p\n", mp->addr);
4350Sstevel@tonic-gate 	gprintf(level, "   fsz: %d\n", mp->fsz);
4366793Smuffin 	gprintf(level, "   hash_domain: %d\n", mp->hash_domain);
4376793Smuffin 	gprintf(level, "   domain_len: %d\n", mp->domain_len);
4386793Smuffin 	gprintf(level, "   n: %d\n", mp->n);
4396793Smuffin 	gprintf(level, "   category: \"%s\"\n",
4406793Smuffin 	    category_name[mp->category]);
4416793Smuffin 	gprintf(level, "   plural: %d\n", mp->plural);
4426793Smuffin 	gprintf(level, "   nlsp: %d\n", mp->nlsp);
4430Sstevel@tonic-gate 	gprintf(level, "   trusted: %d\n", mp->trusted);
4446793Smuffin 	gprintf(level, "   status: %d\n", mp->status);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate void
printsunmsg(Msg_s_node * smnp,int level)4480Sstevel@tonic-gate printsunmsg(Msg_s_node *smnp, int level)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate 	gprintf(level, "=== sunmsg ===\n");
4510Sstevel@tonic-gate 	gprintf(level, "   msg_file_info: 0x%p\n",
4526793Smuffin 	    (void *)smnp->msg_file_info);
4530Sstevel@tonic-gate 	gprintf(level, "      msg_mid: %d\n",
4546793Smuffin 	    smnp->msg_file_info->msg_mid);
4550Sstevel@tonic-gate 	gprintf(level, "      msg_count: %d\n",
4566793Smuffin 	    smnp->msg_file_info->msg_count);
4570Sstevel@tonic-gate 	gprintf(level, "      str_count_msgid: %d\n",
4586793Smuffin 	    smnp->msg_file_info->str_count_msgid);
4590Sstevel@tonic-gate 	gprintf(level, "      str_count_msgstr: %d\n",
4606793Smuffin 	    smnp->msg_file_info->str_count_msgstr);
4610Sstevel@tonic-gate 	gprintf(level, "      msg_struct_size: %d\n",
4626793Smuffin 	    smnp->msg_file_info->msg_struct_size);
4630Sstevel@tonic-gate 	gprintf(level, "   msg_list: 0x%p\n",
4646793Smuffin 	    (void *)smnp->msg_list);
4650Sstevel@tonic-gate 	gprintf(level, "   msg_ids: 0x%p\n",
4666793Smuffin 	    (void *)smnp->msg_ids);
4670Sstevel@tonic-gate 	gprintf(level, "   msg_strs: 0x%p\n",
4686793Smuffin 	    (void *)smnp->msg_strs);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate void
printgnumsg(Msg_g_node * gmnp,int level)4720Sstevel@tonic-gate printgnumsg(Msg_g_node *gmnp, int level)
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate 	gprintf(level, "=== gnumsg ===\n");
4756793Smuffin 	gprintf(level, "   msg_file_info: 0x%p\n", gmnp->msg_file_info);
4760Sstevel@tonic-gate 	gprintf(level, "      magic: 0x%x\n",
4776793Smuffin 	    gmnp->msg_file_info->magic);
4780Sstevel@tonic-gate 	gprintf(level, "      revision: %d\n",
4796793Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->revision));
4800Sstevel@tonic-gate 	gprintf(level, "      num_of_str: %d\n",
4816793Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->num_of_str));
4820Sstevel@tonic-gate 	gprintf(level, "      off_msgid_tbl: %d\n",
4836793Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->off_msgid_tbl));
4840Sstevel@tonic-gate 	gprintf(level, "      off_msgstr_tbl: %d\n",
4856793Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->off_msgstr_tbl));
4860Sstevel@tonic-gate 	gprintf(level, "      sz_hashtbl: %d\n",
4876793Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->sz_hashtbl));
4880Sstevel@tonic-gate 	gprintf(level, "      off_hashtbl: %d\n",
4896793Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->off_hashtbl));
4906793Smuffin 	if (gmnp->flag & ST_REV1) {
4916793Smuffin 		struct gnu_msg_rev1_info	*a =
4926793Smuffin 		    (struct gnu_msg_rev1_info *)(uintptr_t)
4936793Smuffin 		    ((char *)gmnp->msg_file_info +
4946793Smuffin 		    sizeof (struct gnu_msg_info));
4956793Smuffin 		gprintf(level, "      num_of_dynamic_macro: %d\n",
4966793Smuffin 		    SWAP(gmnp, a->num_of_dynamic_macro));
4976793Smuffin 		gprintf(level, "      off_dynamic_macro: %d\n",
4986793Smuffin 		    SWAP(gmnp, a->off_dynamic_macro));
4996793Smuffin 		gprintf(level, "      num_of_dynamic_str: %d\n",
5006793Smuffin 		    SWAP(gmnp, a->num_of_dynamic_str));
5016793Smuffin 		gprintf(level, "      off_dynamic_msgid_tbl: %d\n",
5026793Smuffin 		    SWAP(gmnp, a->off_dynamic_msgid_tbl));
5036793Smuffin 		gprintf(level, "      off_dynamic_msgstr_tbl: %d\n",
5046793Smuffin 		    SWAP(gmnp, a->off_dynamic_msgstr_tbl));
5056793Smuffin 	}
5066793Smuffin 	gprintf(level, "   fsize: %lu\n", gmnp->fsize);
5076793Smuffin 	gprintf(level, "   flag: %08x\n", gmnp->flag);
5086793Smuffin 	gprintf(level, "   num_of_str: %u\n", gmnp->num_of_str);
5096793Smuffin 	gprintf(level, "   num_of_d_str: %u\n", gmnp->num_of_d_str);
5106793Smuffin 	gprintf(level, "   hash_size: %u\n", gmnp->hash_size);
5116793Smuffin 	gprintf(level, "   hash_table: 0x%p\n", (void *)gmnp->hash_table);
5126793Smuffin 	gprintf(level, "   d_msgid: 0x%p\n", (void *)gmnp->d_msg[MSGID]);
5136793Smuffin 	gprintf(level, "   d_msgstr: 0x%p\n", (void *)gmnp->d_msg[MSGSTR]);
5146793Smuffin 	gprintf(level, "   mchunk: 0x%p\n", (void *)gmnp->mchunk);
5156793Smuffin 
5160Sstevel@tonic-gate 	gprintf(level, "   src_encoding: \"%s\"\n",
5176793Smuffin 	    gmnp->src_encoding ? gmnp->src_encoding : "(null)");
5180Sstevel@tonic-gate 	gprintf(level, "   dst_encoding: \"%s\"\n",
5196793Smuffin 	    gmnp->dst_encoding ? gmnp->dst_encoding : "(null)");
5200Sstevel@tonic-gate 	gprintf(level, "   nplurals: %d\n",
5216793Smuffin 	    gmnp->nplurals);
5220Sstevel@tonic-gate 	gprintf(level, "   plural: 0x%p\n",
5236793Smuffin 	    (void *)gmnp->plural);
5240Sstevel@tonic-gate 	if (gmnp->plural)
5250Sstevel@tonic-gate 		printexpr(gmnp->plural, level+1);
5260Sstevel@tonic-gate 	gprintf(level, "   fd: 0x%p\n", (void *)gmnp->fd);
5270Sstevel@tonic-gate 	gprintf(level, "   conv_msgstr: 0x%p\n",
5286793Smuffin 	    (void *)gmnp->conv_msgstr);
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate void
printexpr(struct expr * e,int level)5320Sstevel@tonic-gate printexpr(struct expr *e, int level)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate 	static const char	*op_name[] = {
5356793Smuffin 	    "NULL", "INIT", "EXP",
5366793Smuffin 	    "NUM", "VAR", "?", ":", "||",
5376793Smuffin 	    "&&", "==", "!=", ">", "<",
5386793Smuffin 	    ">=", "<=", "+", "-", "*", "/",
5396793Smuffin 	    "%", "!", "(", ")", "ERR"
5400Sstevel@tonic-gate 	};
5410Sstevel@tonic-gate 	switch (GETOPNUM(e->op)) {
5420Sstevel@tonic-gate 	case 0:
5430Sstevel@tonic-gate 		switch (GETTYPE(e->op)) {
5440Sstevel@tonic-gate 		case T_NUM:
5450Sstevel@tonic-gate 			gprintf(level, "NUM(%d)\n", e->num);
5460Sstevel@tonic-gate 			break;
5470Sstevel@tonic-gate 		case T_VAR:
5480Sstevel@tonic-gate 			gprintf(level, "VAR(n)\n");
5490Sstevel@tonic-gate 			break;
5500Sstevel@tonic-gate 		}
5510Sstevel@tonic-gate 		break;
5520Sstevel@tonic-gate 	case 1:
5530Sstevel@tonic-gate 		gprintf(level, "OP: !\n");
5540Sstevel@tonic-gate 		printexpr(e->nodes[0], level+1);
5550Sstevel@tonic-gate 		break;
5560Sstevel@tonic-gate 	case 2:
5570Sstevel@tonic-gate 		gprintf(level, "OP: %s\n", op_name[GETTYPE(e->op)]);
5580Sstevel@tonic-gate 		printexpr(e->nodes[0], level+1);
5590Sstevel@tonic-gate 		printexpr(e->nodes[1], level+1);
5600Sstevel@tonic-gate 		break;
5610Sstevel@tonic-gate 	case 3:
5620Sstevel@tonic-gate 		gprintf(level, "OP: ?\n");
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 		printexpr(e->nodes[0], level+1);
5650Sstevel@tonic-gate 		printexpr(e->nodes[1], level+1);
5660Sstevel@tonic-gate 		printexpr(e->nodes[2], level+1);
5670Sstevel@tonic-gate 		break;
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate void
printmnp(Msg_node * mnp,int level)5730Sstevel@tonic-gate printmnp(Msg_node *mnp, int level)
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate 	gprintf(level, "=== mnp ===\n");
5760Sstevel@tonic-gate 
5776793Smuffin 	gprintf(level, "   hashid: %d\n", mnp->hashid);
5780Sstevel@tonic-gate 	gprintf(level, "   type: \"%s\"\n",
5796793Smuffin 	    mnp->type == T_ILL_MO ? "T_ILL_MO" :
5806793Smuffin 	    mnp->type == T_SUN_MO ? "T_SUN_MO" :
5816793Smuffin 	    mnp->type == T_GNU_MO ? "T_GNU_MO" :
5826793Smuffin 	    "UNKNOWN TYPE");
5830Sstevel@tonic-gate 	gprintf(level, "   path: \"%s\"\n",
5846793Smuffin 	    mnp->path ? mnp->path : "(null)");
5850Sstevel@tonic-gate 	gprintf(level, "   msg_file_trusted: %d\n",
5866793Smuffin 	    mnp->trusted);
5870Sstevel@tonic-gate 	if (mnp->type == T_SUN_MO)
5880Sstevel@tonic-gate 		printsunmsg(mnp->msg.sunmsg, level+1);
5890Sstevel@tonic-gate 	else if (mnp->type == T_GNU_MO)
5900Sstevel@tonic-gate 		printgnumsg(mnp->msg.gnumsg, level+1);
5910Sstevel@tonic-gate 	gprintf(level, "   next: 0x%p\n", (void *)mnp->next);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate void
printnls(Nls_node * n,int level)5956793Smuffin printnls(Nls_node *n, int level)
5960Sstevel@tonic-gate {
5976793Smuffin 	gprintf(level, "=== nls ===\n");
5986793Smuffin 	gprintf(level, "   domain: \"%s\"\n", n->domain ? n->domain : "NULL");
5996793Smuffin 	gprintf(level, "   locale: \"%s\"\n", n->locale ? n->locale : "NULL");
6006793Smuffin 	gprintf(level, "   nlspath: \"%s\"\n", n->nlspath ? n->nlspath :
6016793Smuffin 	    "NULL");
6026793Smuffin 	gprintf(level, "   next: 0x%p\n", n->next);
6036793Smuffin }
6040Sstevel@tonic-gate 
6056793Smuffin void
printdbind(Dbinding * d,int level)6066793Smuffin printdbind(Dbinding *d, int level)
6076793Smuffin {
6086793Smuffin 	gprintf(level, "=== dbind ===\n");
6096793Smuffin 	gprintf(level, "   domain: \"%s\"\n", d->domain ? d->domain : "NULL");
6106793Smuffin 	gprintf(level, "   binding: \"%s\"\n", d->binding ? d->binding :
6116793Smuffin 	    "NULL");
6126793Smuffin 	gprintf(level, "   codeset: \"%s\"\n", d->codeset ? d->codeset :
6136793Smuffin 	    "NULL");
6146793Smuffin 	gprintf(level, "   next: 0x%p\n", d->next);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate void
printgt(Gettext_t * gt,int level)6186793Smuffin printgt(Gettext_t *gt, int level)
6190Sstevel@tonic-gate {
6206793Smuffin 	gprintf(level, "=== gt ===\n");
6216793Smuffin 	gprintf(level, "   cur_domain: \"%s\"\n", gt->cur_domain);
6226793Smuffin 	if (gt->dbind) {
6236793Smuffin 		printdbind(gt->dbind, level+1);
6246793Smuffin 	} else {
6256793Smuffin 		gprintf(level, "   dbind: NULL\n");
6266793Smuffin 	}
6276793Smuffin 	if (gt->m_node) {
6286793Smuffin 		printmnp(gt->m_node, level + 1);
6296793Smuffin 	} else {
6306793Smuffin 		gprintf(level, "   m_node: NULL\n");
6316793Smuffin 	}
6326793Smuffin 	if (gt->n_node) {
6336793Smuffin 		printnls(gt->n_node, level + 1);
6346793Smuffin 	} else {
6356793Smuffin 		gprintf(level, "   n_node: NULL\n");
6366793Smuffin 	}
6376793Smuffin 	if (gt->c_m_node) {
6386793Smuffin 		printmnp(gt->c_m_node, level + 1);
6396793Smuffin 	} else {
6406793Smuffin 		gprintf(level, "   c_m_node: NULL\n");
6416793Smuffin 	}
6426793Smuffin 	if (gt->c_n_node) {
6436793Smuffin 		printnls(gt->c_n_node, level + 1);
6446793Smuffin 	} else {
6456793Smuffin 		gprintf(level, "   c_n_node: NULL\n");
6466793Smuffin 	}
6470Sstevel@tonic-gate }
6486793Smuffin 
6490Sstevel@tonic-gate #endif
650