summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc
diff options
context:
space:
mode:
authormuffin <none@none>2008-06-03 15:49:37 -0700
committermuffin <none@none>2008-06-03 15:49:37 -0700
commitf13ac6397da869bb7b7bc8a9f0b2e8fff530c346 (patch)
tree52cfac8e709209385b4c2165a48baa129a9862dc /usr/src/lib/libc
parent44f31f1309f988eeccdb6879c1945d72a2b14258 (diff)
downloadillumos-gate-f13ac6397da869bb7b7bc8a9f0b2e8fff530c346.tar.gz
PSARC/2007/634 More compatibility with GNU gettext in gettext(3c)
6570425 gettext(3c) should support GNU gettext mo format version 1.0
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r--usr/src/lib/libc/inc/msgfmt.h281
-rw-r--r--usr/src/lib/libc/port/i18n/gettext.h145
-rw-r--r--usr/src/lib/libc/port/i18n/gettext_gnu.c1132
-rw-r--r--usr/src/lib/libc/port/i18n/gettext_real.c679
-rw-r--r--usr/src/lib/libc/port/i18n/gettext_util.c804
-rw-r--r--usr/src/lib/libc/port/mapfile-vers3
6 files changed, 1719 insertions, 1325 deletions
diff --git a/usr/src/lib/libc/inc/msgfmt.h b/usr/src/lib/libc/inc/msgfmt.h
index 4792884879..7618e05eac 100644
--- a/usr/src/lib/libc/inc/msgfmt.h
+++ b/usr/src/lib/libc/inc/msgfmt.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 1998, 2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#ifndef _MSGFMT_H
@@ -29,6 +28,9 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <stdint.h>
+#include <stddef.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -120,46 +122,49 @@ struct msg_struct {
/*
*
* +-----------------------------------------+
- * 0 | (unsigned int) magic number |
+ * 0 | (uint32_t) magic number |
* +-----------------------------------------+
- * 4 | (unsigned int) format revision |
+ * 4 | (uint32_t) format revision |
* +-----------------------------------------+
- * 8 | (unsigned int) number of strings | == N
+ * 8 | (uint32_t) number of strings | == N
* +-----------------------------------------+
- * 12 | (unsigned int) offset of msgid table | == O
+ * 12 | (uint32_t) offset of msgid table | == O
* +-----------------------------------------+
- * 16 | (unsigned int) offset of msgstr table | == T
+ * 16 | (uint32_t) offset of msgstr table | == T
* +-----------------------------------------+
- * 20 | (unsigned int) size of hashing table | == S
+ * 20 | (uint32_t) size of hashing table | == S
* +-----------------------------------------+
- * 24 | (unsigned int) offset of hashing table | == H
+ * 24 | (uint32_t) offset of hashing table | == H
* +-----------------------------------------+
* +-----------------------------------------+
- * O | (unsigned int) length of 0th msgid |
+ * O | (uint32_t) length of 0th msgid |
* +-----------------------------------------+
- * O+4 | (unsigned int) offset of 0th msgid | == M(0)
+ * O+4 | (uint32_t) offset of 0th msgid | == M(0)
* +-----------------------------------------+
* ...............................
* +-----------------------------------------+
- * O+((N-1)*8) | (unsigned int) length of (N-1)th msgid |
+ * O+((N-1)*8) | (uint32_t) length of (N-1)th msgid |
* +-----------------------------------------+
- * O+((N-1)*8) | (unsigned int) offset of (N-1)th msgid | == M(N-1)
+ * O+((N-1)*8) | (uint32_t) offset of (N-1)th msgid | == M(N-1)
* +4 +-----------------------------------------+
- * T | (unsigned int) length of 0th msgstr |
* +-----------------------------------------+
- * T+4 | (unsigned int) offset of 0th msgstr | == Q(0)
+ * T | (uint32_t) length of 0th msgstr |
+ * +-----------------------------------------+
+ * T+4 | (uint32_t) offset of 0th msgstr | == Q(0)
* +-----------------------------------------+
* ...............................
* +-----------------------------------------+
- * T+((N-1)*8) | (unsigned int) length of (N-1)th msgstr |
+ * T+((N-1)*8) | (uint32_t) length of (N-1)th msgstr |
* +-----------------------------------------+
- * T+((N-1)*8) | (unsigned int) offset of (N-1)th msgstr | == Q(N-1)
+ * T+((N-1)*8) | (uint32_t) offset of (N-1)th msgstr | == Q(N-1)
* +4 +-----------------------------------------+
- * H | (unsigned int) start hashing table |
+ * +-----------------------------------------+
+ * H | (uint32_t) start hashing table |
* +-----------------------------------------+
* ...............................
* +-----------------------------------------+
- * H + S * 4 | (unsigned int) end hashing table |
+ * H + S * 4 | (uint32_t) end hashing table |
+ * +-----------------------------------------+
* +-----------------------------------------+
* M(0) | NULL terminated 0th msgid string |
* +-----------------------------------------+
@@ -169,6 +174,7 @@ struct msg_struct {
* +-----------------------------------------+
* M(N-1) | NULL terminated (N-1)th msgid string |
* +-----------------------------------------+
+ * +-----------------------------------------+
* Q(0) | NULL terminated 0th msgstr string |
* +-----------------------------------------+
* Q(1) | NULL terminated 1st msgstr string |
@@ -179,24 +185,229 @@ struct msg_struct {
* +-----------------------------------------+
*/
-#define GNU_MAGIC 0x950412de
-#define GNU_MAGIC_SWAPPED 0xde120495
-#define GNU_REVISION 0
-#define GNU_REVISION_SWAPPED 0
+/*
+ * GNU MO file format (Revision 1)
+ */
+/*
+ *
+ * +-----------------------------------------------+
+ * 0 | (uint32_t) magic number |
+ * +-----------------------------------------------+
+ * 4 | (uint32_t) format revision |
+ * +-----------------------------------------------+
+ * 8 | (uint32_t) number of strings | == N
+ * +-----------------------------------------------+
+ * 12 | (uint32_t) offset of msgid table | == O
+ * +-----------------------------------------------+
+ * 16 | (uint32_t) offset of msgstr table | == T
+ * +-----------------------------------------------+
+ * 20 | (uint32_t) size of hashing table | == S
+ * +-----------------------------------------------+
+ * 24 | (uint32_t) offset of hashing table | == H
+ * +-----------------------------------------------+
+ * 32 | (uint32_t) number of dynamic macros | == M
+ * +-----------------------------------------------+
+ * 36 | (uint32_t) offset of dynamic macros | == P
+ * +-----------------------------------------------+
+ * 40 | (uint32_t) number of dynamic strings | == D
+ * +-----------------------------------------------+
+ * 44 | (uint32_t) offset of dynamic msgid tbl | == A
+ * +-----------------------------------------------+
+ * 48 | (uint32_t) offset of dynamic msgstr tbl | == B
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * O | (uint32_t) length of 0th msgid |
+ * +-----------------------------------------------+
+ * O+4 | (uint32_t) offset of 0th msgid | == M(0)
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * O+((N-1)*8) | (uint32_t) length of (N-1)th msgid |
+ * +-----------------------------------------------+
+ * O+((N-1)*8) | (uint32_t) offset of (N-1)th msgid | == M(N-1)
+ * +4 +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * T | (uint32_t) length of 0th msgstr |
+ * +-----------------------------------------------+
+ * T+4 | (uint32_t) offset of 0th msgstr | == Q(0)
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * T+((N-1)*8) | (uint32_t) length of (N-1)th msgstr |
+ * +-----------------------------------------------+
+ * T+((N-1)*8) | (uint32_t) offset of (N-1)th msgstr | == Q(N-1)
+ * +4 +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * H | (uint32_t) start hashing table |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * H + S * 4 | (uint32_t) end hashing table |
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * P | (uint32_t) length of 0th macro |
+ * +-----------------------------------------------+
+ * P+4 | (uint32_t) offset of 0th macro | == C(0)
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * P+((M-1)*8) | (uint32_t) length of (M-1)th macro |
+ * +-----------------------------------------------+
+ * P+((M-1)*8) | (uint32_t) offset of (M-1)th macro | == C(M-1)
+ * +4 +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * A | (uint32_t) offset of 0th d_msgid | == L(0)
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * A+((D-1)*4) | (uint32_t) offset of (D-1)th d_msgid | == L(D-1)
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * B | (uint32_t) offset of 0th d_msgstr | == E(0)
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * B+((D-1)*4) | (uint32_t) offset of (D-1)th d_msgstr | == E(D-1)
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * L(0) | (uint32_t) offset of 0th d_msgid message | == F(0)
+ * +-----------------------------------------------+
+ * L(0)+4 | (uint32_t) length of 0th fixed substring |
+ * +-----------------------------------------------+
+ * L(0)+8 | (uint32_t) index to a dynamic macro |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * L(0)+4+ | (uint32_t) length of (m-1)th fixed substring |
+ * ((m-1)*8) +-----------------------------------------------+
+ * L(0)+8+ | (uint32_t) NOMORE_DYNAMIC_STR |
+ * ((m-1)*8) +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * L(D-1) | (uint32_t) offset of 0th d_msgid message | == F(D-1)
+ * +-----------------------------------------------+
+ * L(D-1)+4 | (uint32_t) length of 0th fixed substring |
+ * +-----------------------------------------------+
+ * L(D-1)+8 | (uint32_t) index to a dynamic macro |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * L(D-1)+4 | (uint32_t) length of (m-1)th fixed substring |
+ * ((m-1)*8) +-----------------------------------------------+
+ * L(D-1)+8 | (uint32_t) NOMORE_DYNAMIC_STR |
+ * ((m-1)*8) +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * E(0) | (uint32_t) offset of 0th d_msgstr message | == G(0)
+ * +-----------------------------------------------+
+ * E(0)+4 | (uint32_t) length of 0th fixed substring |
+ * +-----------------------------------------------+
+ * E(0)+8 | (uint32_t) index to a dynamic macro |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * E(0)+4+ | (uint32_t) length of (m-1)th fixed substring |
+ * ((m-1)*8) +-----------------------------------------------+
+ * E(0)+8+ | (uint32_t) NOMORE_DYNAMIC_STR |
+ * ((m-1)*8) +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * E(D-1) | (uint32_t) offset of 0th d_msgstr message | == G(D-1)
+ * +-----------------------------------------------+
+ * E(D-1)+4 | (uint32_t) length of 0th fixed substring |
+ * +-----------------------------------------------+
+ * E(D-1)+8 | (uint32_t) index to a dynamic macro |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * E(D-1)+4 | (uint32_t) length of (m-1)th fixed substring |
+ * ((m-1)*8) +-----------------------------------------------+
+ * E(D-1)+8 | (uint32_t) NOMORE_DYNAMIC_STR |
+ * ((m-1)*8) +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * M(0) | NULL terminated 0th msgid string |
+ * +-----------------------------------------------+
+ * M(1) | NULL terminated 1st msgid string |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * M(N-1) | NULL terminated (N-1)th msgid string |
+ * +-----------------------------------------------+
+ * Q(0) | NULL terminated 0th msgstr string |
+ * +-----------------------------------------------+
+ * Q(1) | NULL terminated 1st msgstr string |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * Q(N-1) | NULL terminated (N-1)th msgstr string |
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * C(0) | NULL terminated 0th macro |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * C(M-1) | NULL terminated (M-1)th macro |
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * F(0) | NULL terminated 0th dynamic msgid string |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * F(D-1) | NULL terminated (D-1)th dynamic msgid string |
+ * +-----------------------------------------------+
+ * +-----------------------------------------------+
+ * G(0) | NULL terminated 0th dynamic msgstr string |
+ * +-----------------------------------------------+
+ * ...............................
+ * +-----------------------------------------------+
+ * G(D-1) | NULL terminated (D-1)th dynamic msgstr string |
+ * +-----------------------------------------------+
+ */
+
+#define GNU_MAGIC 0x950412de
+#define GNU_MAGIC_SWAPPED 0xde120495
+#define GNU_REVISION 0
+#define GNU_REVISION_0_0 0
+#define GNU_REVISION_0_0_SWAPPED 0
+#define GNU_REVISION_0_1 0x00000001
+#define GNU_REVISION_0_1_SWAPPED 0x01000000
+#define GNU_REVISION_1_1 0x00010001
+#define GNU_REVISION_1_1_SWAPPED 0x01000100
+#define NOMORE_DYNAMIC_MACRO 0xffffffff
+
+enum gnu_msgidstr {
+ MSGID = 0,
+ MSGSTR = 1
+};
struct gnu_msg_info {
- unsigned int magic;
- unsigned int revision;
- unsigned int num_of_str;
- unsigned int off_msgid_tbl;
- unsigned int off_msgstr_tbl;
- unsigned int sz_hashtbl;
- unsigned int off_hashtbl;
+ uint32_t magic;
+ uint32_t revision;
+ uint32_t num_of_str;
+ uint32_t off_msgid_tbl;
+ uint32_t off_msgstr_tbl;
+ uint32_t sz_hashtbl;
+ uint32_t off_hashtbl;
+};
+
+struct gnu_msg_rev1_info {
+ uint32_t num_of_dynamic_macro;
+ uint32_t off_dynamic_macro;
+ uint32_t num_of_dynamic_str;
+ uint32_t off_dynamic_msgid_tbl;
+ uint32_t off_dynamic_msgstr_tbl;
};
struct gnu_msg_ent {
- unsigned int len;
- unsigned int offset;
+ uint32_t len;
+ uint32_t offset;
+};
+
+struct gnu_dynamic_ent {
+ uint32_t len;
+ uint32_t idx;
+};
+
+struct gnu_dynamic_tbl {
+ uint32_t offset;
+ struct gnu_dynamic_ent entry[1];
};
#ifdef __cplusplus
diff --git a/usr/src/lib/libc/port/i18n/gettext.h b/usr/src/lib/libc/port/i18n/gettext.h
index 181b007ad9..bbfdf66ade 100644
--- a/usr/src/lib/libc/port/i18n/gettext.h
+++ b/usr/src/lib/libc/port/i18n/gettext.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,10 +38,14 @@ extern "C" {
#endif
/* Type of MO file */
-#define T_SUN_MO 0x1
-#define T_GNU_MO 0x2
-#define T_GNU_SWAPPED_MO 0x4
-#define T_ILL_MO 0x8
+#define T_MO_MASK 0x07
+#define T_SUN_MO 0x01
+#define T_GNU_MO 0x02
+#define T_ILL_MO 0x04
+
+#define T_GNU_MASK 0x300
+#define T_GNU_SWAPPED 0x100
+#define T_GNU_REV1 0x200
#define TP_BINDING 0
#define TP_CODESET 1
@@ -49,6 +53,15 @@ extern "C" {
/* Msg_g_node->flag */
#define ST_CHK 0x1 /* header has been checked? */
#define ST_SWP 0x2 /* reversed endian? */
+#define ST_REV1 0x4 /* Revision 1 */
+
+/*
+ * msg_pack->status:
+ * interaction between handle_lang() and handle_mo()
+ */
+#define ST_GNU_MSG_FOUND 0x1 /* valid msg found in GNU MO */
+#define ST_GNU_MO_FOUND 0x2 /* GNU MO found */
+#define ST_SUN_MO_FOUND 0x4 /* Sun MO found */
typedef struct domain_binding {
char *domain; /* domain name */
@@ -63,6 +76,7 @@ typedef struct domain_binding {
*/
typedef struct nlstmp {
char pathname[MAXPATHLEN]; /* the full pathname to file */
+ size_t len; /* length of pathname */
struct nlstmp *next; /* link to the next entry */
} Nlstmp;
@@ -76,21 +90,35 @@ typedef struct {
typedef struct expr *plural_expr_t;
typedef struct {
- struct gnu_msg_info *msg_file_info; /* information of msg file */
- unsigned int *hash_table; /* hash table */
+ unsigned int len; /* length of the expanded str of macro */
+ const char *ptr; /* pointer to the expanded str of macro */
+} gnu_d_macro_t;
+
+typedef struct {
+ struct gnu_msg_info *msg_file_info;
+ struct gnu_msg_rev1_info *rev1_header;
+ size_t fsize; /* size of the GNU mo file */
+ uint32_t flag; /* status */
+ uint32_t num_of_str; /* number of static msgs */
+ uint32_t num_of_d_str; /* number of dynamic msgs */
+ uint32_t hash_size; /* hash table size */
+ uint32_t *hash_table; /* hash table */
+ struct gnu_msg_ent *msg_tbl[2]; /* msgid/str entries */
+ struct gnu_msg_ent *d_msg[2]; /* dynamic msgid/str entries */
+ char *mchunk; /* pointer to memory chunk of dynamic strs */
char *src_encoding; /* src encoding */
char *dst_encoding; /* dst encoding */
- int flag; /* status */
- int nplurals; /* number of plural forms */
- plural_expr_t plural; /* plural expression */
- iconv_t fd; /* iconv descriptor */
- char **conv_msgstr; /* code-converted msgstr */
+ unsigned int nplurals; /* number of plural forms */
+ plural_expr_t plural; /* plural expression */
+ iconv_t fd; /* iconv descriptor */
+ uint32_t **conv_msgstr; /* code-converted msgstr */
} Msg_g_node;
typedef struct msg_node {
- int type; /* T_SUN_MO, T_GNU_MO, or T_ILL_MO */
- int trusted; /* is this a trusted source? */
- char *path; /* name of message catalog */
+ uint32_t hashid; /* hashed value of the domain name */
+ uint16_t type; /* T_SUN_MO, T_GNU_MO, or T_ILL_MO */
+ uint16_t trusted; /* is this a trusted source? */
+ char *path; /* name of message catalog */
union {
Msg_s_node *sunmsg;
Msg_g_node *gnumsg;
@@ -106,20 +134,11 @@ typedef struct nls_node {
struct nls_node *next; /* link to the next */
} Nls_node;
-typedef struct cache_node {
- unsigned int hashid; /* hashed valued for the locale name */
- Msg_node *m_node; /* link to Msg_node */
- Msg_node *m_last; /* link to the last Msg_node */
- Nls_node *n_node; /* link to Nls_node */
- Nls_node *n_last; /* link to the last Nls_node */
- struct cache_node *next; /* link to the next */
-} Cache_node;
-
typedef struct {
char *cur_domain; /* current domain */
Dbinding *dbind; /* domain binding */
- Cache_node *c_node; /* link to the cache node */
- Cache_node *c_last; /* link to the last cache node */
+ Msg_node *m_node; /* link to the Msg_node cache */
+ Nls_node *n_node; /* link to the Nls_node cache */
Msg_node *c_m_node; /* link to the current Msg_node */
Nls_node *c_n_node; /* link to the current Nls_node */
} Gettext_t;
@@ -134,27 +153,17 @@ struct msg_pack {
char *language; /* LANGUAGE env */
caddr_t addr; /* mmap'ed address */
size_t fsz; /* file size */
- size_t msgfile_len; /* length of msgfile */
- size_t domain_len; /* length of domain */
- size_t locale_len; /* length of locale */
-
+ uint32_t hash_domain; /* hash ID of domain */
+ uint32_t domain_len; /* length of domain */
unsigned int n; /* n argument */
- int category; /* category argument */
- int plural; /* plural or not */
- unsigned int hash_locale; /* hash ID of locale */
- int nlsp; /* nlsp */
- int trusted; /* trusted msg catalog or not */
-};
-
-struct cache_pack {
- int cacheline;
- Msg_node *mnp;
- Cache_node *cnp;
- Cache_node *node_hash;
+ int category; /* category argument */
+ int plural; /* plural or not */
+ int nlsp; /* nlsp */
+ int trusted; /* trusted msg catalog or not */
+ int status; /* status */
};
#define DEFAULT_DOMAIN "messages"
-#define DEFAULT_DOMAIN_LEN (sizeof (DEFAULT_DOMAIN) - 1)
#define DEFAULT_BINDING _DFLT_LOC_PATH
#define MSGFILESUFFIX ".mo"
#define MSGFILESUFFIXLEN (sizeof (MSGFILESUFFIX) - 1)
@@ -167,47 +176,49 @@ struct cache_pack {
((n == 1) ? (char *)msgid1 : (char *)msgid2) : \
(char *)msgid1)
+#define ROUND(m, s) if ((m) % (s)) (m) += ((s) - ((m) % (s)))
+
#define SWAP(p, ui32) \
(((p)->flag & ST_SWP) ? doswap32(ui32) : (ui32))
+#define HASH_TBL(p, ui32) \
+ ((((p)->flag & (ST_REV1|ST_SWP)) == ST_SWP) ? \
+ doswap32(ui32) : (ui32))
+
extern const char *defaultbind;
extern const char default_domain[];
extern Gettext_t *global_gt;
-extern char *_textdomain_u(const char *, char *);
-extern char *_real_bindtextdomain_u(const char *, const char *, int);
-extern char *_real_gettext_u(const char *, const char *,
- const char *, unsigned long int, int, int);
-
-extern int setmsg(Msg_node *, char *, size_t);
-extern char *handle_lang(struct cache_pack *, struct msg_pack *);
-extern char *mk_msgfile(struct msg_pack *);
-extern int check_cache(struct cache_pack *, struct msg_pack *);
-extern void connect_entry(struct cache_pack *);
-extern int connect_invalid_entry(struct cache_pack *, struct msg_pack *);
-extern Msg_node *create_mnp(struct msg_pack *);
-extern Cache_node *create_cnp(Msg_node *, struct msg_pack *);
-extern void free_mnp_mp(Msg_node *, struct msg_pack *);
-extern unsigned int get_hashid(const char *, size_t *);
-extern unsigned int doswap32(unsigned int);
+extern char *_textdomain_u(const char *, char *);
+extern char *_real_bindtextdomain_u(const char *, const char *, int);
+extern char *_real_gettext_u(const char *, const char *,
+ const char *, unsigned long int, int, int);
+extern char *handle_mo(struct msg_pack *);
+
+extern int gnu_setmsg(Msg_node *, char *, size_t);
+extern char *handle_lang(struct msg_pack *);
+extern char *mk_msgfile(struct msg_pack *);
+extern Msg_node *check_cache(struct msg_pack *);
+extern uint32_t get_hashid(const char *, uint32_t *);
+extern uint32_t doswap32(uint32_t);
extern int plural_expr(plural_expr_t *, const char *);
extern unsigned int plural_eval(plural_expr_t, unsigned int);
-extern char *gnu_key_2_text(Msg_g_node *, const char *,
- struct msg_pack *);
+extern char *gnu_key_2_text(Msg_g_node *, const char *, struct msg_pack *);
-extern char *get_codeset(const char *);
+extern char *get_codeset(const char *);
#ifdef GETTEXT_DEBUG
+extern void gprintf(int, const char *, ...);
+extern void printgt(Gettext_t *, int);
extern void printmp(struct msg_pack *, int);
extern void printsunmsg(Msg_s_node *, int);
extern void printgnumsg(Msg_g_node *, int);
extern void printexpr(plural_expr_t, int);
extern void printmnp(Msg_node *, int);
-extern void printcnp(Cache_node *, int);
-extern void printcp(struct cache_pack *, int);
extern void printlist(void);
+extern void print_rev1_info(Msg_g_node *);
#endif
#ifdef __cplusplus
diff --git a/usr/src/lib/libc/port/i18n/gettext_gnu.c b/usr/src/lib/libc/port/i18n/gettext_gnu.c
index b4a2424068..89be4bdd25 100644
--- a/usr/src/lib/libc/port/i18n/gettext_gnu.c
+++ b/usr/src/lib/libc/port/i18n/gettext_gnu.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,6 +41,7 @@
#include <unistd.h>
#include <limits.h>
#include <errno.h>
+#include <inttypes.h>
#include "libc.h"
#include "msgfmt.h"
#include "nlspath_checks.h"
@@ -50,6 +51,10 @@
#include <assert.h>
#endif
+/* The following symbols are just for GNU binary compatibility */
+int _nl_msg_cat_cntr;
+int *_nl_domain_bindings;
+
static const char *nullstr = "";
#define CHARSET_MOD "charset="
@@ -59,32 +64,39 @@ static const char *nullstr = "";
#define PLURAL_MOD "plural="
#define PLURAL_LEN (sizeof (PLURAL_MOD) - 1)
+static uint32_t get_hash_index(uint32_t *, uint32_t, uint32_t);
+
/*
* free_conv_msgstr
*
* release the memory allocated for storing code-converted messages
+ *
+ * f
+ * 0: do not free gmnp->conv_msgstr
+ * 1: free gmnp->conv_msgstr
*/
static void
-free_conv_msgstr(Msg_g_node *gmnp)
+free_conv_msgstr(Msg_g_node *gmnp, int f)
{
- int i;
- unsigned int num_of_str;
+ uint32_t i, num_of_conv;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** free_conv_msgstr(0x%p)\n",
- (void *)gmnp);
- printgnumsg(gmnp, 0);
+ gprintf(0, "*************** free_conv_msgstr(0x%p, %d)\n",
+ (void *)gmnp, f);
+ printgnumsg(gmnp, 1);
#endif
- num_of_str = SWAP(gmnp, gmnp->msg_file_info->num_of_str);
- for (i = 0; i < num_of_str; i++) {
+ num_of_conv = gmnp->num_of_str + gmnp->num_of_d_str;
+ for (i = 0; i < num_of_conv; i++) {
if (gmnp->conv_msgstr[i]) {
free(gmnp->conv_msgstr[i]);
}
+ gmnp->conv_msgstr[i] = NULL;
+ }
+ if (f) {
+ free(gmnp->conv_msgstr);
+ gmnp->conv_msgstr = NULL;
}
- free(gmnp->conv_msgstr);
- gmnp->conv_msgstr = NULL;
-
}
/*
@@ -94,19 +106,19 @@ free_conv_msgstr(Msg_g_node *gmnp)
* and return it.
*/
static char *
-dfltmsgstr(Msg_g_node *gmnp, const char *msgstr, size_t msgstr_len,
- struct msg_pack *mp)
+dfltmsgstr(Msg_g_node *gmnp, const char *msgstr, uint32_t msgstr_len,
+ struct msg_pack *mp)
{
unsigned int pindex;
size_t len;
const char *p;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** dfltmsgstr(0x%p, \"%s\", %d, 0x%p)\n",
- (void *)gmnp,
- msgstr ? msgstr : "(null)", msgstr_len, (void *)mp);
- printgnumsg(gmnp, 0);
- printmp(mp, 0);
+ gprintf(0, "*************** dfltmsgstr(0x%p, \"%s\", %u, 0x%p)\n",
+ (void *)gmnp,
+ msgstr ? msgstr : "(null)", msgstr_len, (void *)mp);
+ printgnumsg(gmnp, 1);
+ printmp(mp, 1);
#endif
if (mp->plural) {
@@ -123,7 +135,7 @@ dfltmsgstr(Msg_g_node *gmnp, const char *msgstr, size_t msgstr_len,
pindex = 1;
}
#ifdef GETTEXT_DEBUG
- (void) printf("plural_eval returned: %d\n", pindex);
+ gprintf(0, "plural_eval returned: %u\n", pindex);
#endif
if (pindex >= gmnp->nplurals) {
/* should never happen */
@@ -133,14 +145,14 @@ dfltmsgstr(Msg_g_node *gmnp, const char *msgstr, size_t msgstr_len,
for (; pindex != 0; pindex--) {
len = msgstr_len - (p - msgstr);
p = memchr(p, '\0', len);
- if (!p) {
+ if (p == NULL) {
/*
* null byte not found
* this should never happen
*/
char *result;
DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
+ mp->n, mp->plural);
return (result);
}
p++; /* skip */
@@ -170,37 +182,37 @@ parse_header(const char *header, Msg_g_node *gmnp)
int ret;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** parse_header(\"%s\", 0x%p)\n",
- header ? header : "(null)", (void *)gmnp);
- printgnumsg(gmnp, 0);
+ gprintf(0, "*************** parse_header(\"%s\", 0x%p)\n",
+ header ? header : "(null)", (void *)gmnp);
+ printgnumsg(gmnp, 1);
#endif
- if (!header) {
+ if (header == NULL) {
gmnp->src_encoding = (char *)nullstr;
gmnp->nplurals = 2;
gmnp->plural = NULL;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** exiting parse_header\n");
- (void) printf("no header\n");
+ gprintf(0, "*************** exiting parse_header\n");
+ gprintf(0, "no header\n");
#endif
return (0);
}
charset_str = strstr(header, CHARSET_MOD);
- if (!charset_str) {
+ if (charset_str == NULL) {
gmnp->src_encoding = (char *)nullstr;
} else {
p = charset_str + CHARSET_LEN;
q = p;
while ((*q != ' ') && (*q != '\t') &&
- (*q != '\n')) {
+ (*q != '\n')) {
q++;
}
len = q - p;
if (len > 0) {
- charset = (char *)malloc(len + 1);
- if (!charset) {
+ charset = malloc(len + 1);
+ if (charset == NULL) {
gmnp->src_encoding = (char *)nullstr;
gmnp->nplurals = 2;
gmnp->plural = NULL;
@@ -216,13 +228,13 @@ parse_header(const char *header, Msg_g_node *gmnp)
nplurals_str = strstr(header, NPLURALS_MOD);
plural_str = strstr(header, PLURAL_MOD);
- if (!nplurals_str || !plural_str) {
+ if (nplurals_str == NULL || plural_str == NULL) {
/* no valid plural specification */
gmnp->nplurals = 2;
gmnp->plural = NULL;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** exiting parse_header\n");
- (void) printf("no plural entry\n");
+ gprintf(0, "*************** exiting parse_header\n");
+ gprintf(0, "no plural entry\n");
#endif
return (0);
} else {
@@ -239,7 +251,7 @@ parse_header(const char *header, Msg_g_node *gmnp)
p = plural_str + PLURAL_LEN;
#ifdef GETTEXT_DEBUG
- (void) printf("plural_str: \"%s\"\n", p);
+ gprintf(0, "plural_str: \"%s\"\n", p);
#endif
ret = plural_expr(&plural, (const char *)p);
@@ -247,10 +259,10 @@ parse_header(const char *header, Msg_g_node *gmnp)
/* parse succeeded */
gmnp->plural = plural;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** exiting parse_header\n");
- (void) printf("charset: \"%s\"\n",
- charset ? charset : "(null)");
- printexpr(plural, 0);
+ gprintf(0, "*************** exiting parse_header\n");
+ gprintf(0, "charset: \"%s\"\n",
+ charset ? charset : "(null)");
+ printexpr(plural, 1);
#endif
return (0);
} else if (ret == 1) {
@@ -271,58 +283,23 @@ parse_header(const char *header, Msg_g_node *gmnp)
/* NOTREACHED */
}
-static char *
-handle_gnu_mo(struct cache_pack *cp, struct msg_pack *mp,
- Gettext_t *gt)
-{
- char *result;
- char *codeset = get_codeset(mp->domain);
-
- result = gnu_key_2_text(cp->mnp->msg.gnumsg, codeset, mp);
- if (mp->plural) {
- if (((result == mp->msgid1) && (mp->n == 1)) ||
- ((result == mp->msgid2) && (mp->n != 1))) {
- return (NULL);
- }
- } else {
- if (result == mp->msgid1) {
- return (NULL);
- }
- }
- gt->c_m_node = cp->mnp;
- if (!cp->mnp->trusted) {
- result = check_format(mp->msgid1, result, 0);
- if (result == mp->msgid1) {
- DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n,
- mp->plural);
- }
- }
- return (result);
-}
-
/*
* handle_lang
*
* take care of the LANGUAGE specification
*/
char *
-handle_lang(struct cache_pack *cp, struct msg_pack *mp)
+handle_lang(struct msg_pack *mp)
{
- Gettext_t *gt = global_gt;
- struct stat64 statbuf;
const char *p, *op, *q;
- char *locale = NULL, *olocale, *result;
- unsigned int hash_locale;
- size_t locale_len, olocale_len = 0;
- int gnu_mo_found = 0;
- int fd;
- int ret;
+ size_t locale_len;
+ char *result;
+ char locale[MAXPATHLEN];
+
#ifdef GETTEXT_DEBUG
- (void) printf("*************** handle_lang(0x%p, 0x%p)\n",
- (void *)cp, (void *)mp);
- printcp(cp, 0);
- printmp(mp, 0);
+ gprintf(0, "*************** handle_lang(0x%p)\n", (void *)mp);
+ printmp(mp, 1);
#endif
p = mp->language;
@@ -330,36 +307,21 @@ handle_lang(struct cache_pack *cp, struct msg_pack *mp)
while (*p) {
op = p;
q = strchr(p, ':');
- if (!q) {
+ if (q == NULL) {
locale_len = strlen(p);
p += locale_len;
} else {
locale_len = q - p;
p += locale_len + 1;
}
- if ((locale_len >= MAXPATHLEN) ||
- (locale_len == 0)) {
+ if (locale_len >= MAXPATHLEN || locale_len == 0) {
/* illegal locale name */
continue;
}
- if (olocale_len < locale_len) {
- olocale = locale;
- locale = (char *)realloc(locale, locale_len + 1);
- if (!locale) {
- if (olocale)
- free(olocale);
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- return (result);
- }
- olocale_len = locale_len;
- }
(void) memcpy(locale, op, locale_len);
locale[locale_len] = '\0';
- hash_locale = get_hashid(locale, NULL);
mp->locale = locale;
- mp->hash_locale = hash_locale;
- mp->locale_len = locale_len;
+
#ifdef GETTEXT_DEBUG
*mp->msgfile = '\0';
#endif
@@ -368,121 +330,30 @@ handle_lang(struct cache_pack *cp, struct msg_pack *mp)
continue;
}
- cp->node_hash = NULL;
-
- ret = check_cache(cp, mp);
- if (ret) {
- /*
- * found in cache
- */
- switch (cp->mnp->type) {
- case T_ILL_MO:
- /* invalid MO */
- continue;
- case T_SUN_MO:
- /* Solaris MO */
- goto out_loop;
- case T_GNU_MO:
- /* GNU MO */
- gnu_mo_found = 1;
- result = handle_gnu_mo(cp, mp, gt);
- if (result) {
- free(locale);
- return (result);
- }
- continue;
- }
- /* NOTREACHED */
- }
- /*
- * not found in cache
- */
- fd = nls_safe_open(mp->msgfile, &statbuf, &mp->trusted, 1);
- if ((fd == -1) || (statbuf.st_size > LONG_MAX)) {
- if (connect_invalid_entry(cp, mp) == -1) {
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- free(locale);
- return (result);
- }
- continue;
- }
- mp->fsz = (size_t)statbuf.st_size;
- mp->addr = mmap(0, mp->fsz, PROT_READ, MAP_SHARED, fd, 0);
- (void) close(fd);
-
- if (mp->addr == (caddr_t)-1) {
- if (connect_invalid_entry(cp, mp) == -1) {
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- free(locale);
- return (result);
- }
- continue;
- }
-
- cp->mnp = create_mnp(mp);
- if (!cp->mnp) {
- free(locale);
- free_mnp_mp(cp->mnp, mp);
- DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n,
- mp->plural);
- return (result);
- }
-
- if (setmsg(cp->mnp, (char *)mp->addr, mp->fsz) == -1) {
- free(locale);
- free_mnp_mp(cp->mnp, mp);
- DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n,
- mp->plural);
+ result = handle_mo(mp);
+ if (mp->status & ST_GNU_MSG_FOUND)
return (result);
- }
- if (!cp->cacheline) {
- cp->cnp = create_cnp(cp->mnp, mp);
- if (!cp->cnp) {
- free(locale);
- free_mnp_mp(cp->mnp, mp);
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- return (result);
- }
- }
- cp->mnp->trusted = mp->trusted;
- connect_entry(cp);
- switch (cp->mnp->type) {
- case T_ILL_MO:
- /* invalid MO */
- continue;
- case T_SUN_MO:
- /* Solaris MO */
- goto out_loop;
- case T_GNU_MO:
- /* GNU MO */
- gnu_mo_found = 1;
-
- result = handle_gnu_mo(cp, mp, gt);
- if (result) {
- free(locale);
- return (result);
- }
- continue;
- }
- /* NOTREACHED */
+ if (mp->status & ST_SUN_MO_FOUND)
+ break;
}
-out_loop:
- if (gnu_mo_found) {
+ /*
+ * no valid locale found, Sun MO found, or
+ * GNU MO found but no valid msg found there.
+ */
+
+ if (mp->status & ST_GNU_MO_FOUND) {
+ /*
+ * GNU MO found but no valid msg found there.
+ * returning DFLTMSG.
+ */
DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
- free(locale);
return (result);
}
- if (locale)
- free(locale);
return (NULL);
}
-
/*
* gnu_msgsearch
*
@@ -499,45 +370,39 @@ out_loop:
*/
static char *
gnu_msgsearch(Msg_g_node *gmnp, const char *msgid1,
- size_t *msgstrlen, unsigned int *midx)
+ uint32_t *msgstrlen, uint32_t *midx)
{
- unsigned int *hash_table;
+ struct gnu_msg_info *header = gmnp->msg_file_info;
struct gnu_msg_ent *msgid_tbl, *msgstr_tbl;
+ uint32_t num_of_str, idx, mlen, msglen;
+ uint32_t hash_size, hash_val, hash_id, hash_inc, hash_idx;
+ uint32_t *hash_table;
char *base;
- struct gnu_msg_info *header = gmnp->msg_file_info;
- unsigned int hash_size, hash_val, hash_inc, hash_idx;
- unsigned int offset, msglen, idx;
- unsigned int num_of_str;
- unsigned int off_msgid_tbl, off_msgstr_tbl;
- size_t msgid1_len;
+ char *msg;
+
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "*************** gnu_msgsearch(0x%p, \"%s\", "
+ "0x%p, 0x%p)\n",
+ (void *)gmnp, msgid1, msgstrlen, midx);
+ printgnumsg(gmnp, 1);
+#endif
base = (char *)header;
- off_msgid_tbl = SWAP(gmnp, header->off_msgid_tbl);
- off_msgstr_tbl = SWAP(gmnp, header->off_msgstr_tbl);
- /* LINTED */
- msgid_tbl = (struct gnu_msg_ent *)(base + off_msgid_tbl);
- /* LINTED */
- msgstr_tbl = (struct gnu_msg_ent *)(base + off_msgstr_tbl);
+ msgid_tbl = gmnp->msg_tbl[MSGID];
+ msgstr_tbl = gmnp->msg_tbl[MSGSTR];
hash_table = gmnp->hash_table;
- hash_size = SWAP(gmnp, header->sz_hashtbl);
- num_of_str = SWAP(gmnp, header->num_of_str);
-
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** gnu_msgsearch("
- "0x%p, \"%s\", 0x%p, 0x%p)\n",
- (void *)gmnp,
- msgid1 ? msgid1 : "(null)",
- (void *)msgstrlen, (void *)midx);
- printgnumsg(gmnp, 0);
-#endif
+ hash_size = gmnp->hash_size;
+ num_of_str = gmnp->num_of_str;
- if (!hash_table || (hash_size <= 2)) {
+ if (!(gmnp->flag & ST_REV1) &&
+ (hash_table == NULL || (hash_size <= 2))) {
/*
+ * Revision 0 and
* No hash table exists or
- * hash size is enough small
+ * hash size is enough small.
*/
- unsigned int top, bottom;
+ uint32_t top, bottom;
char *msg_id_str;
int val;
@@ -546,7 +411,7 @@ gnu_msgsearch(Msg_g_node *gmnp, const char *msgid1,
while (top < bottom) {
idx = (top + bottom) / 2;
msg_id_str = base +
- SWAP(gmnp, msgid_tbl[idx].offset);
+ SWAP(gmnp, msgid_tbl[idx].offset);
val = strcmp(msg_id_str, msgid1);
if (val < 0) {
@@ -554,7 +419,11 @@ gnu_msgsearch(Msg_g_node *gmnp, const char *msgid1,
} else if (val > 0) {
bottom = idx;
} else {
- goto found;
+ *msgstrlen = (unsigned int)
+ SWAP(gmnp, msgstr_tbl[idx].len) + 1;
+ *midx = idx;
+ return (base +
+ SWAP(gmnp, msgstr_tbl[idx].offset));
}
}
/* not found */
@@ -562,36 +431,51 @@ gnu_msgsearch(Msg_g_node *gmnp, const char *msgid1,
}
/* use hash table */
- hash_val = get_hashid(msgid1, &msgid1_len);
- msglen = (unsigned int)msgid1_len;
- hash_idx = hash_val % hash_size;
- hash_inc = 1 + (hash_val % (hash_size - 2));
+ hash_id = get_hashid(msgid1, &msglen);
+ hash_idx = hash_id % hash_size;
+ hash_inc = 1 + (hash_id % (hash_size - 2));
for (;;) {
- offset = SWAP(gmnp, hash_table[hash_idx]);
+ hash_val = HASH_TBL(gmnp, hash_table[hash_idx]);
- if (offset == 0) {
+ if (hash_val == 0) {
+ /* not found */
return ((char *)msgid1);
}
-
- idx = offset - 1;
- if ((msglen <= SWAP(gmnp, msgid_tbl[idx].len)) &&
- strcmp(msgid1, base +
- SWAP(gmnp, msgid_tbl[idx].offset)) == 0) {
+ if (hash_val <= num_of_str) {
+ /* static message */
+ idx = hash_val - 1;
+ mlen = SWAP(gmnp, msgid_tbl[idx].len);
+ msg = base + SWAP(gmnp, msgid_tbl[idx].offset);
+ } else {
+ if (!(gmnp->flag & ST_REV1)) {
+ /* rev 0 does not have dynamic message */
+ return ((char *)msgid1);
+ }
+ /* dynamic message */
+ idx = hash_val - num_of_str - 1;
+ mlen = gmnp->d_msg[MSGID][idx].len;
+ msg = gmnp->mchunk + gmnp->d_msg[MSGID][idx].offset;
+ }
+ if (msglen <= mlen && strcmp(msgid1, msg) == 0) {
/* found */
- goto found;
+ break;
}
-
hash_idx = (hash_idx + hash_inc) % hash_size;
}
- /* NOTREACHED */
-found:
- if (msgstrlen)
+ /* msgstrlen should include a null termination */
+ if (hash_val <= num_of_str) {
*msgstrlen = SWAP(gmnp, msgstr_tbl[idx].len) + 1;
- if (midx)
+ msg = base + SWAP(gmnp, msgstr_tbl[idx].offset);
*midx = idx;
- return (base + SWAP(gmnp, msgstr_tbl[idx].offset));
+ } else {
+ *msgstrlen = gmnp->d_msg[MSGSTR][idx].len + 1;
+ msg = gmnp->mchunk + gmnp->d_msg[MSGSTR][idx].offset;
+ *midx = idx + num_of_str;
+ }
+
+ return (msg);
}
/*
@@ -600,55 +484,119 @@ found:
* Converts the specified string from the src encoding
* to the dst encoding by calling iconv()
*/
-static size_t
-do_conv(iconv_t fd, char **dst, const char *src, size_t srclen)
+static uint32_t *
+do_conv(iconv_t fd, const char *src, uint32_t srclen)
{
- size_t oleft, ileft, bufsize, tolen;
+ uint32_t tolen;
+ uint32_t *ptr, *optr;
+ size_t oleft, ileft, bufsize, memincr;
char *to, *tptr;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** do_conv("
- "0x%p, 0x%p, \"%s\", %d)\n",
- (void *)fd, (void *)dst, src ? src : "(null)", srclen);
+ gprintf(0, "*************** do_conv("
+ "0x%p, \"%s\", %d)\n",
+ (void *)fd, src ? src : "(null)", srclen);
#endif
- bufsize = srclen * 2;
+ memincr = srclen * 2;
+ bufsize = memincr;
ileft = srclen;
oleft = bufsize;
- to = (char *)malloc(bufsize);
- if (!to) {
- return ((size_t)-1);
+ ptr = malloc(bufsize + sizeof (uint32_t));
+ if (ptr == NULL) {
+ return (NULL);
}
+ to = (char *)(ptr + 1);
- for (; ; ) {
+ for (;;) {
tptr = to;
errno = 0;
#ifdef GETTEXT_DEBUG
- (void) printf("******* calling iconv()\n");
+ gprintf(0, "******* calling iconv()\n");
#endif
- if (iconv(fd, &src, &ileft, &tptr, &oleft) ==
- (size_t)-1) {
+ if (iconv(fd, &src, &ileft, &tptr, &oleft) == (size_t)-1) {
if (errno == E2BIG) {
- char *oto;
- oleft += bufsize;
- bufsize *= 2;
- oto = to;
- to = (char *)realloc(oto, bufsize);
- if (!to) {
- free(oto);
- return ((size_t)-1);
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "******* iconv detected E2BIG\n");
+ gprintf(0, "old bufsize: %u\n", bufsize);
+#endif
+
+ optr = realloc(ptr,
+ bufsize + memincr + sizeof (uint32_t));
+ if (optr == NULL) {
+ free(ptr);
+ return (NULL);
}
+ ptr = optr;
+ to = (char *)(optr + 1);
+ to += bufsize - oleft;
+ oleft += memincr;
+ bufsize += memincr;
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "new bufsize: %u\n", bufsize);
+#endif
continue;
} else {
- tolen = bufsize - oleft;
+ tolen = (uint32_t)(bufsize - oleft);
break;
}
}
- tolen = bufsize - oleft;
+ tolen = (uint32_t)(bufsize - oleft);
break;
}
- *dst = to;
- return (tolen);
+
+ if (tolen < bufsize) {
+ /* shrink the buffer */
+ optr = realloc(ptr, tolen + sizeof (uint32_t));
+ if (optr == NULL) {
+ free(ptr);
+ return (NULL);
+ }
+ ptr = optr;
+ }
+ *ptr = tolen;
+
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "******* exiting do_conv()\n");
+ gprintf(0, "tolen: %u\n", *ptr);
+ gprintf(0, "return: 0x%p\n", ptr);
+#endif
+ return (ptr);
+}
+
+/*
+ * conv_msg
+ */
+static char *
+conv_msg(Msg_g_node *gmnp, char *msgstr, uint32_t msgstr_len, uint32_t midx,
+ struct msg_pack *mp)
+{
+ uint32_t *conv_dst;
+ size_t num_of_conv, conv_msgstr_len;
+ char *conv_msgstr, *result;
+
+ if (gmnp->conv_msgstr == NULL) {
+ num_of_conv = gmnp->num_of_str + gmnp->num_of_d_str;
+ gmnp->conv_msgstr =
+ calloc((size_t)num_of_conv, sizeof (uint32_t *));
+ if (gmnp->conv_msgstr == NULL) {
+ /* malloc failed */
+ result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
+ return (result);
+ }
+ }
+
+ conv_dst = do_conv(gmnp->fd, (const char *)msgstr, msgstr_len);
+
+ if (conv_dst == NULL) {
+ result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
+ return (result);
+ }
+ conv_msgstr_len = *conv_dst;
+ gmnp->conv_msgstr[midx] = conv_dst;
+ conv_msgstr = (char *)(conv_dst + 1);
+ result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
+ return (result);
}
/*
@@ -658,37 +606,31 @@ do_conv(iconv_t fd, char **dst, const char *src, size_t srclen)
*/
char *
gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
- struct msg_pack *mp)
+ struct msg_pack *mp)
{
- char *result, *msgstr;
- size_t msgstr_len;
- unsigned int midx;
- int ret;
- char *conv_msgstr, *conv_dst;
- size_t *p;
- size_t conv_msgstr_len, buflen;
+ uint32_t msgstr_len, midx;
iconv_t fd;
- int conversion, new_encoding;
- unsigned int num_of_str;
+ char *result, *msgstr;
+ int ret, conversion, new_encoding;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** gnu_key_2_text("
- "0x%p, \"%s\", 0x%p)\n",
- (void *)gmnp, codeset ? codeset : "(null)", (void *)mp);
- printgnumsg(gmnp, 0);
- printmp(mp, 0);
+ gprintf(0, "*************** gnu_key_2_text("
+ "0x%p, \"%s\", 0x%p)\n",
+ (void *)gmnp, codeset ? codeset : "(null)", (void *)mp);
+ printgnumsg(gmnp, 1);
+ printmp(mp, 1);
#endif
/* first checks if header entry has been processed */
if (!(gmnp->flag & ST_CHK)) {
char *msg_header;
- msg_header = gnu_msgsearch(gmnp, "", NULL, NULL);
+ msg_header = gnu_msgsearch(gmnp, "", &msgstr_len, &midx);
ret = parse_header((const char *)msg_header, gmnp);
if (ret == -1) {
/* fatal error */
DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
+ mp->n, mp->plural);
return (result);
}
gmnp->flag |= ST_CHK;
@@ -701,14 +643,14 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
}
#ifdef GETTEXT_DEBUG
- printgnumsg(gmnp, 0);
+ printgnumsg(gmnp, 1);
#endif
- if (!gmnp->dst_encoding) {
+ if (gmnp->dst_encoding == NULL) {
/*
* destination encoding has not been set.
*/
char *dupcodeset = strdup(codeset);
- if (!dupcodeset) {
+ if (dupcodeset == NULL) {
/* strdup failed */
result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
return (result);
@@ -734,7 +676,7 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
gmnp->fd = (iconv_t)-1;
}
if (gmnp->conv_msgstr)
- free_conv_msgstr(gmnp);
+ free_conv_msgstr(gmnp, 0);
conversion = 1;
new_encoding = 1;
}
@@ -747,7 +689,7 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
* dst encoding and target encoding are the same.
*/
if (strcmp(gmnp->dst_encoding, gmnp->src_encoding)
- == 0) {
+ == 0) {
/*
* dst encoding and src encoding are the same.
* No conversion required.
@@ -768,7 +710,7 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
*/
conversion = 0;
} else {
- if (!gmnp->conv_msgstr) {
+ if (gmnp->conv_msgstr == NULL) {
/*
* memory allocation for
* conv_msgstr should
@@ -777,7 +719,7 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
new_encoding = 1;
if (gmnp->fd)
(void) iconv_close(
- gmnp->fd);
+ gmnp->fd);
gmnp->fd = (iconv_t)-1;
}
}
@@ -788,20 +730,22 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
* It has changed since before.
*/
char *dupcodeset = strdup(codeset);
- if (!dupcodeset) {
+ if (dupcodeset == NULL) {
result = dfltmsgstr(gmnp, msgstr,
- msgstr_len, mp);
+ msgstr_len, mp);
return (result);
}
free(gmnp->dst_encoding);
gmnp->dst_encoding = dupcodeset;
if (strcmp(gmnp->dst_encoding, gmnp->src_encoding)
- == 0) {
+ == 0) {
/*
* dst encoding and src encoding are the same.
* now, no conversion required.
*/
conversion = 0;
+ if (gmnp->conv_msgstr)
+ free_conv_msgstr(gmnp, 1);
} else {
/*
* dst encoding is different from src encoding.
@@ -809,6 +753,8 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
*/
conversion = 1;
new_encoding = 1;
+ if (gmnp->conv_msgstr)
+ free_conv_msgstr(gmnp, 0);
}
if (gmnp->fd && (gmnp->fd != (iconv_t)-1)) {
@@ -817,8 +763,6 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
if (gmnp->fd != (iconv_t)-1) {
gmnp->fd = (iconv_t)-1;
}
- if (gmnp->conv_msgstr)
- free_conv_msgstr(gmnp);
}
}
@@ -831,47 +775,27 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
if (new_encoding == 0) {
/* dst codeset hasn't been changed since before */
- if (!gmnp->conv_msgstr[midx]) {
+ uint32_t *cmsg;
+ uint32_t conv_msgstr_len;
+ char *conv_msgstr;
+
+ if (gmnp->conv_msgstr[midx] == NULL) {
/* this msgstr hasn't been converted yet */
- conv_msgstr_len = do_conv(gmnp->fd,
- &conv_dst, (const char *)msgstr, msgstr_len);
- if (conv_msgstr_len == (size_t)-1) {
- result = dfltmsgstr(gmnp, msgstr,
- msgstr_len, mp);
- return (result);
- }
- buflen = (conv_msgstr_len + sizeof (size_t));
- /* allign to sizeof (size_t) */
- if (buflen % sizeof (size_t))
- buflen += (sizeof (size_t) -
- (buflen % sizeof (size_t)));
- p = (size_t *)malloc(buflen);
- if (!p) {
- free(conv_dst);
- result = dfltmsgstr(gmnp, msgstr,
- msgstr_len, mp);
- return (result);
- }
- *p = conv_msgstr_len;
- (void) memcpy(p + 1, conv_dst, conv_msgstr_len);
- free(conv_dst);
- gmnp->conv_msgstr[midx] = (char *)p;
- conv_msgstr = (char *)(p + 1);
- } else {
- /* this msgstr is in the conversion cache */
- /* LINTED */
- size_t *cmsg = (size_t *)gmnp->conv_msgstr[midx];
- conv_msgstr_len = *cmsg;
- conv_msgstr = (char *)(cmsg + 1);
+ result = conv_msg(gmnp, msgstr, msgstr_len, midx, mp);
+ return (result);
}
+ /* this msgstr is in the conversion cache */
+ cmsg = (uint32_t *)(uintptr_t)gmnp->conv_msgstr[midx];
+ conv_msgstr_len = *cmsg;
+ conv_msgstr = (char *)(cmsg + 1);
result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
return (result);
}
/* new conversion */
#ifdef GETTEXT_DEBUG
- (void) printf("******* calling iconv_open()\n");
- (void) printf(" dst: \"%s\", src: \"%s\"\n",
- gmnp->dst_encoding, gmnp->src_encoding);
+ gprintf(0, "******* calling iconv_open()\n");
+ gprintf(0, " dst: \"%s\", src: \"%s\"\n",
+ gmnp->dst_encoding, gmnp->src_encoding);
#endif
fd = iconv_open(gmnp->dst_encoding, gmnp->src_encoding);
gmnp->fd = fd;
@@ -883,37 +807,495 @@ gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
return (result);
}
- num_of_str = SWAP(gmnp, gmnp->msg_file_info->num_of_str);
- gmnp->conv_msgstr = (char **)calloc((size_t)num_of_str,
- sizeof (char *));
- if (!gmnp->conv_msgstr) {
- /* malloc failed */
- result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
- return (result);
+ result = conv_msg(gmnp, msgstr, msgstr_len, midx, mp);
+ return (result);
+}
+
+
+#define PRI_STR(x, n) PRI##x##n
+#define PRI_LEN(x, n) (char)(sizeof (PRI_STR(x, n)) - 1)
+#define PRIS(P, x) {\
+/* x/N/ */ P(x, 8), P(x, 16), P(x, 32), P(x, 64), \
+/* xLEAST/N/ */ P(x, LEAST8), P(x, LEAST16), P(x, LEAST32), P(x, LEAST64), \
+/* xFAST/N/ */ P(x, FAST8), P(x, FAST16), P(x, FAST32), P(x, FAST64), \
+/* xMAX,PTR */ P(x, MAX), P(x, PTR) \
+}
+
+#define PRI_BIAS_LEAST 4
+#define PRI_BIAS_FAST 8
+#define PRI_BIAS_MAX 12
+#define PRI_BIAS_PTR 13
+
+static const char *pri_d[] = PRIS(PRI_STR, d);
+static const char *pri_i[] = PRIS(PRI_STR, i);
+static const char *pri_o[] = PRIS(PRI_STR, o);
+static const char *pri_u[] = PRIS(PRI_STR, u);
+static const char *pri_x[] = PRIS(PRI_STR, x);
+static const char *pri_X[] = PRIS(PRI_STR, X);
+
+static const char pri_d_len[] = PRIS(PRI_LEN, d);
+static const char pri_i_len[] = PRIS(PRI_LEN, i);
+static const char pri_o_len[] = PRIS(PRI_LEN, o);
+static const char pri_u_len[] = PRIS(PRI_LEN, u);
+static const char pri_x_len[] = PRIS(PRI_LEN, x);
+static const char pri_X_len[] = PRIS(PRI_LEN, X);
+
+static struct {
+ const char type;
+ const char **str_table;
+ const char *len_table;
+} pri_table[] = {
+ {'d', pri_d, pri_d_len}, {'i', pri_i, pri_i_len},
+ {'o', pri_o, pri_o_len}, {'u', pri_u, pri_u_len},
+ {'x', pri_x, pri_x_len}, {'X', pri_X, pri_X_len},
+};
+
+static struct {
+ const char *name;
+ const char nlen;
+ const char want_digits;
+ const char bias;
+} special_table[] = {
+ {"LEAST", 5, 1, PRI_BIAS_LEAST},
+ {"FAST", 4, 1, PRI_BIAS_FAST},
+ {"MAX", 3, 0, PRI_BIAS_MAX},
+ {"PTR", 3, 0, PRI_BIAS_PTR},
+};
+
+/*
+ * conv_macro() returns the conversion specifier corresponding
+ * to the macro name specified in 'name'. 'len' contains the
+ * length of the macro name including the null termination.
+ * '*elen' will be set to the length of the returning conversion
+ * specifier without the null termination.
+ */
+static const char *
+conv_macro(const char *str, uint32_t len, uint32_t *lenp)
+{
+ const char **tbl;
+ const char *ltbl;
+ char *next;
+ int n, i, num, bias, idx, want_digits;
+
+ if (len == 2) {
+ if (*str == 'I') {
+ /* Solaris does not support %I */
+ *lenp = 0;
+ return ("");
+ }
+ return (NULL);
}
- conv_msgstr_len = do_conv(gmnp->fd, &conv_dst,
- (const char *)msgstr, msgstr_len);
- if (conv_msgstr_len == (size_t)-1) {
- free_conv_msgstr(gmnp);
- result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
- return (result);
+
+ if (len <= 4 || strncmp(str, "PRI", 3) != 0)
+ return (NULL);
+
+ str += 3;
+
+ n = sizeof (pri_table) / sizeof (pri_table[0]);
+ for (i = 0; i < n; i++) {
+ if (pri_table[i].type == *str)
+ break;
}
- buflen = (conv_msgstr_len + sizeof (size_t));
- /* allign to sizeof (size_t) */
- if (buflen % sizeof (size_t))
- buflen += (sizeof (size_t) - (buflen % sizeof (size_t)));
- p = (size_t *)malloc(buflen);
- if (!p) {
- free(conv_dst);
- free_conv_msgstr(gmnp);
- result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
- return (result);
+ if (i == n)
+ return (NULL);
+ tbl = pri_table[i].str_table;
+ ltbl = pri_table[i].len_table;
+
+ str++;
+ idx = want_digits = 0;
+
+ if (isdigit((unsigned char)*str)) {
+ /* PRIx/N/ */
+ bias = 0;
+ want_digits = 1;
+ } else {
+ n = sizeof (special_table) / sizeof (special_table[0]);
+ for (i = 0; i < n; i++) {
+ if (strncmp(special_table[i].name,
+ str, special_table[i].nlen) == 0) {
+ break;
+ }
+ }
+ if (i == n)
+ return (NULL);
+ bias = special_table[i].bias;
+ want_digits = special_table[i].want_digits;
+ str += special_table[i].nlen;
}
- *p = conv_msgstr_len;
- (void) memcpy(p + 1, conv_dst, conv_msgstr_len);
- free(conv_dst);
- gmnp->conv_msgstr[midx] = (char *)p;
- conv_msgstr = (char *)(p + 1);
- result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
- return (result);
+
+ if (want_digits) {
+ if (!isdigit((unsigned char)*str))
+ return (NULL);
+ num = strtol(str, &next, 10);
+ /* see if it is 8/16/32/64 */
+ for (n = 8, idx = 0; idx < 4; idx++, n *= 2) {
+ if (n == num)
+ break;
+ }
+ if (idx == 4)
+ return (NULL);
+ str = next;
+ }
+ if (*str != '\0') {
+ /* unknow format */
+ return (NULL);
+ }
+
+ *lenp = (uint32_t)ltbl[bias + idx];
+ return (tbl[bias + idx]);
+}
+
+static gnu_d_macro_t *
+expand_macros(Msg_g_node *p)
+{
+ char *base = (char *)p->msg_file_info;
+ struct gnu_msg_rev1_info *rev1_header = p->rev1_header;
+ struct gnu_msg_ent *d_macro_tbl;
+ gnu_d_macro_t *d_macro;
+ uint32_t num_of_d_macro, e_maclen, maclen, i;
+ const char *e_macname;
+ char *macname;
+
+ /* number of the dynamic macros */
+ num_of_d_macro = SWAP(p, rev1_header->num_of_dynamic_macro);
+
+ d_macro = malloc((size_t)num_of_d_macro * sizeof (gnu_d_macro_t));
+ if (d_macro == NULL)
+ return (NULL);
+
+ /* pointer to the dynamic strings table */
+ d_macro_tbl = (struct gnu_msg_ent *)(uintptr_t)
+ (base + SWAP(p, rev1_header->off_dynamic_macro));
+
+ for (i = 0; i < num_of_d_macro; i++) {
+ macname = base + SWAP(p, d_macro_tbl[i].offset);
+ maclen = SWAP(p, d_macro_tbl[i].len);
+
+ /*
+ * sanity check
+ * maclen includes a null termination.
+ */
+ if (maclen != strlen(macname) + 1) {
+ free(d_macro);
+ return (NULL);
+ }
+ e_macname = conv_macro(macname, maclen, &e_maclen);
+ if (e_macname == NULL) {
+ free(d_macro);
+ return (NULL);
+ }
+ d_macro[i].len = e_maclen;
+ d_macro[i].ptr = e_macname;
+ }
+
+ return (d_macro);
+}
+
+static char *
+expand_dynamic_message(Msg_g_node *p, struct gnu_msg_ent **e_msgs)
+{
+
+ char *base = (char *)p->msg_file_info;
+ struct gnu_msg_rev1_info *rev1_header = p->rev1_header;
+ struct gnu_dynamic_tbl *d_info;
+ struct gnu_dynamic_ent *entry;
+ gnu_d_macro_t *d_macro;
+ uint32_t num_of_d_str, mlen, dlen, didx, i, j;
+ uint32_t off_d_tbl;
+ uint32_t *d_msg_off_tbl;
+ size_t mchunk_size, used, need;
+ char *mchunk, *msg;
+
+#define MEM_INCR (1024)
+
+ d_macro = expand_macros(p);
+ if (d_macro == NULL)
+ return (NULL);
+
+ /* number of dynamic messages */
+ num_of_d_str = p->num_of_d_str;
+
+ mchunk = NULL;
+ mchunk_size = 0; /* size of the allocated memory in mchunk */
+ used = 0; /* size of the used memory in mchunk */
+ for (i = MSGID; i <= MSGSTR; i++) {
+ /* pointer to the offset table of dynamic msgids/msgstrs */
+ off_d_tbl = SWAP(p,
+ i == MSGID ? rev1_header->off_dynamic_msgid_tbl :
+ rev1_header->off_dynamic_msgstr_tbl);
+ /* pointer to the dynamic msgids/msgstrs */
+ d_msg_off_tbl = (uint32_t *)(uintptr_t)(base + off_d_tbl);
+ for (j = 0; j < num_of_d_str; j++) {
+ e_msgs[i][j].offset = used;
+ d_info = (struct gnu_dynamic_tbl *)(uintptr_t)
+ (base + SWAP(p, d_msg_off_tbl[j]));
+ entry = d_info->entry;
+ msg = base + SWAP(p, d_info->offset);
+
+ for (;;) {
+ mlen = SWAP(p, entry->len);
+ didx = SWAP(p, entry->idx);
+ dlen = (didx == NOMORE_DYNAMIC_MACRO) ? 0 :
+ d_macro[didx].len;
+ need = used + mlen + dlen;
+ if (need >= mchunk_size) {
+ char *t;
+ size_t n = mchunk_size;
+ do {
+ n += MEM_INCR;
+ } while (n <= need);
+ t = realloc(mchunk, n);
+ if (t == NULL) {
+ free(d_macro);
+ free(mchunk);
+ return (NULL);
+ }
+ mchunk = t;
+ mchunk_size = n;
+ }
+ (void) memcpy(mchunk + used, msg, (size_t)mlen);
+ msg += mlen;
+ used += mlen;
+
+ if (didx == NOMORE_DYNAMIC_MACRO) {
+ /*
+ * Last segment of a static
+ * msg string contains a null
+ * termination, so an explicit
+ * null termination is not required
+ * here.
+ */
+ break;
+ }
+ (void) memcpy(mchunk + used,
+ d_macro[didx].ptr, (size_t)dlen);
+ used += dlen;
+ entry++; /* to next entry */
+ }
+ /*
+ * e_msgs[][].len does not include a null termination
+ */
+ e_msgs[i][j].len = used - e_msgs[i][j].offset - 1;
+ }
+ }
+
+ free(d_macro);
+
+ /* shrink mchunk to 'used' */
+ {
+ char *t;
+ t = realloc(mchunk, used);
+ if (t == NULL) {
+ free(mchunk);
+ return (NULL);
+ }
+ mchunk = t;
+ }
+
+ return (mchunk);
+}
+
+static int
+build_rev1_info(Msg_g_node *p)
+{
+ uint32_t *d_hash;
+ uint32_t num_of_d_str, num_of_str;
+ uint32_t idx, hash_value, hash_size;
+ size_t hash_mem_size;
+ size_t d_msgid_size, d_msgstr_size;
+ char *chunk, *mchunk;
+ int i;
+
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "******* entering build_rev1_info(0x%p)\n", p);
+ printgnumsg(p, 1);
+#endif
+
+ if (p->hash_table == NULL) {
+ /* Revision 1 always requires the hash table */
+ return (-1);
+ }
+
+ num_of_str = p->num_of_str;
+ hash_size = p->hash_size;
+ num_of_d_str = p->num_of_d_str;
+
+ hash_mem_size = hash_size * sizeof (uint32_t);
+ ROUND(hash_mem_size, sizeof (struct gnu_msg_ent));
+
+ d_msgid_size = num_of_d_str * sizeof (struct gnu_msg_ent);
+ d_msgstr_size = num_of_d_str * sizeof (struct gnu_msg_ent);
+
+ chunk = malloc(hash_mem_size + d_msgid_size + d_msgstr_size);
+ if (chunk == NULL) {
+ return (-1);
+ }
+
+ d_hash = (uint32_t *)(uintptr_t)chunk;
+ p->d_msg[MSGID] = (struct gnu_msg_ent *)(uintptr_t)
+ (chunk + hash_mem_size);
+ p->d_msg[MSGSTR] = (struct gnu_msg_ent *)(uintptr_t)
+ (chunk + hash_mem_size + d_msgid_size);
+
+ if ((mchunk = expand_dynamic_message(p, p->d_msg)) == NULL) {
+ free(chunk);
+ return (-1);
+ }
+
+ /* copy the original hash table into the dynamic hash table */
+ for (i = 0; i < hash_size; i++) {
+ d_hash[i] = SWAP(p, p->hash_table[i]);
+ }
+
+ /* fill in the dynamic hash table with dynamic messages */
+ for (i = 0; i < num_of_d_str; i++) {
+ hash_value = get_hashid(mchunk + p->d_msg[MSGID][i].offset,
+ NULL);
+ idx = get_hash_index(d_hash, hash_value, hash_size);
+ d_hash[idx] = num_of_str + i + 1;
+ }
+
+ p->mchunk = mchunk;
+ p->hash_table = d_hash;
+
+#ifdef GETTEXT_DEBUG
+ print_rev1_info(p);
+ gprintf(0, "******* exiting build_rev1_info()\n");
+ printgnumsg(p, 1);
+#endif
+
+ return (0);
+}
+
+/*
+ * gnu_setmsg
+ *
+ * INPUT
+ * mnp - message node
+ * addr - address to the mmapped file
+ * size - size of the file
+ *
+ * RETURN
+ * 0 - either T_GNU_MO or T_ILL_MO has been set
+ * -1 - failed
+ */
+int
+gnu_setmsg(Msg_node *mnp, char *addr, size_t size)
+{
+ struct gnu_msg_info *gnu_header;
+ Msg_g_node *p;
+
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "******** entering gnu_setmsg(0x%p, 0x%p, %lu)\n",
+ (void *)mnp, addr, size);
+ printmnp(mnp, 1);
+#endif
+
+ /* checks the GNU MAGIC number */
+ if (size < sizeof (struct gnu_msg_info)) {
+ /* invalid mo file */
+ mnp->type = T_ILL_MO;
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "********* exiting gnu_setmsg\n");
+ printmnp(mnp, 1);
+#endif
+ return (0);
+ }
+
+ gnu_header = (struct gnu_msg_info *)(uintptr_t)addr;
+
+ p = calloc(1, sizeof (Msg_g_node));
+ if (p == NULL) {
+ return (-1);
+ }
+ p->msg_file_info = gnu_header;
+
+ if (gnu_header->magic == GNU_MAGIC) {
+ switch (gnu_header->revision) {
+ case GNU_REVISION_0_1:
+ case GNU_REVISION_1_1:
+ p->flag |= ST_REV1;
+ break;
+ }
+ } else if (gnu_header->magic == GNU_MAGIC_SWAPPED) {
+ p->flag |= ST_SWP;
+ switch (gnu_header->revision) {
+ case GNU_REVISION_0_1_SWAPPED:
+ case GNU_REVISION_1_1_SWAPPED:
+ p->flag |= ST_REV1;
+ break;
+ }
+ } else {
+ /* invalid mo file */
+ free(p);
+ mnp->type = T_ILL_MO;
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "********* exiting gnu_setmsg\n");
+ printmnp(mnp, 1);
+#endif
+ return (0);
+ }
+
+ p->fsize = size;
+ p->num_of_str = SWAP(p, gnu_header->num_of_str);
+ p->hash_size = SWAP(p, gnu_header->sz_hashtbl);
+ p->hash_table = p->hash_size <= 2 ? NULL :
+ (uint32_t *)(uintptr_t)
+ (addr + SWAP(p, gnu_header->off_hashtbl));
+
+ p->msg_tbl[MSGID] = (struct gnu_msg_ent *)(uintptr_t)
+ (addr + SWAP(p, gnu_header->off_msgid_tbl));
+ p->msg_tbl[MSGSTR] = (struct gnu_msg_ent *)(uintptr_t)
+ (addr + SWAP(p, gnu_header->off_msgstr_tbl));
+
+ if (p->flag & ST_REV1) {
+ /* Revision 1 */
+ struct gnu_msg_rev1_info *rev1_header;
+
+ rev1_header = (struct gnu_msg_rev1_info *)
+ (uintptr_t)(addr + sizeof (struct gnu_msg_info));
+ p->rev1_header = rev1_header;
+ p->num_of_d_str = SWAP(p, rev1_header->num_of_dynamic_str);
+ if (build_rev1_info(p) == -1) {
+ free(p);
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "******** exiting gnu_setmsg: "
+ "build_rev1_info() failed\n");
+#endif
+ return (-1);
+ }
+ }
+
+ mnp->msg.gnumsg = p;
+ mnp->type = T_GNU_MO;
+
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "********* exiting gnu_setmsg\n");
+ printmnp(mnp, 1);
+#endif
+ return (0);
+}
+
+/*
+ * get_hash_index
+ *
+ * Returns the index to an empty slot in the hash table
+ * for the specified hash_value.
+ */
+static uint32_t
+get_hash_index(uint32_t *hash_tbl, uint32_t hash_value, uint32_t hash_size)
+{
+ uint32_t idx, inc;
+
+ idx = hash_value % hash_size;
+ inc = 1 + (hash_value % (hash_size - 2));
+
+ for (;;) {
+ if (hash_tbl[idx] == 0) {
+ /* found an empty slot */
+ return (idx);
+ }
+ idx = (idx + inc) % hash_size;
+ }
+ /* NOTREACHED */
}
diff --git a/usr/src/lib/libc/port/i18n/gettext_real.c b/usr/src/lib/libc/port/i18n/gettext_real.c
index c40f103be0..516364835f 100644
--- a/usr/src/lib/libc/port/i18n/gettext_real.c
+++ b/usr/src/lib/libc/port/i18n/gettext_real.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -50,68 +49,44 @@
#include "nlspath_checks.h"
static int process_nlspath(const char *, const char *,
- const char *, char **);
-static char *replace_nls_option(char *, const char *, char *,
- char *, char *, char *, char *);
-static char *key_2_text(Msg_s_node *, const char *);
-static char *handle_mo(struct cache_pack *, struct msg_pack *);
-static void mini_strcpy(char *, const char *);
-static size_t mini_strlen(const char *);
+ const char *, char **);
+static char *replace_nls_option(char *, const char *, char *,
+ char *, char *, char *, char *);
char *
-_real_gettext_u(const char *domain,
- const char *msgid1, const char *msgid2,
- unsigned long int ln, int category,
- int plural)
+_real_gettext_u(const char *domain, const char *msgid1, const char *msgid2,
+ unsigned long int ln, int category, int plural)
{
char msgfile[MAXPATHLEN]; /* 1024 */
- char binding[MAXPATHLEN]; /* 1024 */
char mydomain[TEXTDOMAINMAX + 1]; /* 256 + 1 */
char *cur_binding; /* points to current binding in list */
- char *bptr, *cur_locale, *cur_domain, *result, *nlspath;
- char *locale, *msgloc, *cb, *cur_domain_binding;
+ char *cur_locale, *cur_domain, *result, *nlspath;
+ char *msgloc, *cb, *cur_domain_binding;
char *language;
- int n = (unsigned int)ln; /* we don't need long for n */
- size_t cblen, cur_locale_len, cur_domain_len;
- unsigned int hash_locale;
-
+ unsigned int n = (unsigned int)ln; /* we don't need long for n */
+ uint32_t cur_domain_len, cblen;
+ uint32_t hash_domain;
struct msg_pack *mp, omp;
- struct cache_pack *cp, ocp;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** _real_gettext_u(%s, %s, "
- "%s, %d, %d, %d)\n",
+ gprintf(0, "*************** _real_gettext_u(\"%s\", \"%s\", "
+ "\"%s\", %d, %d, %d)\n",
domain ? domain : "NULL", msgid1 ? msgid1 : "NULL",
- msgid2 ? msgid2 : "NULL", n, category, plural);
+ msgid2 ? msgid2 : "NULL", n, category, plural);
+ gprintf(0, "***************** global_gt: 0x%p\n", global_gt);
+ printgt(global_gt, 1);
#endif
if (msgid1 == NULL)
return (NULL);
- cp = memset(&ocp, 0, sizeof (ocp)); /* cache pack */
mp = memset(&omp, 0, sizeof (omp)); /* msg pack */
/*
* category may be LC_MESSAGES or LC_TIME
* locale contains the value of 'category'
- * hash_locale contains the hash value of locale
- * msgloc contains the value of LC_MESSAGES
- * hash_msgloc contains the hash value of msgloc
*/
- locale = setlocale(category, NULL);
- hash_locale = get_hashid(locale, &cur_locale_len);
-
- /*
- * content of locale will be overridden by
- * succeeding setlocale invocation.
- * So, duplicate it
- */
- cur_locale = (char *)malloc(cur_locale_len + 1);
- if (!cur_locale) {
- DFLTMSG(result, msgid1, msgid2, n, plural);
- return (result);
- }
- mini_strcpy(cur_locale, locale);
+ cur_locale = setlocale(category, NULL);
language = getenv("LANGUAGE"); /* for GNU */
if (language) {
@@ -129,39 +104,36 @@ _real_gettext_u(const char *domain,
* Query the current domain if domain argument is NULL pointer
*/
mydomain[0] = '\0';
- if (!domain) {
+ if (domain == NULL) {
/*
* if NULL is specified for domainname,
* use the currently bound domain.
*/
cur_domain = _textdomain_u(NULL, mydomain);
- cur_domain_len = mini_strlen(cur_domain);
} else if (!*domain) {
/*
* if an empty string is specified
*/
cur_domain = DEFAULT_DOMAIN;
- cur_domain_len = DEFAULT_DOMAIN_LEN;
} else {
- cur_domain_len = mini_strlen(domain);
- if (cur_domain_len > TEXTDOMAINMAX) {
- /* domain is invalid, return msg_id */
- free(cur_locale);
- DFLTMSG(result, msgid1, msgid2, n, plural);
- return (result);
- }
cur_domain = (char *)domain;
}
+ hash_domain = get_hashid(cur_domain, &cur_domain_len);
+ if (cur_domain_len > TEXTDOMAINMAX) {
+ /* domain is invalid, return msg_id */
+ DFLTMSG(result, msgid1, msgid2, n, plural);
+ return (result);
+ }
+
nlspath = getenv("NLSPATH"); /* get the content of NLSPATH */
- if (!nlspath || !*nlspath) {
+ if (nlspath == NULL || !*nlspath) {
/* no NLSPATH is defined in the environ */
if ((*cur_locale == 'C') && (*(cur_locale + 1) == '\0')) {
/*
* If C locale,
* return the original msgid immediately.
*/
- free(cur_locale);
DFLTMSG(result, msgid1, msgid2, n, plural);
return (result);
}
@@ -173,10 +145,9 @@ _real_gettext_u(const char *domain,
msgloc = setlocale(LC_MESSAGES, NULL);
ret = process_nlspath(cur_domain, msgloc,
- (const char *)nlspath, &cur_binding);
+ (const char *)nlspath, &cur_binding);
if (ret == -1) {
/* error occurred */
- free(cur_locale);
DFLTMSG(result, msgid1, msgid2, n, plural);
return (result);
} else if (ret == 0) {
@@ -185,9 +156,8 @@ _real_gettext_u(const char *domain,
}
cur_domain_binding = _real_bindtextdomain_u(cur_domain,
- NULL, TP_BINDING);
- if (!cur_domain_binding) {
- free(cur_locale);
+ NULL, TP_BINDING);
+ if (cur_domain_binding == NULL) {
DFLTMSG(result, msgid1, msgid2, n, plural);
return (result);
}
@@ -199,12 +169,11 @@ _real_gettext_u(const char *domain,
mp->binding = cur_domain_binding;
mp->locale = cur_locale;
mp->language = language;
- mp->locale_len = cur_locale_len;
mp->domain_len = cur_domain_len;
mp->n = n;
mp->category = category;
mp->plural = plural;
- mp->hash_locale = hash_locale;
+ mp->hash_domain = hash_domain;
/*
* Spec1170 requires that we use NLSPATH if it's defined, to
@@ -225,15 +194,14 @@ _real_gettext_u(const char *domain,
/*
* First, examine NLSPATH
*/
- bptr = binding;
if (nlspath) {
/*
* NLSPATH binding has been successfully built
*/
#ifdef GETTEXT_DEBUG
- (void) printf("************************** examining NLSPATH\n");
- (void) printf(" cur_binding: \"%s\"\n",
- cur_binding ? cur_binding : "(null)");
+ gprintf(0, "************************** examining NLSPATH\n");
+ gprintf(0, " cur_binding: \"%s\"\n",
+ cur_binding ? cur_binding : "(null)");
#endif
mp->nlsp = 1;
@@ -249,26 +217,23 @@ _real_gettext_u(const char *domain,
cur_binding++;
if (cblen >= MAXPATHLEN) {
/* cur_binding too long */
- free(cur_locale);
DFLTMSG(result, msgid1, msgid2, n, plural);
return (result);
}
- (void) memcpy(bptr, cb, cblen);
- *(bptr + cblen) = '\0';
- (void) memcpy(mp->msgfile, bptr, cblen + 1);
- mp->msgfile_len = cblen;
+ (void) memcpy(mp->msgfile, cb, cblen);
+ *(mp->msgfile + cblen) = '\0';
+
#ifdef GETTEXT_DEBUG
- (void) printf("*******************"
- "********************* \n");
- (void) printf(" msgfile: \"%s\"\n",
- msgfile ? msgfile : "(null)");
- (void) printf("*******************"
- "********************* \n");
+ gprintf(0, "*******************"
+ "********************* \n");
+ gprintf(0, " msgfile: \"%s\"\n",
+ msgfile ? msgfile : "(null)");
+ gprintf(0, "*******************"
+ "********************* \n");
#endif
- result = handle_mo(cp, mp);
+ result = handle_mo(mp);
if (result) {
- free(cur_locale);
return (result);
}
}
@@ -281,21 +246,16 @@ _real_gettext_u(const char *domain,
*/
if (language) {
char *ret_msg;
- ret_msg = handle_lang(cp, mp);
+ ret_msg = handle_lang(mp);
if (ret_msg != NULL) {
- /*
- * GNU MO found
- */
- free(cur_locale);
+ /* valid msg found in GNU MO */
return (ret_msg);
}
/*
- * handle_lang() may have overridden
- * locale and hash_locale
+ * handle_lang() may have overridden locale
*/
mp->locale = cur_locale;
- mp->locale_len = cur_locale_len;
- mp->hash_locale = hash_locale;
+ mp->status = 0;
}
/*
@@ -305,13 +265,11 @@ _real_gettext_u(const char *domain,
*mp->msgfile = '\0';
#endif
if (mk_msgfile(mp) == NULL) {
- free(cur_locale);
DFLTMSG(result, msgid1, msgid2, n, plural);
return (result);
}
- result = handle_mo(cp, mp);
- free(cur_locale);
+ result = handle_mo(mp);
if (result) {
return (result);
}
@@ -320,11 +278,11 @@ _real_gettext_u(const char *domain,
} /* _real_gettext_u */
#define ALLFREE \
- free_all(nlstmp, nnp, pathname, ppaths, lang, cacheline, cnp)
+ free_all(nlstmp, nnp, pathname, ppaths, lang)
static void
free_all(Nlstmp *nlstmp, Nls_node *nnp, char *pathname,
- char *ppaths, char *lang, int cacheline, Cache_node *cnp)
+ char *ppaths, char *lang)
{
Nlstmp *tp, *tq;
@@ -344,8 +302,6 @@ free_all(Nlstmp *nlstmp, Nls_node *nnp, char *pathname,
free(ppaths);
if (lang)
free(lang);
- if (!cacheline)
- free(cnp);
free(nnp);
}
@@ -364,7 +320,7 @@ free_all(Nlstmp *nlstmp, Nls_node *nnp, char *pathname,
*/
static int
process_nlspath(const char *cur_domain, const char *cur_msgloc,
- const char *nlspath, char **binding)
+ const char *nlspath, char **binding)
{
char *s; /* generic string ptr */
char *territory; /* our current territory element */
@@ -374,112 +330,70 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
char *lang = NULL; /* our current language element */
char *ppaths = NULL; /* ptr to all of the templates */
char *pathname = NULL; /* the full pathname to the file */
- unsigned int hashid;
size_t nlspath_len, domain_len, locale_len, path_len;
size_t ppaths_len = 0;
- int cacheline = 0;
Nlstmp *nlstmp = NULL;
Nlstmp *pnlstmp, *qnlstmp;
- Cache_node *cnp;
- Nls_node *cur_nls, *nnp = NULL;
+ Nls_node *cur_nls, *nnp;
Gettext_t *gt = global_gt;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** process_nlspath(%s, %s, "
- "%s, 0x%p)\n", cur_domain,
+ gprintf(0, "*************** process_nlspath(%s, %s, "
+ "%s, 0x%p)\n", cur_domain,
cur_msgloc, nlspath, (void *)binding);
#endif
cur_nls = gt->c_n_node;
if (cur_nls &&
- (strcmp(cur_nls->domain, cur_domain) == 0 &&
- strcmp(cur_nls->locale, cur_msgloc) == 0 &&
- strcmp(cur_nls->nlspath, nlspath) == 0)) {
+ (strcmp(cur_nls->domain, cur_domain) == 0 &&
+ strcmp(cur_nls->locale, cur_msgloc) == 0 &&
+ strcmp(cur_nls->nlspath, nlspath) == 0)) {
*binding = cur_nls->ppaths;
return (1);
}
- hashid = get_hashid(cur_msgloc, NULL);
-
- cnp = gt->c_node;
- while (cnp) {
- if (cnp->hashid == hashid) {
- nnp = cnp->n_node;
- cacheline = 1;
- while (nnp) {
- if (strcmp(nnp->locale, cur_msgloc) == 0 &&
- strcmp(nnp->domain, cur_domain) == 0 &&
- strcmp(nnp->nlspath, nlspath) == 0) {
- gt->c_n_node = nnp;
- *binding = nnp->ppaths;
- return (1);
- }
- nnp = nnp->next;
- }
- break;
- } else {
- cnp = cnp->next;
+ nnp = gt->n_node;
+ while (nnp) {
+ if (strcmp(nnp->domain, cur_domain) == 0 &&
+ strcmp(nnp->locale, cur_msgloc) == 0 &&
+ strcmp(nnp->nlspath, nlspath) == 0) {
+ /* found */
+ gt->c_n_node = nnp;
+ *binding = nnp->ppaths;
+ return (1);
}
+ nnp = nnp->next;
}
+ /* not found */
- if (cacheline) {
- nnp = (Nls_node *)calloc(1, sizeof (Nls_node));
- if (!nnp) {
- ALLFREE;
- return (-1);
- }
- } else {
- cnp = (Cache_node *)calloc(1, sizeof (Cache_node));
- if (!cnp) {
- ALLFREE;
- return (-1);
- }
- cnp->hashid = hashid;
- nnp = (Nls_node *)calloc(1, sizeof (Nls_node));
- if (!nnp) {
- ALLFREE;
- return (-1);
- }
- cnp->n_node = nnp;
- cnp->n_last = nnp;
+ nnp = calloc(1, sizeof (Nls_node));
+ if (nnp == NULL) {
+ ALLFREE;
+ return (-1);
}
nlspath_len = strlen(nlspath);
locale_len = strlen(cur_msgloc);
domain_len = strlen(cur_domain);
- /*
- * nlspath_len, locale_len, and domain_len
- * are including a null termination.
- */
- nlspath_len++;
- locale_len++;
- domain_len++;
-
- lang = NULL;
- territory = NULL;
- codeset = NULL;
-
- if (cur_msgloc) {
- lang = s = strdup(cur_msgloc);
- if (lang == NULL) {
- ALLFREE;
- return (-1);
- }
- s1 = s2 = NULL;
- while (s && *s) {
- if (*s == '_') {
- s1 = s;
- *s1++ = '\0';
- } else if (*s == '.') {
- s2 = s;
- *s2++ = '\0';
- }
- s++;
+ lang = s = strdup(cur_msgloc);
+ if (lang == NULL) {
+ ALLFREE;
+ return (-1);
+ }
+ s1 = s2 = NULL;
+ while (*s) {
+ if (*s == '_') {
+ s1 = s;
+ *s1++ = '\0';
+ } else if (*s == '.') {
+ s2 = s;
+ *s2++ = '\0';
}
- territory = s1;
- codeset = s2;
+ s++;
}
+ territory = s1;
+ codeset = s2;
/*
* now that we have the name (domain), we first look through NLSPATH,
@@ -496,7 +410,7 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
* if we find one of these characters, we will carry out the
* appropriate substitution.
*/
- pathname = (char *)malloc(MAXPATHLEN);
+ pathname = malloc(MAXPATHLEN);
if (pathname == NULL) {
ALLFREE;
return (-1);
@@ -510,19 +424,21 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
* ":" by "name". replace_nls_option() below
* will handle the subsequent ":"'s.
*/
- pnlstmp = (Nlstmp *)malloc(sizeof (Nlstmp));
- if (!pnlstmp) {
+ pnlstmp = malloc(sizeof (Nlstmp));
+ if (pnlstmp == NULL) {
ALLFREE;
return (-1);
}
(void) memcpy(pnlstmp->pathname, cur_domain,
- domain_len);
- ppaths_len += domain_len;
+ domain_len + 1);
+ pnlstmp->len = domain_len;
+ ppaths_len += domain_len + 1; /* 1 for ':' */
+
pnlstmp->next = NULL;
- if (!nlstmp) {
+ if (nlstmp == NULL) {
nlstmp = pnlstmp;
qnlstmp = pnlstmp;
} else {
@@ -535,7 +451,7 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
}
/* replace Substitution field */
s = replace_nls_option(s, cur_domain, pathname,
- (char *)cur_msgloc, lang, territory, codeset);
+ (char *)cur_msgloc, lang, territory, codeset);
if (s == NULL) {
ALLFREE;
@@ -545,20 +461,21 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
/* if we've found a valid file: */
if (*pathname) {
/* add template to end of chain of pathnames: */
- pnlstmp = (Nlstmp *)malloc(sizeof (Nlstmp));
- if (!pnlstmp) {
+ pnlstmp = malloc(sizeof (Nlstmp));
+ if (pnlstmp == NULL) {
ALLFREE;
return (-1);
}
- path_len = strlen(pathname) + 1;
+ path_len = strlen(pathname);
(void) memcpy(pnlstmp->pathname, pathname,
- path_len);
- ppaths_len += path_len;
+ path_len + 1);
+ pnlstmp->len = path_len;
+ ppaths_len += path_len + 1; /* 1 for ':' */
pnlstmp->next = NULL;
- if (!nlstmp) {
+ if (nlstmp == NULL) {
nlstmp = pnlstmp;
qnlstmp = pnlstmp;
} else {
@@ -576,8 +493,8 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
*/
if (ppaths_len != 0) {
- ppaths = (char *)malloc(ppaths_len + 1);
- if (!ppaths) {
+ ppaths = malloc(ppaths_len + 1);
+ if (ppaths == NULL) {
ALLFREE;
return (-1);
}
@@ -592,60 +509,50 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
* all into a ":" separated string for _bindtextdomain_u()
*/
pnlstmp = nlstmp;
+ s = ppaths;
while (pnlstmp) {
- (void) strcat(ppaths, pnlstmp->pathname);
- (void) strcat(ppaths, ":");
+ (void) memcpy(s, pnlstmp->pathname, pnlstmp->len);
+ s += pnlstmp->len;
+ *s++ = ':';
qnlstmp = pnlstmp->next;
free(pnlstmp);
pnlstmp = qnlstmp;
}
+ *s = '\0';
nlstmp = NULL;
- nnp->domain = (char *)malloc(domain_len);
- if (!nnp->domain) {
+ nnp->domain = malloc(domain_len + 1);
+ if (nnp->domain == NULL) {
ALLFREE;
return (-1);
} else {
- (void) memcpy(nnp->domain, cur_domain, domain_len);
+ (void) memcpy(nnp->domain, cur_domain, domain_len + 1);
}
- nnp->locale = (char *)malloc(locale_len);
- if (!nnp->locale) {
+ nnp->locale = malloc(locale_len + 1);
+ if (nnp->locale == NULL) {
ALLFREE;
return (-1);
} else {
- (void) memcpy(nnp->locale, cur_msgloc, locale_len);
+ (void) memcpy(nnp->locale, cur_msgloc, locale_len + 1);
}
- nnp->nlspath = (char *)malloc(nlspath_len);
- if (!nnp->nlspath) {
+ nnp->nlspath = malloc(nlspath_len + 1);
+ if (nnp->nlspath == NULL) {
ALLFREE;
return (-1);
} else {
- (void) memcpy(nnp->nlspath, nlspath, nlspath_len);
+ (void) memcpy(nnp->nlspath, nlspath, nlspath_len + 1);
}
nnp->ppaths = ppaths;
- nnp->next = NULL;
-
- if (cacheline) {
- if (cnp->n_last)
- cnp->n_last->next = nnp;
- else
- cnp->n_node = nnp;
- cnp->n_last = nnp;
- } else {
- if (gt->c_last)
- gt->c_last->next = cnp;
- else
- gt->c_node = cnp;
- gt->c_last = cnp;
- }
+
+ nnp->next = gt->n_node;
+ gt->n_node = nnp;
gt->c_n_node = nnp;
free(pathname);
free(lang);
#ifdef GETTEXT_DEBUG
- (void) printf("*************** existing process_nlspath "
- "with success\n");
- (void) printf(" binding: \"%s\"\n", ppaths);
+ gprintf(0, "*************** existing process_nlspath with success\n");
+ gprintf(0, " binding: \"%s\"\n", ppaths);
#endif
*binding = ppaths;
return (1);
@@ -658,7 +565,7 @@ process_nlspath(const char *cur_domain, const char *cur_msgloc,
*/
static char *
replace_nls_option(char *s, const char *name, char *pathname,
- char *locale, char *lang, char *territory, char *codeset)
+ char *locale, char *lang, char *territory, char *codeset)
{
char *t, *u;
char *limit;
@@ -692,14 +599,14 @@ replace_nls_option(char *s, const char *name, char *pathname,
if (lang) {
u = lang;
while (*u && (*u != '_') &&
- (t < limit))
+ (t < limit))
*t++ = *u++;
}
} else if (*s == 't') {
if (territory) {
u = territory;
while (*u && (*u != '.') &&
- (t < limit))
+ (t < limit))
*t++ = *u++;
}
} else if (*s == 'c') {
@@ -725,24 +632,25 @@ replace_nls_option(char *s, const char *name, char *pathname,
char *
_real_bindtextdomain_u(const char *domain, const char *binding,
- int type)
+ int type)
{
struct domain_binding *bind, *prev;
Gettext_t *gt = global_gt;
char **binding_addr;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** _real_bindtextdomain_u(%s, %s, %s)\n",
- (domain ? domain : ""),
- (binding ? binding : ""),
- (type == TP_BINDING) ? "TP_BINDING" : "TP_CODESET");
+ gprintf(0, "*************** _real_bindtextdomain_u(\"%s\", "
+ "\"%s\", \"%s\")\n",
+ (domain ? domain : ""),
+ (binding ? binding : ""),
+ (type == TP_BINDING) ? "TP_BINDING" : "TP_CODESET");
#endif
/*
* If domain is a NULL pointer, no change will occur regardless
* of binding value. Just return NULL.
*/
- if (!domain) {
+ if (domain == NULL) {
return (NULL);
}
@@ -764,8 +672,8 @@ _real_bindtextdomain_u(const char *domain, const char *binding,
* Domain found.
*/
binding_addr = (type == TP_BINDING) ? &(bind->binding) :
- &(bind->codeset);
- if (!binding) {
+ &(bind->codeset);
+ if (binding == NULL) {
/*
* if binding is null, then query
*/
@@ -794,7 +702,7 @@ _real_bindtextdomain_u(const char *domain, const char *binding,
* Then add a new node to the end of linked list.
*/
- if ((bind = (Dbinding *)malloc(sizeof (Dbinding))) == NULL) {
+ if ((bind = malloc(sizeof (Dbinding))) == NULL) {
return (NULL);
}
if ((bind->domain = strdup(domain)) == NULL) {
@@ -804,7 +712,7 @@ _real_bindtextdomain_u(const char *domain, const char *binding,
bind->binding = NULL;
bind->codeset = NULL;
binding_addr = (type == TP_BINDING) ? &(bind->binding) :
- &(bind->codeset);
+ &(bind->codeset);
if ((*binding_addr = strdup(binding)) == NULL) {
free(bind->domain);
free(bind);
@@ -850,13 +758,13 @@ _textdomain_u(const char *domain, char *result)
Gettext_t *gt = global_gt;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** _textdomain_u(\"%s\", 0x%p)\n",
- (domain ? domain : ""), (void *)result);
+ gprintf(0, "*************** _textdomain_u(\"%s\", 0x%p)\n",
+ (domain ? domain : ""), (void *)result);
#endif
/* Query is performed for NULL domain pointer */
if (domain == NULL) {
- mini_strcpy(result, CURRENT_DOMAIN(gt));
+ (void) strcpy(result, CURRENT_DOMAIN(gt));
return (result);
}
@@ -865,7 +773,7 @@ _textdomain_u(const char *domain, char *result)
* domain is limited to TEXTDOMAINMAX bytes
* excluding a null termination.
*/
- domain_len = mini_strlen(domain);
+ domain_len = strlen(domain);
if (domain_len > TEXTDOMAINMAX) {
/* too long */
return (NULL);
@@ -885,16 +793,16 @@ _textdomain_u(const char *domain, char *result)
CURRENT_DOMAIN(gt) = (char *)default_domain;
}
} else {
- p = (char *)malloc(domain_len + 1);
- if (!p)
+ p = malloc(domain_len + 1);
+ if (p == NULL)
return (NULL);
- mini_strcpy(p, domain);
+ (void) strcpy(p, domain);
if (CURRENT_DOMAIN(gt) != default_domain)
free(CURRENT_DOMAIN(gt));
CURRENT_DOMAIN(gt) = p;
}
- mini_strcpy(result, CURRENT_DOMAIN(gt));
+ (void) strcpy(result, CURRENT_DOMAIN(gt));
return (result);
} /* _textdomain_u */
@@ -910,16 +818,16 @@ key_2_text(Msg_s_node *messages, const char *key_string)
struct msg_struct *check_msg_list;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** key_2_text(0x%p, \"%s\")\n",
- (void *)messages, key_string ? key_string : "(null)");
- printsunmsg(messages, 0);
+ gprintf(0, "*************** key_2_text(0x%p, \"%s\")\n",
+ (void *)messages, key_string ? key_string : "(null)");
+ printsunmsg(messages, 1);
#endif
check_msg_list = messages->msg_list +
- messages->msg_file_info->msg_mid;
+ messages->msg_file_info->msg_mid;
for (;;) {
msg_id_str = messages->msg_ids +
- check_msg_list->msgid_offset;
+ check_msg_list->msgid_offset;
/*
* To maintain the compatibility with Zeus mo file,
* msg_id's are stored in descending order.
@@ -929,13 +837,13 @@ key_2_text(Msg_s_node *messages, const char *key_string)
*/
val = *(unsigned char *)msg_id_str - kc;
if ((val == 0) &&
- (val = strcmp(msg_id_str, key_string)) == 0) {
+ (val = strcmp(msg_id_str, key_string)) == 0) {
return (messages->msg_strs
- + check_msg_list->msgstr_offset);
+ + check_msg_list->msgstr_offset);
} else if (val < 0) {
if (check_msg_list->less != LEAFINDICATOR) {
check_msg_list = messages->msg_list +
- check_msg_list->less;
+ check_msg_list->less;
continue;
}
return ((char *)key_string);
@@ -943,7 +851,7 @@ key_2_text(Msg_s_node *messages, const char *key_string)
/* val > 0 */
if (check_msg_list->more != LEAFINDICATOR) {
check_msg_list = messages->msg_list +
- check_msg_list->more;
+ check_msg_list->more;
continue;
}
return ((char *)key_string);
@@ -951,15 +859,126 @@ key_2_text(Msg_s_node *messages, const char *key_string)
}
}
+/*
+ * sun_setmsg
+ *
+ * INPUT
+ * mnp - message node
+ * addr - address to the mmapped file
+ * size - size of the file
+ *
+ * RETURN
+ * 0 - either T_SUN_MO or T_ILL_MO has been set
+ * 1 - not a valid sun mo file
+ * -1 - failed
+ */
+static int
+sun_setmsg(Msg_node *mnp, char *addr, size_t size)
+{
+ struct msg_info *sun_header;
+ Msg_s_node *p;
+ uint32_t first_4bytes;
+ int mid, count;
+ int struct_size, struct_size_old;
+ int msg_struct_size;
+
+ if (size < sizeof (struct msg_info)) {
+ /* invalid mo file */
+ mnp->type = T_ILL_MO;
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "********* exiting sun_setmsg\n");
+ printmnp(mnp, 1);
+#endif
+ return (0);
+ }
+
+ first_4bytes = *((uint32_t *)(uintptr_t)addr);
+ if (first_4bytes > INT_MAX) {
+ /*
+ * Not a valid sun mo file
+ */
+ return (1);
+ }
+
+ /* candidate for sun mo */
+
+ sun_header = (struct msg_info *)(uintptr_t)addr;
+ mid = sun_header->msg_mid;
+ count = sun_header->msg_count;
+ msg_struct_size = sun_header->msg_struct_size;
+ struct_size_old = (int)(OLD_MSG_STRUCT_SIZE * count);
+ struct_size = (int)(MSG_STRUCT_SIZE * count);
+
+ if ((((count - 1) / 2) != mid) ||
+ ((msg_struct_size != struct_size_old) &&
+ (msg_struct_size != struct_size))) {
+ /* invalid mo file */
+ mnp->type = T_ILL_MO;
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "********* exiting sun_setmsg\n");
+ printmnp(mnp, 1);
+#endif
+ return (0);
+ }
+ /* valid sun mo file */
+
+ p = malloc(sizeof (Msg_s_node));
+ if (p == NULL) {
+ return (-1);
+ }
+
+ p->msg_file_info = sun_header;
+ p->msg_list = (struct msg_struct *)(uintptr_t)
+ (addr + sizeof (struct msg_info));
+ p->msg_ids = (char *)(addr + sizeof (struct msg_info) +
+ struct_size);
+ p->msg_strs = (char *)(addr + sizeof (struct msg_info) +
+ struct_size + sun_header->str_count_msgid);
+
+ mnp->msg.sunmsg = p;
+ mnp->type = T_SUN_MO;
+#ifdef GETTEXT_DEBUG
+ gprintf(0, "******** exiting sun_setmsg\n");
+ printmnp(mnp, 1);
+#endif
+ return (0);
+}
+
+/*
+ * setmsg
+ *
+ * INPUT
+ * mnp - message node
+ * addr - address to the mmapped file
+ * size - size of the file
+ *
+ * RETURN
+ * 0 - succeeded
+ * -1 - failed
+ */
+static int
+setmsg(Msg_node *mnp, char *addr, size_t size)
+{
+ int ret;
+ if ((ret = sun_setmsg(mnp, addr, size)) <= 0)
+ return (ret);
+
+ return (gnu_setmsg(mnp, addr, size));
+}
+
static char *
-handle_type_mo(struct cache_pack *cp, struct msg_pack *mp)
+handle_type_mo(Msg_node *mnp, struct msg_pack *mp)
{
char *result;
- switch (cp->mnp->type) {
+ switch (mnp->type) {
case T_ILL_MO:
+ /* invalid MO */
return (NULL);
case T_SUN_MO:
+ /* Sun MO found */
+ mp->status |= ST_SUN_MO_FOUND;
+
if (mp->plural) {
/*
* *ngettext is called against
@@ -971,143 +990,115 @@ handle_type_mo(struct cache_pack *cp, struct msg_pack *mp)
result = (char *)mp->msgid2;
return (result);
}
- result = key_2_text(cp->mnp->msg.sunmsg, mp->msgid1);
- if (!cp->mnp->trusted) {
+ result = key_2_text(mnp->msg.sunmsg, mp->msgid1);
+ if (!mnp->trusted) {
result = check_format(mp->msgid1, result, 0);
}
return (result);
case T_GNU_MO:
- if (mp->language) {
- /*
- * LANGUAGE has been set.
- * Failed to find out a valid GNU MO in
- * handle_lang() using LANGUAGE.
- * Now found a valid GNU MO. But, gettext()
- * needs to default-return.
- */
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
+ /* GNU MO found */
+ mp->status |= ST_GNU_MO_FOUND;
+
+ result = gnu_key_2_text(mnp->msg.gnumsg,
+ get_codeset(mp->domain), mp);
+
+ if (result == mp->msgid1 || result == mp->msgid2) {
+ /* no valid msg found */
return (result);
}
- result = gnu_key_2_text(cp->mnp->msg.gnumsg,
- get_codeset(mp->domain), mp);
- if (!cp->mnp->trusted) {
+
+ /* valid msg found */
+ mp->status |= ST_GNU_MSG_FOUND;
+
+ if (!mnp->trusted) {
result = check_format(mp->msgid1, result, 0);
if (result == mp->msgid1) {
DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
+ mp->n, mp->plural);
}
}
return (result);
default:
/* this should never happen */
- return (NULL);
+ DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
+ return (result);
}
/* NOTREACHED */
}
-static char *
-handle_mo(struct cache_pack *cp, struct msg_pack *mp)
+/*
+ * handle_mo() returns NULL if invalid MO found.
+ */
+char *
+handle_mo(struct msg_pack *mp)
{
- int fd, ret;
+ int fd;
char *result;
struct stat64 statbuf;
+ Msg_node *mnp;
Gettext_t *gt = global_gt;
+#define CONNECT_ENTRY \
+ mnp->next = gt->m_node; \
+ gt->m_node = mnp; \
+ gt->c_m_node = mnp
+
#ifdef GETTEXT_DEBUG
- (void) printf("*************** handle_mo(0x%p, 0x%p)\n",
- (void *)cp, (void *)mp);
- printcp(cp, 0);
- printmp(mp, 0);
+ gprintf(0, "*************** handle_mo(0x%p)\n", (void *)mp);
+ printmp(mp, 1);
#endif
- /*
- * At this point, msgfile contains full path for
- * domain.
- * Look up cache entry first. If cache misses,
- * then search domain look-up table.
- */
+ mnp = check_cache(mp);
- ret = check_cache(cp, mp);
-
- if (ret) {
+ if (mnp != NULL) {
/* cache found */
- gt->c_m_node = cp->mnp;
- return (handle_type_mo(cp, mp));
+ return (handle_type_mo(mnp, mp));
}
+
/*
* Valid entry not found in the cache
*/
- fd = nls_safe_open(mp->msgfile, &statbuf, &mp->trusted,
- !mp->nlsp);
+ mnp = calloc(1, sizeof (Msg_node));
+ if (mnp == NULL) {
+ DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
+ return (result);
+ }
+ mnp->hashid = mp->hash_domain;
+ mnp->path = strdup(mp->msgfile);
+ if (mnp->path == NULL) {
+ free(mnp);
+ DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
+ return (result);
+ }
+
+ fd = nls_safe_open(mp->msgfile, &statbuf, &mp->trusted, !mp->nlsp);
if ((fd == -1) || (statbuf.st_size > LONG_MAX)) {
- if (connect_invalid_entry(cp, mp) == -1) {
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- return (result);
- }
+ if (fd != -1)
+ (void) close(fd);
+ mnp->type = T_ILL_MO;
+ CONNECT_ENTRY;
return (NULL);
}
mp->fsz = (size_t)statbuf.st_size;
- mp->addr = mmap(0, mp->fsz, PROT_READ, MAP_SHARED, fd, 0);
+ mp->addr = mmap(NULL, mp->fsz, PROT_READ, MAP_SHARED, fd, 0);
(void) close(fd);
- if (mp->addr == (caddr_t)-1) {
- if (connect_invalid_entry(cp, mp) == -1) {
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- return (result);
- }
- return (NULL);
- }
-
- cp->mnp = create_mnp(mp);
- if (!cp->mnp) {
- free_mnp_mp(cp->mnp, mp);
+ if (mp->addr == MAP_FAILED) {
+ free(mnp->path);
+ free(mnp);
DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
return (result);
}
- if (setmsg(cp->mnp, (char *)mp->addr, mp->fsz) == -1) {
- free_mnp_mp(cp->mnp, mp);
+ if (setmsg(mnp, (char *)mp->addr, mp->fsz) == -1) {
+ free(mnp->path);
+ free(mnp);
(void) munmap(mp->addr, mp->fsz);
DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
return (result);
}
- if (!cp->cacheline) {
- cp->cnp = create_cnp(cp->mnp, mp);
- if (!cp->cnp) {
- free_mnp_mp(cp->mnp, mp);
- (void) munmap(mp->addr, mp->fsz);
- DFLTMSG(result, mp->msgid1, mp->msgid2,
- mp->n, mp->plural);
- return (result);
- }
- }
- cp->mnp->trusted = mp->trusted;
- connect_entry(cp);
-
- return (handle_type_mo(cp, mp));
- /* NOTREACHED */
-}
-
-static void
-mini_strcpy(char *dst, const char *src)
-{
- const char *p = (const char *)src;
- char *q = dst;
- while (*q++ = *p++)
- ;
-}
-
-static size_t
-mini_strlen(const char *str)
-{
- const char *p = (const char *)str;
- size_t len;
+ mnp->trusted = mp->trusted;
+ CONNECT_ENTRY;
- while (*p)
- p++;
- len = (size_t)(p - str);
- return (len);
+ return (handle_type_mo(mnp, mp));
}
diff --git a/usr/src/lib/libc/port/i18n/gettext_util.c b/usr/src/lib/libc/port/i18n/gettext_util.c
index 58d588db90..f8982665af 100644
--- a/usr/src/lib/libc/port/i18n/gettext_util.c
+++ b/usr/src/lib/libc/port/i18n/gettext_util.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -33,9 +33,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
-#include <thread.h>
-#include <synch.h>
-#include <limits.h>
#include <unistd.h>
#include <sys/mman.h>
#include <langinfo.h>
@@ -67,164 +64,6 @@ static const int category_name_len[] = {
11
};
-static int
-setmo(Msg_node *mnp, char *addr, int type)
-{
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** setmo(0x%p, %d)\n",
- (void *)mnp, ret);
- printmnp(mnp, 0);
-#endif
-
- switch (type) {
- case T_ILL_MO:
- /* invalid MO */
- mnp->type = T_ILL_MO;
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** exiting setmo\n");
- printmnp(mnp, 0);
-#endif
- return (0);
- case T_SUN_MO:
- {
- struct msg_info *sun_header;
- int struct_size, info_size, count;
- Msg_s_node *p;
- p = (Msg_s_node *)calloc(1, sizeof (Msg_s_node));
- if (!p) {
- return (-1);
- }
- /* LINTED */
- sun_header = (struct msg_info *)addr;
- count = sun_header->msg_count;
- struct_size = (int)(MSG_STRUCT_SIZE * count);
- info_size = (int)(sizeof (struct msg_info));
- p->msg_file_info = sun_header;
- /* LINTED */
- p->msg_list = (struct msg_struct *)(((char *)addr) +
- info_size);
- p->msg_ids = (char *)(((char *)addr) + info_size +
- struct_size);
- p->msg_strs = (char *)(((char *)addr) + info_size +
- struct_size + sun_header->str_count_msgid);
-
- mnp->msg.sunmsg = p;
- mnp->type = T_SUN_MO;
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** exiting setmo\n");
- printmnp(mnp, 0);
-#endif
- return (0);
- }
- /* NOTREACHED */
- case T_GNU_MO:
- case T_GNU_SWAPPED_MO:
- {
- struct gnu_msg_info *gnu_header;
- Msg_g_node *p;
- p = (Msg_g_node *)calloc(1, sizeof (Msg_g_node));
- if (!p) {
- return (-1);
- }
- /* LINTED */
- gnu_header = (struct gnu_msg_info *)addr;
- p->msg_file_info = gnu_header;
- if (type == T_GNU_SWAPPED_MO) {
- /*
- * This MO file has been created on
- * the reversed endian system
- */
- p->flag |= ST_SWP;
- }
- /* LINTED */
- p->hash_table = (unsigned int *)(((char *)addr) +
- SWAP(p, gnu_header->off_hashtbl));
-
- mnp->msg.gnumsg = p;
- mnp->type = T_GNU_MO;
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** exiting setmo\n");
- printmnp(mnp, 0);
-#endif
- return (0);
- }
- /* NOTREACHED */
- }
- /* NOTREACHED */
- return (0); /* keep gcc happy */
-}
-
-/*
- * setmsg
- *
- * INPUT
- * mnp - message node
- * addr - address to the mmapped file
- * size - size of the file
- *
- * RETURN
- * 0 - succeeded
- * -1 - failed
- */
-int
-setmsg(Msg_node *mnp, char *addr, size_t size)
-{
- struct msg_info *sun_header;
- struct gnu_msg_info *gnu_header;
- unsigned int first_4bytes;
- int mid, count;
- int struct_size, struct_size_old;
- int msg_struct_size;
-
- if (size < sizeof (struct msg_info)) {
- /* invalid mo file */
- return (setmo(mnp, addr, T_ILL_MO));
- }
-
- /* LINTED */
- first_4bytes = *((unsigned int *)addr);
- if (first_4bytes <= INT_MAX) {
- /* candidate for sun mo */
- /* LINTED */
- sun_header = (struct msg_info *)addr;
- mid = sun_header->msg_mid;
- count = sun_header->msg_count;
- msg_struct_size = sun_header->msg_struct_size;
- struct_size_old = (int)(OLD_MSG_STRUCT_SIZE * count);
- struct_size = (int)(MSG_STRUCT_SIZE * count);
-
- if ((((count - 1) / 2) == mid) &&
- ((msg_struct_size == struct_size_old) ||
- (msg_struct_size == struct_size))) {
- /* valid sun mo file */
- return (setmo(mnp, addr, T_SUN_MO));
- }
- /* invalid mo file */
- return (setmo(mnp, addr, T_ILL_MO));
- }
-
- /* checks the GNU MAGIC number */
- if (size < sizeof (struct gnu_msg_info)) {
- /* invalid mo file */
- return (setmo(mnp, addr, T_ILL_MO));
- }
-
- /* LINTED */
- gnu_header = (struct gnu_msg_info *)addr;
- if ((gnu_header->magic == GNU_MAGIC) &&
- (gnu_header->revision == GNU_REVISION)) {
- /* GNU mo file */
- return (setmo(mnp, addr, T_GNU_MO));
- } else if ((gnu_header->magic == GNU_MAGIC_SWAPPED) &&
- (gnu_header->revision == GNU_REVISION_SWAPPED)) {
- /* endian-swapped GNU mo file */
- return (setmo(mnp, addr, T_GNU_SWAPPED_MO));
- }
-
- /* invalid mo file */
- return (setmo(mnp, addr, T_ILL_MO));
-}
-
/*
* mk_msgfile
*
@@ -236,12 +75,10 @@ setmsg(Msg_node *mnp, char *addr, size_t size)
* locale - locale name
* domain - domain name
* category - category
- * locale_len - length of locale name
* domain_len - length of domain name
*
* OUTPUT
* mp->msgfile - pathname to the message file is stored
- * mp->msgfile_len - length of mp->msgfile without null termination
*
* RETURN
* mp->msgfile is returned
@@ -251,19 +88,18 @@ mk_msgfile(struct msg_pack *mp)
{
char *p, *q;
const char *catstr;
- size_t cblen, catlen, totallen;
+ uint32_t cblen, loclen, catlen, totallen;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** mk_msgfile(0x%p)\n",
- (void *)mp);
- printmp(mp, 0);
+ gprintf(0, "*************** mk_msgfile(0x%p)\n", (void *)mp);
+ printmp(mp, 1);
#endif
p = mp->msgfile;
q = mp->binding;
while (*p = *q++)
p++;
- cblen = (size_t)(p - mp->msgfile);
+ cblen = (uint32_t)(p - mp->msgfile);
if (*(p - 1) != '/') {
/*
* if the last character of binding
@@ -277,15 +113,16 @@ mk_msgfile(struct msg_pack *mp)
cblen++;
}
+ loclen = strlen(mp->locale);
catstr = category_name[mp->category];
- catlen = (size_t)category_name_len[mp->category];
+ catlen = (uint32_t)category_name_len[mp->category];
/*
* totallen is the length of the msgfile
* pathname excluding a null termination.
*/
- totallen = cblen + mp->locale_len + 1 + catlen + 1 +
- mp->domain_len + MSGFILESUFFIXLEN;
+ totallen = cblen + loclen + 1 + catlen + 1 +
+ mp->domain_len + MSGFILESUFFIXLEN;
if (totallen >= MAXPATHLEN)
return (NULL);
@@ -297,141 +134,87 @@ mk_msgfile(struct msg_pack *mp)
;
*(p - 1) = '/';
q = mp->domain;
+ while (*p = *q++)
+ p++;
+ q = MSGFILESUFFIX;
while (*p++ = *q++)
;
- *(p - 1) = '.';
- *p = 'm';
- *(p + 1) = 'o';
- *(p + 2) = '\0';
-
- mp->msgfile_len = totallen;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** Exiting mk_msgfile\n");
- (void) printf("mp->msgfile: \"%s\"\n", mp->msgfile);
+ gprintf(0, "*************** Exiting mk_msgfile\n");
+ gprintf(0, "mp->msgfile: \"%s\"\n", mp->msgfile);
#endif
return (mp->msgfile);
}
-
/*
* check_cache
*
* INPUT
- * cp - may use the following members:
- * node_hash - pointer to the Cache_node object having this locale
- *
* mp - may use the following members:
* msgfile - pathname to the message catalog file
- * hash_locale - hash id of this locale
- *
- * OUTPUT
- * cp - may update the following members:
- * mnp - pointer to a Msg_node object
- * cnp - pointer to a Cache_node object
- * node_hash - pointer to the Cache_node object having this locale
- * cacheline - flag to show if the Cache_node for this locale exists
+ * hash_domain - hash id of this domain
*
* RETURN
- * 1 - Entry for this message catalog exists in the cache
- * 0 - Entry for this message catalog doesn't exist in the cache
+ * non-NULL
+ * pointer to the Msg_node object of the current message catalog
+ * found in the cache
+ *
+ * NULL
+ * this message catalog does not exist in the cache
*/
-int
-check_cache(struct cache_pack *cp, struct msg_pack *mp)
+Msg_node *
+check_cache(struct msg_pack *mp)
{
- Msg_node *cur_msg;
+ Msg_node *cur_msg, *mnp;
Gettext_t *gt = global_gt;
#ifdef GETTEXT_DEBUG
- {
- int level = 0;
-
- (void) printf("*************** check_cache(0x%p, 0x%p)\n",
- (void *)cp, (void *)mp);
- printcp(cp, 0);
- printmp(mp, 0);
- }
+ gprintf(0, "*************** check_cache(0x%p)\n", mp);
+ printmp(mp, 1);
#endif
- cur_msg = gt->c_m_node;
+ cur_msg = gt->c_m_node; /* current Msg_node */
if (cur_msg &&
- (strcmp(cur_msg->path, mp->msgfile) == 0)) {
+ cur_msg->hashid == mp->hash_domain &&
+ strcmp(cur_msg->path, mp->msgfile) == 0) {
/*
* msgfile is the same as the previous message file
*/
- cp->mnp = cur_msg;
- cp->cnp = gt->c_node;
- cp->cacheline = 1;
-#ifdef GETTEXT_DEBUG
- (void) printf("************* exiting check_cache\n");
- (void) printf("cache found\n");
- printmnp(cp->mnp, 0);
-#endif
- return (1);
- }
- if (cp->node_hash) {
- /*
- * already cache_node having the same
- * hash id found
- */
- cp->cnp = cp->node_hash;
- cp->mnp = cp->cnp->m_node;
- cp->cacheline = 1;
- while (cp->mnp) {
- if (strcmp(cp->mnp->path, mp->msgfile) == 0) {
#ifdef GETTEXT_DEBUG
- (void) printf("************* exiting check_cache\n");
- (void) printf("cache found\n");
- printmnp(cp->mnp, 0);
+ gprintf(0, "*** cache found\n");
+ gprintf(0, "************* exiting check_cache\n");
+ printmnp(cur_msg, 1);
#endif
- return (1);
- }
- cp->mnp = cp->mnp->next;
- }
-#ifdef GETTEXT_DEBUG
- (void) printf("************* exiting check_cache\n");
- (void) printf("cache not found\n");
-#endif
- return (0);
+ return (cur_msg);
}
- /* search the cache list */
- cp->cnp = gt->c_node;
- cp->mnp = NULL;
- while (cp->cnp) {
- if (cp->cnp->hashid == mp->hash_locale) {
- cp->node_hash = cp->cnp;
- cp->mnp = cp->cnp->m_node;
- cp->cacheline = 1;
- while (cp->mnp) {
- if (strcmp(cp->mnp->path, mp->msgfile) == 0) {
- /*
- * msgfile found in the cache
- */
+ mnp = gt->m_node;
+ while (mnp) {
#ifdef GETTEXT_DEBUG
- (void) printf("************* exiting check_cache\n");
- (void) printf("cache found\n");
- printmnp(cp->mnp, 0);
+ gprintf(0, "========== descending the list\n");
+ gprintf(0, " hashid: %d, hash_domain: %d\n",
+ mnp->hashid, mp->hash_domain);
+ printmnp(mnp, 1);
#endif
- return (1);
- }
- cp->mnp = cp->mnp->next;
- }
+ if (mnp->hashid == mp->hash_domain &&
+ strcmp(mnp->path, mp->msgfile) == 0) {
#ifdef GETTEXT_DEBUG
- (void) printf("************* exiting check_cache\n");
- (void) printf("cache not found\n");
+ gprintf(0, "*** cache found\n");
+ gprintf(0, "******* exiting check_cache\n");
+ printmnp(mnp, 1);
#endif
- return (0);
- } else {
- cp->cnp = cp->cnp->next;
+ gt->c_m_node = mnp;
+ return (mnp);
}
+ mnp = mnp->next;
}
- cp->cacheline = 0;
+
#ifdef GETTEXT_DEBUG
- (void) printf("************* exiting check_cache\n");
- (void) printf("cache not found\n");
+ gprintf(0, "*** cache not found\n");
+ gprintf(0, "******* exiting check_cache\n");
#endif
- return (0);
+ return (NULL);
}
char *
@@ -440,174 +223,41 @@ get_codeset(const char *domain)
char *codeset;
#ifdef GETTEXT_DEBUG
- (void) printf("*************** get_codeset(\"%s\")\n",
- domain ? domain : "(null)");
+ gprintf(0, "*************** get_codeset(\"%s\")\n",
+ domain ? domain : "(null)");
#endif
codeset = _real_bindtextdomain_u(domain, NULL, TP_CODESET);
- if (!codeset) {
+ if (codeset == NULL) {
/* no codeset is bound to this domain */
codeset = nl_langinfo(CODESET);
}
#ifdef GETTEXT_DEBUG
- (void) printf("*************** existing get_codeset(\"%s\")\n",
- domain ? domain : "(null)");
- (void) printf(" = \"%s\"\n", codeset);
+ gprintf(0, "*************** existing get_codeset(\"%s\")\n",
+ domain ? domain : "(null)");
+ gprintf(0, " = \"%s\"\n", codeset);
#endif
return (codeset);
}
-void
-connect_entry(struct cache_pack *cp)
-{
- Gettext_t *gt = global_gt;
-
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** connect_entry(0x%p)\n",
- (void *)cp);
- printcp(cp, 0);
-#endif
-
- if (cp->cacheline) {
- if (cp->cnp->m_last)
- cp->cnp->m_last->next = cp->mnp;
- else
- cp->cnp->m_node = cp->mnp;
- cp->cnp->m_last = cp->mnp;
- } else {
- if (gt->c_last)
- gt->c_last->next = cp->cnp;
- else
- gt->c_node = cp->cnp;
- gt->c_last = cp->cnp;
- }
- gt->c_m_node = cp->mnp;
-}
-
-int
-connect_invalid_entry(struct cache_pack *cp, struct msg_pack *mp)
-{
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** connect_invalid_entry(0x%p, 0x%p)\n",
- (void *)cp, (void *)mp);
- printcp(cp, 0);
- printmp(mp, 0);
-#endif
-
- cp->mnp = create_mnp(mp);
- if (!cp->mnp) {
- return (-1);
- }
-
- if (!cp->cacheline) {
- cp->cnp = create_cnp(cp->mnp, mp);
- if (!cp->cnp) {
- free_mnp_mp(cp->mnp, mp);
- return (-1);
- }
- }
- cp->mnp->type = T_ILL_MO;
- connect_entry(cp);
-
- return (0);
-}
-
-Msg_node *
-create_mnp(struct msg_pack *mp)
-{
- Msg_node *mnp;
- char *s;
- size_t msglen;
-
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** create_mnp(0x%p)\n", (void *)mp);
- printmp(mp, 0);
-#endif
-
- mnp = (Msg_node *)calloc(1, sizeof (Msg_node));
- if (!mnp) {
- return (NULL);
- }
- msglen = mp->msgfile_len;
- s = (char *)malloc(msglen + 1);
- if (!s) {
- free(mnp);
- return (NULL);
- }
- (void) memcpy(s, mp->msgfile, msglen + 1);
- mnp->path = s;
- return (mnp);
-}
-
-Cache_node *
-create_cnp(Msg_node *mnp, struct msg_pack *mp)
-{
- Cache_node *cnp;
-
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** create_cnp(0x%p, 0x%p)\n",
- (void *)mnp, (void *)mp);
- printmnp(mnp, 0);
- printmp(mp, 0);
-#endif
-
- cnp = (Cache_node *)calloc(1, sizeof (Cache_node));
- if (!cnp) {
- return (NULL);
- }
- cnp->hashid = mp->hash_locale;
- cnp->m_node = mnp;
- cnp->m_last = mnp;
-
- return (cnp);
-}
-
-void
-free_mnp_mp(Msg_node *mnp, struct msg_pack *mp)
-{
-#ifdef GETTEXT_DEBUG
- (void) printf("*************** free_mnp_mp(0x%p, 0x%p)\n",
- (void *)mnp, (void *)mp);
- printmnp(mnp, 0);
- printmp(mp, 0);
-#endif
-
- if (mnp) {
- if (mnp->path)
- free(mnp->path);
- switch (mnp->type) {
- case T_SUN_MO:
- free(mnp->msg.sunmsg);
- break;
- case T_GNU_MO:
- free(mnp->msg.gnumsg);
- break;
- }
- free(mnp);
- }
- if (mp->addr != (caddr_t)-1) {
- (void) munmap(mp->addr, mp->fsz);
- }
-}
-
/*
- * get_hashid
+ * get_hashid (hashpjw)
*
* Calculates the hash value from the specified string.
* Actual hashid will be mod(hash value, PRIME_NUMBER).
*
- * hashpjw
* Ref: Compilers - Principles, Techniques, and Tools
* Aho, Sethi, and Ullman
*/
-unsigned int
-get_hashid(const char *str, size_t *len)
+uint32_t
+get_hashid(const char *str, uint32_t *len)
{
- const char *p;
- unsigned int h = 0, g;
+ const unsigned char *p = (unsigned char *)str;
+ uint32_t h = 0;
+ uint32_t g;
- for (p = str; *p; p++) {
+ for (; *p; p++) {
h = (h << 4) + *p;
g = h & 0xf0000000;
if (g) {
@@ -615,22 +265,117 @@ get_hashid(const char *str, size_t *len)
h = h ^ g;
}
}
+
if (len)
- *len = (size_t)(p - str);
+ *len = (uint32_t)(p - (unsigned char *)str);
return (h);
}
-unsigned int
-doswap32(unsigned int n)
+uint32_t
+doswap32(uint32_t n)
{
- unsigned int r;
+ uint32_t r;
r = (n << 24) | ((n & 0xff00) << 8) |
- ((n >> 8) & 0xff00) | (n >> 24);
+ ((n >> 8) & 0xff00) | (n >> 24);
return (r);
}
#ifdef GETTEXT_DEBUG
+static uint32_t
+search_msg(Msg_g_node *p, const char *id, uint32_t hash_val,
+ struct gnu_msg_ent *m)
+{
+ char *base = (char *)p->msg_file_info;
+ uint32_t hash_size, num_of_str, i, idx, inc;
+ char *ms;
+
+ num_of_str = p->num_of_str;
+ hash_size = p->hash_size;
+ idx = hash_val % hash_size;
+ inc = 1 + (hash_val % (hash_size - 2));
+
+ while ((i = p->hash_table[idx]) != 0) {
+ ms = (i <= num_of_str) ?
+ base + SWAP(p, m[i-1].offset) :
+ p->mchunk + p->d_msg[MSGID][i-num_of_str-1].offset;
+ if (strcmp(id, ms) == 0) {
+ /* found */
+ return (i);
+ }
+ idx = (idx + inc) % hash_size;
+ }
+ /* not found */
+ return (0);
+}
+
+void
+print_rev1_info(Msg_g_node *p)
+{
+ char *base = (char *)p->msg_file_info;
+ struct gnu_msg_info *header = p->msg_file_info;
+ struct gnu_msg_ent *m;
+ uint32_t hv, hidx;
+ char *ms;
+ enum gnu_msgidstr v;
+ int x;
+
+#ifdef GETTEXT_DEBUG_DYMMSG
+ gprintf(0, "******** dynamic msgid/msgstr\n");
+ for (v = MSGID; v <= MSGSTR; v++) {
+ for (x = 0; x < p->num_of_d_str; x++) {
+ gprintf(0, "len: %u\n", p->d_msg[v][x].len);
+ gprintf(0, "str: \"%s\"\n",
+ p->mchunk + p->d_msg[v][x].offset);
+ }
+ }
+#endif
+#ifdef GETTEXT_DEBUG_HASHTBL
+ gprintf(0, "******** dynamic hash table\n");
+ for (x = 0; x < p->hash_size; x++) {
+ gprintf(0, "%d: %u\n", x, p->hash_table[x]);
+ }
+#endif
+#ifdef GETTEXT_DEBUG_CHECK_STMSGID
+ gprintf(0, "******** sanity check of static msgid\n");
+ m = (struct gnu_msg_ent *)(uintptr_t)
+ (base + SWAP(p, header->off_msgid_tbl));
+ for (x = 0; x < p->num_of_str; x++) {
+ ms = base + SWAP(p, m[x].offset);
+ gprintf(0, "\"%s\"\n", ms);
+ hv = get_hashid(ms, NULL);
+ hidx = search_msg(p, ms, hv, m);
+ if (hidx == 0) {
+ gprintf(0,
+ "failed to find this msg in the hash table\n");
+ } else {
+ if (hidx != x + 1) {
+ gprintf(0, "hash table mismatch\n");
+ }
+ }
+ }
+#endif
+#ifdef GETTEXT_DEBUG_CHECK_DYMMSGID
+ gprintf(0, "******* sanity check of dynamic msgid\n");
+ m = (struct gnu_msg_ent *)(uintptr_t)
+ (base + SWAP(p, header->off_msgid_tbl));
+ for (x = 0; x < p->num_of_d_str; x++) {
+ ms = p->mchunk + p->d_msg[MSGID][x].offset;
+ gprintf(0, "\"%s\"\n", ms);
+ hv = get_hashid(ms, NULL);
+ hidx = search_msg(p, ms, hv, m);
+ if (hidx == 0) {
+ gprintf(0,
+ "failed to find this msg in the hash table\n");
+ } else {
+ if (hidx != x + p->num_of_str + 1) {
+ gprintf(0, "hash table mismatch\n");
+ }
+ }
+ }
+#endif
+}
+
void
gprintf(int level, const char *format, ...)
{
@@ -638,11 +383,13 @@ gprintf(int level, const char *format, ...)
va_start(ap, format);
- while (level-- >= 0) {
+ while (level-- > 0) {
(void) fputs(" ", stdout);
}
(void) vprintf(format, ap);
va_end(ap);
+
+ (void) fflush(stdout);
}
void
@@ -651,19 +398,19 @@ printlist(void)
struct domain_binding *ppp;
Gettext_t *gt = global_gt;
- (void) printf("=== Printing default list and regural list\n");
- (void) printf(" Default domain=<%s>, binding=<%s>\n",
+ gprintf(0, "=== Printing default list and regural list\n");
+ gprintf(0, " Default domain=<%s>, binding=<%s>\n",
DEFAULT_DOMAIN, defaultbind);
ppp = FIRSTBIND(gt);
while (ppp) {
- (void) printf(
- " domain=<%s>, binding=<%s>, codeset=<%s>\n",
+ gprintf(0, " domain=<%s>, binding=<%s>, codeset=<%s>\n",
ppp->domain ? ppp->domain : "(null)",
- ppp->binding ? ppp->binding : "(null)",
- ppp->codeset ? ppp->codeset : "(null)");
+ ppp->binding ? ppp->binding : "(null)",
+ ppp->codeset ? ppp->codeset : "(null)");
ppp = ppp->next;
}
+ (void) fflush(stdout);
}
void
@@ -671,27 +418,30 @@ printmp(struct msg_pack *mp, int level)
{
gprintf(level, "=== mp ===\n");
gprintf(level, " msgid1: \"%s\"\n",
- mp->msgid1 ? mp->msgid1 : "(null)");
+ mp->msgid1 ? mp->msgid1 : "(null)");
gprintf(level, " msgid2: \"%s\"\n",
- mp->msgid2 ? mp->msgid2 : "(null)");
- gprintf(level, " n: %d\n", mp->n);
- gprintf(level, " plural: %d\n", mp->plural);
- gprintf(level, " category: \"%s\"\n",
- category_name[mp->category]);
+ mp->msgid2 ? mp->msgid2 : "(null)");
+ gprintf(level, " msgfile: \"%s\"\n",
+ mp->msgfile ? mp->msgfile : "(null)");
gprintf(level, " domain: \"%s\"\n",
- mp->domain ? mp->domain : "(null)");
+ mp->domain ? mp->domain : "(null)");
gprintf(level, " binding: \"%s\"\n",
- mp->binding ? mp->binding : "(null)");
- gprintf(level, " msgfile: \"%s\"\n",
- mp->msgfile ? mp->msgfile : "(null)");
+ mp->binding ? mp->binding : "(null)");
gprintf(level, " locale: \"%s\"\n",
- mp->locale ? mp->locale : "(null)");
+ mp->locale ? mp->locale : "(null)");
gprintf(level, " language: \"%s\"\n",
- mp->language ? mp->language : "(null)");
- gprintf(level, " hash_locale: %d\n", mp->hash_locale);
+ mp->language ? mp->language : "(null)");
gprintf(level, " addr: 0x%p\n", mp->addr);
gprintf(level, " fsz: %d\n", mp->fsz);
+ gprintf(level, " hash_domain: %d\n", mp->hash_domain);
+ gprintf(level, " domain_len: %d\n", mp->domain_len);
+ gprintf(level, " n: %d\n", mp->n);
+ gprintf(level, " category: \"%s\"\n",
+ category_name[mp->category]);
+ gprintf(level, " plural: %d\n", mp->plural);
+ gprintf(level, " nlsp: %d\n", mp->nlsp);
gprintf(level, " trusted: %d\n", mp->trusted);
+ gprintf(level, " status: %d\n", mp->status);
}
void
@@ -699,73 +449,94 @@ printsunmsg(Msg_s_node *smnp, int level)
{
gprintf(level, "=== sunmsg ===\n");
gprintf(level, " msg_file_info: 0x%p\n",
- (void *)smnp->msg_file_info);
+ (void *)smnp->msg_file_info);
gprintf(level, " msg_mid: %d\n",
- smnp->msg_file_info->msg_mid);
+ smnp->msg_file_info->msg_mid);
gprintf(level, " msg_count: %d\n",
- smnp->msg_file_info->msg_count);
+ smnp->msg_file_info->msg_count);
gprintf(level, " str_count_msgid: %d\n",
- smnp->msg_file_info->str_count_msgid);
+ smnp->msg_file_info->str_count_msgid);
gprintf(level, " str_count_msgstr: %d\n",
- smnp->msg_file_info->str_count_msgstr);
+ smnp->msg_file_info->str_count_msgstr);
gprintf(level, " msg_struct_size: %d\n",
- smnp->msg_file_info->msg_struct_size);
+ smnp->msg_file_info->msg_struct_size);
gprintf(level, " msg_list: 0x%p\n",
- (void *)smnp->msg_list);
+ (void *)smnp->msg_list);
gprintf(level, " msg_ids: 0x%p\n",
- (void *)smnp->msg_ids);
+ (void *)smnp->msg_ids);
gprintf(level, " msg_strs: 0x%p\n",
- (void *)smnp->msg_strs);
+ (void *)smnp->msg_strs);
}
void
printgnumsg(Msg_g_node *gmnp, int level)
{
gprintf(level, "=== gnumsg ===\n");
- gprintf(level, " msg_file_info: 0x%p\n",
- (void *)gmnp->msg_file_info);
+ gprintf(level, " msg_file_info: 0x%p\n", gmnp->msg_file_info);
gprintf(level, " magic: 0x%x\n",
- gmnp->msg_file_info->magic);
+ gmnp->msg_file_info->magic);
gprintf(level, " revision: %d\n",
- SWAP(gmnp, gmnp->msg_file_info->revision));
+ SWAP(gmnp, gmnp->msg_file_info->revision));
gprintf(level, " num_of_str: %d\n",
- SWAP(gmnp, gmnp->msg_file_info->num_of_str));
+ SWAP(gmnp, gmnp->msg_file_info->num_of_str));
gprintf(level, " off_msgid_tbl: %d\n",
- SWAP(gmnp, gmnp->msg_file_info->off_msgid_tbl));
+ SWAP(gmnp, gmnp->msg_file_info->off_msgid_tbl));
gprintf(level, " off_msgstr_tbl: %d\n",
- SWAP(gmnp, gmnp->msg_file_info->off_msgstr_tbl));
+ SWAP(gmnp, gmnp->msg_file_info->off_msgstr_tbl));
gprintf(level, " sz_hashtbl: %d\n",
- SWAP(gmnp, gmnp->msg_file_info->sz_hashtbl));
+ SWAP(gmnp, gmnp->msg_file_info->sz_hashtbl));
gprintf(level, " off_hashtbl: %d\n",
- SWAP(gmnp, gmnp->msg_file_info->off_hashtbl));
- gprintf(level, " hash_table: 0x%p\n",
- (void *)gmnp->hash_table);
- gprintf(level, " header_flag: %08x\n",
- gmnp->header_flag);
+ SWAP(gmnp, gmnp->msg_file_info->off_hashtbl));
+ if (gmnp->flag & ST_REV1) {
+ struct gnu_msg_rev1_info *a =
+ (struct gnu_msg_rev1_info *)(uintptr_t)
+ ((char *)gmnp->msg_file_info +
+ sizeof (struct gnu_msg_info));
+ gprintf(level, " num_of_dynamic_macro: %d\n",
+ SWAP(gmnp, a->num_of_dynamic_macro));
+ gprintf(level, " off_dynamic_macro: %d\n",
+ SWAP(gmnp, a->off_dynamic_macro));
+ gprintf(level, " num_of_dynamic_str: %d\n",
+ SWAP(gmnp, a->num_of_dynamic_str));
+ gprintf(level, " off_dynamic_msgid_tbl: %d\n",
+ SWAP(gmnp, a->off_dynamic_msgid_tbl));
+ gprintf(level, " off_dynamic_msgstr_tbl: %d\n",
+ SWAP(gmnp, a->off_dynamic_msgstr_tbl));
+ }
+ gprintf(level, " fsize: %lu\n", gmnp->fsize);
+ gprintf(level, " flag: %08x\n", gmnp->flag);
+ gprintf(level, " num_of_str: %u\n", gmnp->num_of_str);
+ gprintf(level, " num_of_d_str: %u\n", gmnp->num_of_d_str);
+ gprintf(level, " hash_size: %u\n", gmnp->hash_size);
+ gprintf(level, " hash_table: 0x%p\n", (void *)gmnp->hash_table);
+ gprintf(level, " d_msgid: 0x%p\n", (void *)gmnp->d_msg[MSGID]);
+ gprintf(level, " d_msgstr: 0x%p\n", (void *)gmnp->d_msg[MSGSTR]);
+ gprintf(level, " mchunk: 0x%p\n", (void *)gmnp->mchunk);
+
gprintf(level, " src_encoding: \"%s\"\n",
- gmnp->src_encoding ? gmnp->src_encoding : "(null)");
+ gmnp->src_encoding ? gmnp->src_encoding : "(null)");
gprintf(level, " dst_encoding: \"%s\"\n",
- gmnp->dst_encoding ? gmnp->dst_encoding : "(null)");
+ gmnp->dst_encoding ? gmnp->dst_encoding : "(null)");
gprintf(level, " nplurals: %d\n",
- gmnp->nplurals);
+ gmnp->nplurals);
gprintf(level, " plural: 0x%p\n",
- (void *)gmnp->plural);
+ (void *)gmnp->plural);
if (gmnp->plural)
printexpr(gmnp->plural, level+1);
gprintf(level, " fd: 0x%p\n", (void *)gmnp->fd);
gprintf(level, " conv_msgstr: 0x%p\n",
- (void *)gmnp->conv_msgstr);
+ (void *)gmnp->conv_msgstr);
}
void
printexpr(struct expr *e, int level)
{
static const char *op_name[] = {
- "NULL", "INIT", "EXP",
- "NUM", "VAR", "?", ":", "||",
- "&&", "==", "!=", ">", "<",
- ">=", "<=", "+", "-", "*", "/",
- "%", "!", "(", ")", "ERR"
+ "NULL", "INIT", "EXP",
+ "NUM", "VAR", "?", ":", "||",
+ "&&", "==", "!=", ">", "<",
+ ">=", "<=", "+", "-", "*", "/",
+ "%", "!", "(", ")", "ERR"
};
switch (GETOPNUM(e->op)) {
case 0:
@@ -803,15 +574,16 @@ printmnp(Msg_node *mnp, int level)
{
gprintf(level, "=== mnp ===\n");
+ gprintf(level, " hashid: %d\n", mnp->hashid);
gprintf(level, " type: \"%s\"\n",
- mnp->type == T_ILL_MO ? "T_ILL_MO" :
- mnp->type == T_SUN_MO ? "T_SUN_MO" :
- mnp->type == T_GNU_MO ? "T_GNU_MO" :
- "UNKNOWN TYPE");
+ mnp->type == T_ILL_MO ? "T_ILL_MO" :
+ mnp->type == T_SUN_MO ? "T_SUN_MO" :
+ mnp->type == T_GNU_MO ? "T_GNU_MO" :
+ "UNKNOWN TYPE");
gprintf(level, " path: \"%s\"\n",
- mnp->path ? mnp->path : "(null)");
+ mnp->path ? mnp->path : "(null)");
gprintf(level, " msg_file_trusted: %d\n",
- mnp->trusted);
+ mnp->trusted);
if (mnp->type == T_SUN_MO)
printsunmsg(mnp->msg.sunmsg, level+1);
else if (mnp->type == T_GNU_MO)
@@ -820,34 +592,58 @@ printmnp(Msg_node *mnp, int level)
}
void
-printcnp(Cache_node *cnp, int level)
+printnls(Nls_node *n, int level)
{
- gprintf(level, "=== cnp ===\n");
-
- gprintf(level, " hashid: %d\n", cnp->hashid);
- gprintf(level, " m_node: 0x%p\n", (void *)cnp->m_node);
- if (cnp->m_node)
- printmnp(cnp->m_node, level+1);
- gprintf(level, " m_last: 0x%p\n", (void *)cnp->m_last);
- if (cnp->m_last)
- printmnp(cnp->m_last, level+1);
- gprintf(level, " n_node: 0x%p\n", (void *)cnp->n_node);
- gprintf(level, " next: 0x%p\n", (void *)cnp->next);
+ gprintf(level, "=== nls ===\n");
+ gprintf(level, " domain: \"%s\"\n", n->domain ? n->domain : "NULL");
+ gprintf(level, " locale: \"%s\"\n", n->locale ? n->locale : "NULL");
+ gprintf(level, " nlspath: \"%s\"\n", n->nlspath ? n->nlspath :
+ "NULL");
+ gprintf(level, " next: 0x%p\n", n->next);
}
void
-printcp(struct cache_pack *cp, int level)
+printdbind(Dbinding *d, int level)
{
- gprintf(level, "=== cp ===\n");
- gprintf(level, " cacheline: %d\n", cp->cacheline);
- gprintf(level, " mnp: 0x%p\n", (void *)cp->mnp);
- if (cp->mnp)
- printmnp(cp->mnp, level+1);
- gprintf(level, " cnp: 0x%p\n", (void *)cp->cnp);
- if (cp->cnp)
- printcnp(cp->cnp, level+1);
- gprintf(level, " node_hash: 0x%p\n", (void *)cp->node_hash);
- if (cp->node_hash)
- printcnp(cp->node_hash, level+1);
+ gprintf(level, "=== dbind ===\n");
+ gprintf(level, " domain: \"%s\"\n", d->domain ? d->domain : "NULL");
+ gprintf(level, " binding: \"%s\"\n", d->binding ? d->binding :
+ "NULL");
+ gprintf(level, " codeset: \"%s\"\n", d->codeset ? d->codeset :
+ "NULL");
+ gprintf(level, " next: 0x%p\n", d->next);
}
+
+void
+printgt(Gettext_t *gt, int level)
+{
+ gprintf(level, "=== gt ===\n");
+ gprintf(level, " cur_domain: \"%s\"\n", gt->cur_domain);
+ if (gt->dbind) {
+ printdbind(gt->dbind, level+1);
+ } else {
+ gprintf(level, " dbind: NULL\n");
+ }
+ if (gt->m_node) {
+ printmnp(gt->m_node, level + 1);
+ } else {
+ gprintf(level, " m_node: NULL\n");
+ }
+ if (gt->n_node) {
+ printnls(gt->n_node, level + 1);
+ } else {
+ gprintf(level, " n_node: NULL\n");
+ }
+ if (gt->c_m_node) {
+ printmnp(gt->c_m_node, level + 1);
+ } else {
+ gprintf(level, " c_m_node: NULL\n");
+ }
+ if (gt->c_n_node) {
+ printnls(gt->c_n_node, level + 1);
+ } else {
+ gprintf(level, " c_n_node: NULL\n");
+ }
+}
+
#endif
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 9c4a04b8a7..54c8ad230a 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -33,6 +33,9 @@
#
SUNW_1.23 { # SunOS 5.11 (Solaris 11)
+ global:
+ _nl_domain_bindings;
+ _nl_msg_cat_cntr;
protected:
addrtosymstr;
aio_cancel;