17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f13ac639Smuffin  * Common Development and Distribution License (the "License").
6f13ac639Smuffin  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21f13ac639Smuffin 
227c478bd9Sstevel@tonic-gate /*
23f13ac639Smuffin  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277257d1b4Sraf #include "lint.h"
287c478bd9Sstevel@tonic-gate #include "mtlib.h"
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <sys/mman.h>
367c478bd9Sstevel@tonic-gate #include <langinfo.h>
377c478bd9Sstevel@tonic-gate #include "libc.h"
387c478bd9Sstevel@tonic-gate #include "_loc_path.h"
397c478bd9Sstevel@tonic-gate #include "msgfmt.h"
407c478bd9Sstevel@tonic-gate #include "gettext.h"
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
437c478bd9Sstevel@tonic-gate #include "plural_parser.h"
447c478bd9Sstevel@tonic-gate #include <stdarg.h>
457c478bd9Sstevel@tonic-gate #endif
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate static const char	*category_name[] = {
487c478bd9Sstevel@tonic-gate 	"LC_CTYPE",
497c478bd9Sstevel@tonic-gate 	"LC_NUMERIC",
507c478bd9Sstevel@tonic-gate 	"LC_TIME",
517c478bd9Sstevel@tonic-gate 	"LC_COLLATE",
527c478bd9Sstevel@tonic-gate 	"LC_MONETARY",
537c478bd9Sstevel@tonic-gate 	"LC_MESSAGES"
547c478bd9Sstevel@tonic-gate };
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static const int	category_name_len[] = {
577c478bd9Sstevel@tonic-gate 	8,
587c478bd9Sstevel@tonic-gate 	10,
597c478bd9Sstevel@tonic-gate 	7,
607c478bd9Sstevel@tonic-gate 	10,
617c478bd9Sstevel@tonic-gate 	11,
627c478bd9Sstevel@tonic-gate 	11
637c478bd9Sstevel@tonic-gate };
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * mk_msgfile
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  * INPUT
697c478bd9Sstevel@tonic-gate  * mp -	uses the following members:
70*00ae5933SToomas Soome  *	msgfile  - buffer to store the pathname to the message file
717c478bd9Sstevel@tonic-gate  *	binding  - directory pathname bound to specified domain
727c478bd9Sstevel@tonic-gate  *	cblen    - length of binding
737c478bd9Sstevel@tonic-gate  *	locale   - locale name
747c478bd9Sstevel@tonic-gate  *	domain   - domain name
757c478bd9Sstevel@tonic-gate  *	category - category
767c478bd9Sstevel@tonic-gate  *	domain_len - length of domain name
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  * OUTPUT
797c478bd9Sstevel@tonic-gate  * mp->msgfile - pathname to the message file is stored
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  * RETURN
827c478bd9Sstevel@tonic-gate  * mp->msgfile is returned
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate char *
mk_msgfile(struct msg_pack * mp)857c478bd9Sstevel@tonic-gate mk_msgfile(struct msg_pack *mp)
867c478bd9Sstevel@tonic-gate {
87b599bd93SRobert Mustacchi 	const char *q;
88b599bd93SRobert Mustacchi 	char	*p;
897c478bd9Sstevel@tonic-gate 	const char	*catstr;
90f13ac639Smuffin 	uint32_t	cblen, loclen, catlen, totallen;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
93f13ac639Smuffin 	gprintf(0, "*************** mk_msgfile(0x%p)\n", (void *)mp);
94f13ac639Smuffin 	printmp(mp, 1);
957c478bd9Sstevel@tonic-gate #endif
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	p = mp->msgfile;
987c478bd9Sstevel@tonic-gate 	q = mp->binding;
99*00ae5933SToomas Soome 	while ((*p = *q++) != '\0')
1007c478bd9Sstevel@tonic-gate 		p++;
101f13ac639Smuffin 	cblen = (uint32_t)(p - mp->msgfile);
1027c478bd9Sstevel@tonic-gate 	if (*(p - 1) != '/') {
1037c478bd9Sstevel@tonic-gate 		/*
1047c478bd9Sstevel@tonic-gate 		 * if the last character of binding
1057c478bd9Sstevel@tonic-gate 		 * isn't a '/', adding '/'.
1067c478bd9Sstevel@tonic-gate 		 */
1077c478bd9Sstevel@tonic-gate 		if (cblen + 1 >= MAXPATHLEN) {
1087c478bd9Sstevel@tonic-gate 			/* MAXPATHLEN includes a null termination */
1097c478bd9Sstevel@tonic-gate 			return (NULL);
1107c478bd9Sstevel@tonic-gate 		}
1117c478bd9Sstevel@tonic-gate 		*p++ = '/';
1127c478bd9Sstevel@tonic-gate 		cblen++;
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
115f13ac639Smuffin 	loclen = strlen(mp->locale);
1167c478bd9Sstevel@tonic-gate 	catstr = category_name[mp->category];
117f13ac639Smuffin 	catlen = (uint32_t)category_name_len[mp->category];
1187c478bd9Sstevel@tonic-gate 	/*
1197c478bd9Sstevel@tonic-gate 	 * totallen is the length of the msgfile
1207c478bd9Sstevel@tonic-gate 	 * pathname excluding a null termination.
1217c478bd9Sstevel@tonic-gate 	 */
1227c478bd9Sstevel@tonic-gate 
123f13ac639Smuffin 	totallen = cblen + loclen + 1 + catlen + 1 +
124f13ac639Smuffin 	    mp->domain_len + MSGFILESUFFIXLEN;
1257c478bd9Sstevel@tonic-gate 	if (totallen >= MAXPATHLEN)
1267c478bd9Sstevel@tonic-gate 		return (NULL);
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	q = mp->locale;
129*00ae5933SToomas Soome 	while ((*p++ = *q++) != '\0')
1307c478bd9Sstevel@tonic-gate 		;
1317c478bd9Sstevel@tonic-gate 	*(p - 1) = '/';
132*00ae5933SToomas Soome 	while ((*p++ = *catstr++) != '\0')
1337c478bd9Sstevel@tonic-gate 		;
1347c478bd9Sstevel@tonic-gate 	*(p - 1) = '/';
1357c478bd9Sstevel@tonic-gate 	q = mp->domain;
136*00ae5933SToomas Soome 	while ((*p = *q++) != '\0')
137f13ac639Smuffin 		p++;
138f13ac639Smuffin 	q = MSGFILESUFFIX;
139*00ae5933SToomas Soome 	while ((*p++ = *q++) != '\0')
1407c478bd9Sstevel@tonic-gate 		;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
143f13ac639Smuffin 	gprintf(0, "*************** Exiting mk_msgfile\n");
144f13ac639Smuffin 	gprintf(0, "mp->msgfile: \"%s\"\n", mp->msgfile);
1457c478bd9Sstevel@tonic-gate #endif
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	return (mp->msgfile);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate /*
1517c478bd9Sstevel@tonic-gate  * check_cache
1527c478bd9Sstevel@tonic-gate  *
1537c478bd9Sstevel@tonic-gate  * INPUT
1547c478bd9Sstevel@tonic-gate  * mp - may use the following members:
1557c478bd9Sstevel@tonic-gate  *	msgfile - pathname to the message catalog file
156f13ac639Smuffin  *	hash_domain - hash id of this domain
1577c478bd9Sstevel@tonic-gate  *
1587c478bd9Sstevel@tonic-gate  * RETURN
159f13ac639Smuffin  * non-NULL
160f13ac639Smuffin  *	pointer to the Msg_node object of the current message catalog
161f13ac639Smuffin  *	found in the cache
162f13ac639Smuffin  *
163f13ac639Smuffin  * NULL
164f13ac639Smuffin  *	this message catalog does not exist in the cache
1657c478bd9Sstevel@tonic-gate  */
166f13ac639Smuffin Msg_node *
check_cache(struct msg_pack * mp)167f13ac639Smuffin check_cache(struct msg_pack *mp)
1687c478bd9Sstevel@tonic-gate {
169f13ac639Smuffin 	Msg_node	*cur_msg, *mnp;
1707c478bd9Sstevel@tonic-gate 	Gettext_t	*gt = global_gt;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
173f13ac639Smuffin 	gprintf(0, "*************** check_cache(0x%p)\n", mp);
174f13ac639Smuffin 	printmp(mp, 1);
1757c478bd9Sstevel@tonic-gate #endif
1767c478bd9Sstevel@tonic-gate 
177f13ac639Smuffin 	cur_msg = gt->c_m_node;		/* current Msg_node */
1787c478bd9Sstevel@tonic-gate 	if (cur_msg &&
179f13ac639Smuffin 	    cur_msg->hashid == mp->hash_domain &&
180f13ac639Smuffin 	    strcmp(cur_msg->path, mp->msgfile) == 0) {
1817c478bd9Sstevel@tonic-gate 		/*
1827c478bd9Sstevel@tonic-gate 		 * msgfile is the same as the previous message file
1837c478bd9Sstevel@tonic-gate 		 */
1847c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
185f13ac639Smuffin 		gprintf(0, "*** cache found\n");
186f13ac639Smuffin 		gprintf(0, "************* exiting check_cache\n");
187f13ac639Smuffin 		printmnp(cur_msg, 1);
1887c478bd9Sstevel@tonic-gate #endif
189f13ac639Smuffin 		return (cur_msg);
1907c478bd9Sstevel@tonic-gate 	}
191f13ac639Smuffin 	mnp = gt->m_node;
192f13ac639Smuffin 	while (mnp) {
1937c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
194f13ac639Smuffin 		gprintf(0, "========== descending the list\n");
195f13ac639Smuffin 		gprintf(0, "  hashid: %d, hash_domain: %d\n",
196f13ac639Smuffin 		    mnp->hashid, mp->hash_domain);
197f13ac639Smuffin 		printmnp(mnp, 1);
1987c478bd9Sstevel@tonic-gate #endif
199f13ac639Smuffin 		if (mnp->hashid == mp->hash_domain &&
200f13ac639Smuffin 		    strcmp(mnp->path, mp->msgfile) == 0) {
2017c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
202f13ac639Smuffin 			gprintf(0, "*** cache found\n");
203f13ac639Smuffin 			gprintf(0, "******* exiting check_cache\n");
204f13ac639Smuffin 			printmnp(mnp, 1);
2057c478bd9Sstevel@tonic-gate #endif
206f13ac639Smuffin 			gt->c_m_node = mnp;
207f13ac639Smuffin 			return (mnp);
2087c478bd9Sstevel@tonic-gate 		}
209f13ac639Smuffin 		mnp = mnp->next;
2107c478bd9Sstevel@tonic-gate 	}
211f13ac639Smuffin 
2127c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
213f13ac639Smuffin 	gprintf(0, "*** cache not found\n");
214f13ac639Smuffin 	gprintf(0, "******* exiting check_cache\n");
2157c478bd9Sstevel@tonic-gate #endif
216f13ac639Smuffin 	return (NULL);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate char *
get_codeset(const char * domain)2207c478bd9Sstevel@tonic-gate get_codeset(const char *domain)
2217c478bd9Sstevel@tonic-gate {
2227c478bd9Sstevel@tonic-gate 	char	*codeset;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
225f13ac639Smuffin 	gprintf(0, "*************** get_codeset(\"%s\")\n",
226f13ac639Smuffin 	    domain ? domain : "(null)");
2277c478bd9Sstevel@tonic-gate #endif
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	codeset = _real_bindtextdomain_u(domain, NULL, TP_CODESET);
230f13ac639Smuffin 	if (codeset == NULL) {
2317c478bd9Sstevel@tonic-gate 		/* no codeset is bound to this domain */
2327c478bd9Sstevel@tonic-gate 		codeset = nl_langinfo(CODESET);
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
235f13ac639Smuffin 	gprintf(0, "*************** existing get_codeset(\"%s\")\n",
236f13ac639Smuffin 	    domain ? domain : "(null)");
237f13ac639Smuffin 	gprintf(0, "                = \"%s\"\n", codeset);
2387c478bd9Sstevel@tonic-gate #endif
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	return (codeset);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate /*
244f13ac639Smuffin  * get_hashid (hashpjw)
2457c478bd9Sstevel@tonic-gate  *
2467c478bd9Sstevel@tonic-gate  * Calculates the hash value from the specified string.
2477c478bd9Sstevel@tonic-gate  * Actual hashid will be mod(hash value, PRIME_NUMBER).
2487c478bd9Sstevel@tonic-gate  *
2497c478bd9Sstevel@tonic-gate  * Ref: Compilers - Principles, Techniques, and Tools
2507c478bd9Sstevel@tonic-gate  * Aho, Sethi, and Ullman
2517c478bd9Sstevel@tonic-gate  */
252f13ac639Smuffin uint32_t
get_hashid(const char * str,uint32_t * len)253f13ac639Smuffin get_hashid(const char *str, uint32_t *len)
2547c478bd9Sstevel@tonic-gate {
255f13ac639Smuffin 	const unsigned char	*p = (unsigned char *)str;
256f13ac639Smuffin 	uint32_t	h = 0;
257f13ac639Smuffin 	uint32_t	g;
2587c478bd9Sstevel@tonic-gate 
259f13ac639Smuffin 	for (; *p; p++) {
2607c478bd9Sstevel@tonic-gate 		h = (h << 4) + *p;
2617c478bd9Sstevel@tonic-gate 		g = h & 0xf0000000;
2627c478bd9Sstevel@tonic-gate 		if (g) {
2637c478bd9Sstevel@tonic-gate 			h = h ^ (g >> 24);
2647c478bd9Sstevel@tonic-gate 			h = h ^ g;
2657c478bd9Sstevel@tonic-gate 		}
2667c478bd9Sstevel@tonic-gate 	}
267f13ac639Smuffin 
2687c478bd9Sstevel@tonic-gate 	if (len)
269f13ac639Smuffin 		*len = (uint32_t)(p - (unsigned char *)str);
2707c478bd9Sstevel@tonic-gate 	return (h);
2717c478bd9Sstevel@tonic-gate }
2727c478bd9Sstevel@tonic-gate 
273f13ac639Smuffin uint32_t
doswap32(uint32_t n)274f13ac639Smuffin doswap32(uint32_t n)
2757c478bd9Sstevel@tonic-gate {
276f13ac639Smuffin 	uint32_t	r;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	r = (n << 24) | ((n & 0xff00) << 8) |
279f13ac639Smuffin 	    ((n >> 8) & 0xff00) | (n >> 24);
2807c478bd9Sstevel@tonic-gate 	return (r);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
284f13ac639Smuffin static uint32_t
search_msg(Msg_g_node * p,const char * id,uint32_t hash_val,struct gnu_msg_ent * m)285f13ac639Smuffin search_msg(Msg_g_node *p, const char *id, uint32_t hash_val,
286f13ac639Smuffin     struct gnu_msg_ent *m)
287f13ac639Smuffin {
288f13ac639Smuffin 	char	*base = (char *)p->msg_file_info;
289f13ac639Smuffin 	uint32_t	hash_size, num_of_str, i, idx, inc;
290f13ac639Smuffin 	char	*ms;
291f13ac639Smuffin 
292f13ac639Smuffin 	num_of_str = p->num_of_str;
293f13ac639Smuffin 	hash_size = p->hash_size;
294f13ac639Smuffin 	idx = hash_val % hash_size;
295f13ac639Smuffin 	inc = 1 + (hash_val % (hash_size - 2));
296f13ac639Smuffin 
297f13ac639Smuffin 	while ((i = p->hash_table[idx]) != 0) {
298f13ac639Smuffin 		ms = (i <= num_of_str) ?
299f13ac639Smuffin 		    base + SWAP(p, m[i-1].offset) :
300f13ac639Smuffin 		    p->mchunk + p->d_msg[MSGID][i-num_of_str-1].offset;
301f13ac639Smuffin 		if (strcmp(id, ms) == 0) {
302f13ac639Smuffin 			/* found */
303f13ac639Smuffin 			return (i);
304f13ac639Smuffin 		}
305f13ac639Smuffin 		idx = (idx + inc) % hash_size;
306f13ac639Smuffin 	}
307f13ac639Smuffin 	/* not found */
308f13ac639Smuffin 	return (0);
309f13ac639Smuffin }
310f13ac639Smuffin 
311f13ac639Smuffin void
print_rev1_info(Msg_g_node * p)312f13ac639Smuffin print_rev1_info(Msg_g_node *p)
313f13ac639Smuffin {
314f13ac639Smuffin 	char	*base = (char *)p->msg_file_info;
315f13ac639Smuffin 	struct gnu_msg_info	*header = p->msg_file_info;
316f13ac639Smuffin 	struct gnu_msg_ent	*m;
317f13ac639Smuffin 	uint32_t	hv, hidx;
318f13ac639Smuffin 	char	*ms;
319f13ac639Smuffin 	enum gnu_msgidstr	v;
320f13ac639Smuffin 	int	x;
321f13ac639Smuffin 
322f13ac639Smuffin #ifdef	GETTEXT_DEBUG_DYMMSG
323f13ac639Smuffin 	gprintf(0, "******** dynamic msgid/msgstr\n");
324f13ac639Smuffin 	for (v = MSGID; v <= MSGSTR; v++) {
325f13ac639Smuffin 		for (x = 0; x < p->num_of_d_str; x++) {
326f13ac639Smuffin 			gprintf(0, "len: %u\n", p->d_msg[v][x].len);
327f13ac639Smuffin 			gprintf(0, "str: \"%s\"\n",
328f13ac639Smuffin 			    p->mchunk + p->d_msg[v][x].offset);
329f13ac639Smuffin 		}
330f13ac639Smuffin 	}
331f13ac639Smuffin #endif
332f13ac639Smuffin #ifdef	GETTEXT_DEBUG_HASHTBL
333f13ac639Smuffin 	gprintf(0, "******** dynamic hash table\n");
334f13ac639Smuffin 	for (x = 0; x < p->hash_size; x++) {
335f13ac639Smuffin 		gprintf(0, "%d: %u\n", x, p->hash_table[x]);
336f13ac639Smuffin 	}
337f13ac639Smuffin #endif
338f13ac639Smuffin #ifdef	GETTEXT_DEBUG_CHECK_STMSGID
339f13ac639Smuffin 	gprintf(0, "******** sanity check of static msgid\n");
340f13ac639Smuffin 	m = (struct gnu_msg_ent *)(uintptr_t)
341f13ac639Smuffin 	    (base + SWAP(p, header->off_msgid_tbl));
342f13ac639Smuffin 	for (x = 0; x < p->num_of_str; x++) {
343f13ac639Smuffin 		ms = base + SWAP(p, m[x].offset);
344f13ac639Smuffin 		gprintf(0, "\"%s\"\n", ms);
345f13ac639Smuffin 		hv = get_hashid(ms, NULL);
346f13ac639Smuffin 		hidx = search_msg(p, ms, hv, m);
347f13ac639Smuffin 		if (hidx == 0) {
348f13ac639Smuffin 			gprintf(0,
349f13ac639Smuffin 			    "failed to find this msg in the hash table\n");
350f13ac639Smuffin 		} else {
351f13ac639Smuffin 			if (hidx != x + 1) {
352f13ac639Smuffin 				gprintf(0, "hash table mismatch\n");
353f13ac639Smuffin 			}
354f13ac639Smuffin 		}
355f13ac639Smuffin 	}
356f13ac639Smuffin #endif
357f13ac639Smuffin #ifdef	GETTEXT_DEBUG_CHECK_DYMMSGID
358f13ac639Smuffin 	gprintf(0, "******* sanity check of dynamic msgid\n");
359f13ac639Smuffin 	m = (struct gnu_msg_ent *)(uintptr_t)
360f13ac639Smuffin 	    (base + SWAP(p, header->off_msgid_tbl));
361f13ac639Smuffin 	for (x = 0; x < p->num_of_d_str; x++) {
362f13ac639Smuffin 		ms = p->mchunk + p->d_msg[MSGID][x].offset;
363f13ac639Smuffin 		gprintf(0, "\"%s\"\n", ms);
364f13ac639Smuffin 		hv = get_hashid(ms, NULL);
365f13ac639Smuffin 		hidx = search_msg(p, ms, hv, m);
366f13ac639Smuffin 		if (hidx == 0) {
367f13ac639Smuffin 			gprintf(0,
368f13ac639Smuffin 			    "failed to find this msg in the hash table\n");
369f13ac639Smuffin 		} else {
370f13ac639Smuffin 			if (hidx != x + p->num_of_str + 1) {
371f13ac639Smuffin 				gprintf(0, "hash table mismatch\n");
372f13ac639Smuffin 			}
373f13ac639Smuffin 		}
374f13ac639Smuffin 	}
375f13ac639Smuffin #endif
376f13ac639Smuffin }
377f13ac639Smuffin 
3787c478bd9Sstevel@tonic-gate void
gprintf(int level,const char * format,...)3797c478bd9Sstevel@tonic-gate gprintf(int level, const char *format, ...)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 	va_list	ap;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	va_start(ap, format);
3847c478bd9Sstevel@tonic-gate 
385f13ac639Smuffin 	while (level-- > 0) {
3867c478bd9Sstevel@tonic-gate 		(void) fputs("   ", stdout);
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 	(void) vprintf(format, ap);
3897c478bd9Sstevel@tonic-gate 	va_end(ap);
390f13ac639Smuffin 
391f13ac639Smuffin 	(void) fflush(stdout);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate void
printlist(void)3957c478bd9Sstevel@tonic-gate printlist(void)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate 	struct domain_binding	*ppp;
3987c478bd9Sstevel@tonic-gate 	Gettext_t	*gt = global_gt;
3997c478bd9Sstevel@tonic-gate 
400f13ac639Smuffin 	gprintf(0, "=== Printing default list and regural list\n");
401f13ac639Smuffin 	gprintf(0, "   Default domain=<%s>, binding=<%s>\n",
4027c478bd9Sstevel@tonic-gate 	    DEFAULT_DOMAIN, defaultbind);
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	ppp = FIRSTBIND(gt);
4057c478bd9Sstevel@tonic-gate 	while (ppp) {
406f13ac639Smuffin 		gprintf(0, "   domain=<%s>, binding=<%s>, codeset=<%s>\n",
4077c478bd9Sstevel@tonic-gate 		    ppp->domain ? ppp->domain : "(null)",
408f13ac639Smuffin 		    ppp->binding ? ppp->binding : "(null)",
409f13ac639Smuffin 		    ppp->codeset ? ppp->codeset : "(null)");
4107c478bd9Sstevel@tonic-gate 		ppp = ppp->next;
4117c478bd9Sstevel@tonic-gate 	}
412f13ac639Smuffin 	(void) fflush(stdout);
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate void
printmp(struct msg_pack * mp,int level)4167c478bd9Sstevel@tonic-gate printmp(struct msg_pack *mp, int level)
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate 	gprintf(level, "=== mp ===\n");
4197c478bd9Sstevel@tonic-gate 	gprintf(level, "   msgid1: \"%s\"\n",
420f13ac639Smuffin 	    mp->msgid1 ? mp->msgid1 : "(null)");
4217c478bd9Sstevel@tonic-gate 	gprintf(level, "   msgid2: \"%s\"\n",
422f13ac639Smuffin 	    mp->msgid2 ? mp->msgid2 : "(null)");
423f13ac639Smuffin 	gprintf(level, "   msgfile: \"%s\"\n",
424f13ac639Smuffin 	    mp->msgfile ? mp->msgfile : "(null)");
4257c478bd9Sstevel@tonic-gate 	gprintf(level, "   domain: \"%s\"\n",
426f13ac639Smuffin 	    mp->domain ? mp->domain : "(null)");
4277c478bd9Sstevel@tonic-gate 	gprintf(level, "   binding: \"%s\"\n",
428f13ac639Smuffin 	    mp->binding ? mp->binding : "(null)");
4297c478bd9Sstevel@tonic-gate 	gprintf(level, "   locale: \"%s\"\n",
430f13ac639Smuffin 	    mp->locale ? mp->locale : "(null)");
4317c478bd9Sstevel@tonic-gate 	gprintf(level, "   language: \"%s\"\n",
432f13ac639Smuffin 	    mp->language ? mp->language : "(null)");
4337c478bd9Sstevel@tonic-gate 	gprintf(level, "   addr: 0x%p\n", mp->addr);
4347c478bd9Sstevel@tonic-gate 	gprintf(level, "   fsz: %d\n", mp->fsz);
435f13ac639Smuffin 	gprintf(level, "   hash_domain: %d\n", mp->hash_domain);
436f13ac639Smuffin 	gprintf(level, "   domain_len: %d\n", mp->domain_len);
437f13ac639Smuffin 	gprintf(level, "   n: %d\n", mp->n);
438f13ac639Smuffin 	gprintf(level, "   category: \"%s\"\n",
439f13ac639Smuffin 	    category_name[mp->category]);
440f13ac639Smuffin 	gprintf(level, "   plural: %d\n", mp->plural);
441f13ac639Smuffin 	gprintf(level, "   nlsp: %d\n", mp->nlsp);
4427c478bd9Sstevel@tonic-gate 	gprintf(level, "   trusted: %d\n", mp->trusted);
443f13ac639Smuffin 	gprintf(level, "   status: %d\n", mp->status);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate void
printsunmsg(Msg_s_node * smnp,int level)4477c478bd9Sstevel@tonic-gate printsunmsg(Msg_s_node *smnp, int level)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 	gprintf(level, "=== sunmsg ===\n");
4507c478bd9Sstevel@tonic-gate 	gprintf(level, "   msg_file_info: 0x%p\n",
451f13ac639Smuffin 	    (void *)smnp->msg_file_info);
4527c478bd9Sstevel@tonic-gate 	gprintf(level, "      msg_mid: %d\n",
453f13ac639Smuffin 	    smnp->msg_file_info->msg_mid);
4547c478bd9Sstevel@tonic-gate 	gprintf(level, "      msg_count: %d\n",
455f13ac639Smuffin 	    smnp->msg_file_info->msg_count);
4567c478bd9Sstevel@tonic-gate 	gprintf(level, "      str_count_msgid: %d\n",
457f13ac639Smuffin 	    smnp->msg_file_info->str_count_msgid);
4587c478bd9Sstevel@tonic-gate 	gprintf(level, "      str_count_msgstr: %d\n",
459f13ac639Smuffin 	    smnp->msg_file_info->str_count_msgstr);
4607c478bd9Sstevel@tonic-gate 	gprintf(level, "      msg_struct_size: %d\n",
461f13ac639Smuffin 	    smnp->msg_file_info->msg_struct_size);
4627c478bd9Sstevel@tonic-gate 	gprintf(level, "   msg_list: 0x%p\n",
463f13ac639Smuffin 	    (void *)smnp->msg_list);
4647c478bd9Sstevel@tonic-gate 	gprintf(level, "   msg_ids: 0x%p\n",
465f13ac639Smuffin 	    (void *)smnp->msg_ids);
4667c478bd9Sstevel@tonic-gate 	gprintf(level, "   msg_strs: 0x%p\n",
467f13ac639Smuffin 	    (void *)smnp->msg_strs);
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate void
printgnumsg(Msg_g_node * gmnp,int level)4717c478bd9Sstevel@tonic-gate printgnumsg(Msg_g_node *gmnp, int level)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate 	gprintf(level, "=== gnumsg ===\n");
474f13ac639Smuffin 	gprintf(level, "   msg_file_info: 0x%p\n", gmnp->msg_file_info);
4757c478bd9Sstevel@tonic-gate 	gprintf(level, "      magic: 0x%x\n",
476f13ac639Smuffin 	    gmnp->msg_file_info->magic);
4777c478bd9Sstevel@tonic-gate 	gprintf(level, "      revision: %d\n",
478f13ac639Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->revision));
4797c478bd9Sstevel@tonic-gate 	gprintf(level, "      num_of_str: %d\n",
480f13ac639Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->num_of_str));
4817c478bd9Sstevel@tonic-gate 	gprintf(level, "      off_msgid_tbl: %d\n",
482f13ac639Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->off_msgid_tbl));
4837c478bd9Sstevel@tonic-gate 	gprintf(level, "      off_msgstr_tbl: %d\n",
484f13ac639Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->off_msgstr_tbl));
4857c478bd9Sstevel@tonic-gate 	gprintf(level, "      sz_hashtbl: %d\n",
486f13ac639Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->sz_hashtbl));
4877c478bd9Sstevel@tonic-gate 	gprintf(level, "      off_hashtbl: %d\n",
488f13ac639Smuffin 	    SWAP(gmnp, gmnp->msg_file_info->off_hashtbl));
489f13ac639Smuffin 	if (gmnp->flag & ST_REV1) {
490f13ac639Smuffin 		struct gnu_msg_rev1_info	*a =
491f13ac639Smuffin 		    (struct gnu_msg_rev1_info *)(uintptr_t)
492f13ac639Smuffin 		    ((char *)gmnp->msg_file_info +
493f13ac639Smuffin 		    sizeof (struct gnu_msg_info));
494f13ac639Smuffin 		gprintf(level, "      num_of_dynamic_macro: %d\n",
495f13ac639Smuffin 		    SWAP(gmnp, a->num_of_dynamic_macro));
496f13ac639Smuffin 		gprintf(level, "      off_dynamic_macro: %d\n",
497f13ac639Smuffin 		    SWAP(gmnp, a->off_dynamic_macro));
498f13ac639Smuffin 		gprintf(level, "      num_of_dynamic_str: %d\n",
499f13ac639Smuffin 		    SWAP(gmnp, a->num_of_dynamic_str));
500f13ac639Smuffin 		gprintf(level, "      off_dynamic_msgid_tbl: %d\n",
501f13ac639Smuffin 		    SWAP(gmnp, a->off_dynamic_msgid_tbl));
502f13ac639Smuffin 		gprintf(level, "      off_dynamic_msgstr_tbl: %d\n",
503f13ac639Smuffin 		    SWAP(gmnp, a->off_dynamic_msgstr_tbl));
504f13ac639Smuffin 	}
505f13ac639Smuffin 	gprintf(level, "   fsize: %lu\n", gmnp->fsize);
506f13ac639Smuffin 	gprintf(level, "   flag: %08x\n", gmnp->flag);
507f13ac639Smuffin 	gprintf(level, "   num_of_str: %u\n", gmnp->num_of_str);
508f13ac639Smuffin 	gprintf(level, "   num_of_d_str: %u\n", gmnp->num_of_d_str);
509f13ac639Smuffin 	gprintf(level, "   hash_size: %u\n", gmnp->hash_size);
510f13ac639Smuffin 	gprintf(level, "   hash_table: 0x%p\n", (void *)gmnp->hash_table);
511f13ac639Smuffin 	gprintf(level, "   d_msgid: 0x%p\n", (void *)gmnp->d_msg[MSGID]);
512f13ac639Smuffin 	gprintf(level, "   d_msgstr: 0x%p\n", (void *)gmnp->d_msg[MSGSTR]);
513f13ac639Smuffin 	gprintf(level, "   mchunk: 0x%p\n", (void *)gmnp->mchunk);
514f13ac639Smuffin 
5157c478bd9Sstevel@tonic-gate 	gprintf(level, "   src_encoding: \"%s\"\n",
516f13ac639Smuffin 	    gmnp->src_encoding ? gmnp->src_encoding : "(null)");
5177c478bd9Sstevel@tonic-gate 	gprintf(level, "   dst_encoding: \"%s\"\n",
518f13ac639Smuffin 	    gmnp->dst_encoding ? gmnp->dst_encoding : "(null)");
5197c478bd9Sstevel@tonic-gate 	gprintf(level, "   nplurals: %d\n",
520f13ac639Smuffin 	    gmnp->nplurals);
5217c478bd9Sstevel@tonic-gate 	gprintf(level, "   plural: 0x%p\n",
522f13ac639Smuffin 	    (void *)gmnp->plural);
5237c478bd9Sstevel@tonic-gate 	if (gmnp->plural)
5247c478bd9Sstevel@tonic-gate 		printexpr(gmnp->plural, level+1);
5257c478bd9Sstevel@tonic-gate 	gprintf(level, "   fd: 0x%p\n", (void *)gmnp->fd);
5267c478bd9Sstevel@tonic-gate 	gprintf(level, "   conv_msgstr: 0x%p\n",
527f13ac639Smuffin 	    (void *)gmnp->conv_msgstr);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate void
printexpr(struct expr * e,int level)5317c478bd9Sstevel@tonic-gate printexpr(struct expr *e, int level)
5327c478bd9Sstevel@tonic-gate {
5337c478bd9Sstevel@tonic-gate 	static const char	*op_name[] = {
534f13ac639Smuffin 	    "NULL", "INIT", "EXP",
535f13ac639Smuffin 	    "NUM", "VAR", "?", ":", "||",
536f13ac639Smuffin 	    "&&", "==", "!=", ">", "<",
537f13ac639Smuffin 	    ">=", "<=", "+", "-", "*", "/",
538f13ac639Smuffin 	    "%", "!", "(", ")", "ERR"
5397c478bd9Sstevel@tonic-gate 	};
5407c478bd9Sstevel@tonic-gate 	switch (GETOPNUM(e->op)) {
5417c478bd9Sstevel@tonic-gate 	case 0:
5427c478bd9Sstevel@tonic-gate 		switch (GETTYPE(e->op)) {
5437c478bd9Sstevel@tonic-gate 		case T_NUM:
5447c478bd9Sstevel@tonic-gate 			gprintf(level, "NUM(%d)\n", e->num);
5457c478bd9Sstevel@tonic-gate 			break;
5467c478bd9Sstevel@tonic-gate 		case T_VAR:
5477c478bd9Sstevel@tonic-gate 			gprintf(level, "VAR(n)\n");
5487c478bd9Sstevel@tonic-gate 			break;
5497c478bd9Sstevel@tonic-gate 		}
5507c478bd9Sstevel@tonic-gate 		break;
5517c478bd9Sstevel@tonic-gate 	case 1:
5527c478bd9Sstevel@tonic-gate 		gprintf(level, "OP: !\n");
5537c478bd9Sstevel@tonic-gate 		printexpr(e->nodes[0], level+1);
5547c478bd9Sstevel@tonic-gate 		break;
5557c478bd9Sstevel@tonic-gate 	case 2:
5567c478bd9Sstevel@tonic-gate 		gprintf(level, "OP: %s\n", op_name[GETTYPE(e->op)]);
5577c478bd9Sstevel@tonic-gate 		printexpr(e->nodes[0], level+1);
5587c478bd9Sstevel@tonic-gate 		printexpr(e->nodes[1], level+1);
5597c478bd9Sstevel@tonic-gate 		break;
5607c478bd9Sstevel@tonic-gate 	case 3:
5617c478bd9Sstevel@tonic-gate 		gprintf(level, "OP: ?\n");
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 		printexpr(e->nodes[0], level+1);
5647c478bd9Sstevel@tonic-gate 		printexpr(e->nodes[1], level+1);
5657c478bd9Sstevel@tonic-gate 		printexpr(e->nodes[2], level+1);
5667c478bd9Sstevel@tonic-gate 		break;
5677c478bd9Sstevel@tonic-gate 	}
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate void
printmnp(Msg_node * mnp,int level)5727c478bd9Sstevel@tonic-gate printmnp(Msg_node *mnp, int level)
5737c478bd9Sstevel@tonic-gate {
5747c478bd9Sstevel@tonic-gate 	gprintf(level, "=== mnp ===\n");
5757c478bd9Sstevel@tonic-gate 
576f13ac639Smuffin 	gprintf(level, "   hashid: %d\n", mnp->hashid);
5777c478bd9Sstevel@tonic-gate 	gprintf(level, "   type: \"%s\"\n",
578f13ac639Smuffin 	    mnp->type == T_ILL_MO ? "T_ILL_MO" :
579f13ac639Smuffin 	    mnp->type == T_SUN_MO ? "T_SUN_MO" :
580f13ac639Smuffin 	    mnp->type == T_GNU_MO ? "T_GNU_MO" :
581f13ac639Smuffin 	    "UNKNOWN TYPE");
5827c478bd9Sstevel@tonic-gate 	gprintf(level, "   path: \"%s\"\n",
583f13ac639Smuffin 	    mnp->path ? mnp->path : "(null)");
5847c478bd9Sstevel@tonic-gate 	gprintf(level, "   msg_file_trusted: %d\n",
585f13ac639Smuffin 	    mnp->trusted);
5867c478bd9Sstevel@tonic-gate 	if (mnp->type == T_SUN_MO)
5877c478bd9Sstevel@tonic-gate 		printsunmsg(mnp->msg.sunmsg, level+1);
5887c478bd9Sstevel@tonic-gate 	else if (mnp->type == T_GNU_MO)
5897c478bd9Sstevel@tonic-gate 		printgnumsg(mnp->msg.gnumsg, level+1);
5907c478bd9Sstevel@tonic-gate 	gprintf(level, "   next: 0x%p\n", (void *)mnp->next);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate void
printnls(Nls_node * n,int level)594f13ac639Smuffin printnls(Nls_node *n, int level)
5957c478bd9Sstevel@tonic-gate {
596f13ac639Smuffin 	gprintf(level, "=== nls ===\n");
597f13ac639Smuffin 	gprintf(level, "   domain: \"%s\"\n", n->domain ? n->domain : "NULL");
598f13ac639Smuffin 	gprintf(level, "   locale: \"%s\"\n", n->locale ? n->locale : "NULL");
599f13ac639Smuffin 	gprintf(level, "   nlspath: \"%s\"\n", n->nlspath ? n->nlspath :
600f13ac639Smuffin 	    "NULL");
601f13ac639Smuffin 	gprintf(level, "   next: 0x%p\n", n->next);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate void
printdbind(Dbinding * d,int level)605f13ac639Smuffin printdbind(Dbinding *d, int level)
6067c478bd9Sstevel@tonic-gate {
607f13ac639Smuffin 	gprintf(level, "=== dbind ===\n");
608f13ac639Smuffin 	gprintf(level, "   domain: \"%s\"\n", d->domain ? d->domain : "NULL");
609f13ac639Smuffin 	gprintf(level, "   binding: \"%s\"\n", d->binding ? d->binding :
610f13ac639Smuffin 	    "NULL");
611f13ac639Smuffin 	gprintf(level, "   codeset: \"%s\"\n", d->codeset ? d->codeset :
612f13ac639Smuffin 	    "NULL");
613f13ac639Smuffin 	gprintf(level, "   next: 0x%p\n", d->next);
6147c478bd9Sstevel@tonic-gate }
615f13ac639Smuffin 
616f13ac639Smuffin void
printgt(Gettext_t * gt,int level)617f13ac639Smuffin printgt(Gettext_t *gt, int level)
618f13ac639Smuffin {
619f13ac639Smuffin 	gprintf(level, "=== gt ===\n");
620f13ac639Smuffin 	gprintf(level, "   cur_domain: \"%s\"\n", gt->cur_domain);
621f13ac639Smuffin 	if (gt->dbind) {
622f13ac639Smuffin 		printdbind(gt->dbind, level+1);
623f13ac639Smuffin 	} else {
624f13ac639Smuffin 		gprintf(level, "   dbind: NULL\n");
625f13ac639Smuffin 	}
626f13ac639Smuffin 	if (gt->m_node) {
627f13ac639Smuffin 		printmnp(gt->m_node, level + 1);
628f13ac639Smuffin 	} else {
629f13ac639Smuffin 		gprintf(level, "   m_node: NULL\n");
630f13ac639Smuffin 	}
631f13ac639Smuffin 	if (gt->n_node) {
632f13ac639Smuffin 		printnls(gt->n_node, level + 1);
633f13ac639Smuffin 	} else {
634f13ac639Smuffin 		gprintf(level, "   n_node: NULL\n");
635f13ac639Smuffin 	}
636f13ac639Smuffin 	if (gt->c_m_node) {
637f13ac639Smuffin 		printmnp(gt->c_m_node, level + 1);
638f13ac639Smuffin 	} else {
639f13ac639Smuffin 		gprintf(level, "   c_m_node: NULL\n");
640f13ac639Smuffin 	}
641f13ac639Smuffin 	if (gt->c_n_node) {
642f13ac639Smuffin 		printnls(gt->c_n_node, level + 1);
643f13ac639Smuffin 	} else {
644f13ac639Smuffin 		gprintf(level, "   c_n_node: NULL\n");
645f13ac639Smuffin 	}
646f13ac639Smuffin }
647f13ac639Smuffin 
6487c478bd9Sstevel@tonic-gate #endif
649