1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "gnu_msgfmt.h" 30 #include "../../lib/libc/inc/msgfmt.h" 31 32 static unsigned int 33 doswap(unsigned int n) 34 { 35 unsigned int r; 36 37 r = (n << 24) | ((n & 0xff00) << 8) | 38 ((n >> 8) & 0xff00) | (n >> 24); 39 return (r); 40 } 41 42 struct messages * 43 search_msg(struct catalog *p, const char *id, unsigned int hash_val) 44 { 45 unsigned int i, idx, inc; 46 struct messages *m; 47 48 idx = hash_val % p->thash_size; 49 inc = 1 + (hash_val % (p->thash_size - 2)); 50 if (!p->thash[idx]) 51 return (NULL); 52 53 m = p->msg; 54 for (m = p->msg; (i = p->thash[idx]) != 0; 55 idx = (idx + inc) % p->thash_size) { 56 if (strcmp(m[i - 1].id, id) == 0) { 57 /* found */ 58 return (&m[i - 1]); 59 } 60 } 61 return (NULL); 62 } 63 64 static int 65 msg_cmp(struct messages *m1, struct messages *m2) 66 { 67 return (strcmp(m1->id, m2->id)); 68 } 69 70 void 71 output_all_gnu_mo_files(void) 72 { 73 struct catalog *p, *op; 74 struct messages *m; 75 size_t id_len, str_len, id_off, str_off, ids_top, strs_top; 76 unsigned int *hash_tbl; 77 unsigned int hash_size, off_msgstr_tbl, off_hashtbl; 78 unsigned int num = 0, fnum = 0, unum = 0; 79 unsigned int i, idx; 80 char *ids, *strs; 81 struct msgtbl *id_tbl, *str_tbl; 82 struct gnu_msg_info header; 83 FILE *out; 84 85 p = catalog_head; 86 87 while (p) { 88 num += p->nmsg; 89 fnum += p->fnum; 90 unum += p->unum; 91 92 if (p->header) 93 num--; 94 95 p->msg = (struct messages *)Xrealloc(p->msg, 96 sizeof (struct messages) * p->nmsg); 97 98 free(p->thash); 99 /* 100 * Sort the message array 101 */ 102 qsort(p->msg, p->nmsg, sizeof (struct messages), 103 (int (*)(const void *, const void *))msg_cmp); 104 105 106 hash_size = find_prime(p->nmsg); 107 hash_tbl = (unsigned int *)Xcalloc(hash_size, 108 sizeof (unsigned int)); 109 110 111 /* Setting Header info */ 112 off_msgstr_tbl = sizeof (struct gnu_msg_info) + 113 p->nmsg * sizeof (struct msgtbl); 114 off_hashtbl = off_msgstr_tbl + 115 p->nmsg * sizeof (struct msgtbl); 116 117 header.magic = doswap(GNU_MAGIC); 118 header.revision = doswap(GNU_REVISION); 119 header.num_of_str = doswap(p->nmsg); 120 header.off_msgid_tbl = 121 doswap(sizeof (struct gnu_msg_info)); 122 header.off_msgstr_tbl = doswap(off_msgstr_tbl); 123 header.sz_hashtbl = doswap(hash_size); 124 header.off_hashtbl = doswap(off_hashtbl); 125 126 m = p->msg; 127 128 id_len = 0; 129 str_len = 0; 130 for (i = 0; i < p->nmsg; i++) { 131 id_len += m[i].id_len; 132 str_len += m[i].str_len; 133 } 134 ids = (char *)Xmalloc(id_len); 135 strs = (char *)Xmalloc(str_len); 136 id_tbl = (struct msgtbl *)Xmalloc(sizeof (struct msgtbl) * 137 p->nmsg); 138 str_tbl = (struct msgtbl *)Xmalloc(sizeof (struct msgtbl) * 139 p->nmsg); 140 id_off = 0; 141 str_off = 0; 142 ids_top = off_hashtbl + 143 sizeof (unsigned int) * hash_size; 144 strs_top = ids_top + id_len; 145 for (i = 0; i < p->nmsg; i++) { 146 /* 147 * Set the hash table 148 */ 149 idx = get_hash_index(hash_tbl, m[i].hash, hash_size); 150 hash_tbl[idx] = doswap(i + 1); 151 152 /* 153 * rearrange msgid and msgstr 154 */ 155 id_tbl[i].len = doswap(m[i].id_len - 1); 156 str_tbl[i].len = doswap(m[i].str_len - 1); 157 id_tbl[i].offset = doswap(id_off + ids_top); 158 str_tbl[i].offset = doswap(str_off + strs_top); 159 (void) memcpy(ids + id_off, m[i].id, m[i].id_len); 160 (void) memcpy(strs + str_off, m[i].str, m[i].str_len); 161 id_off += m[i].id_len; 162 str_off += m[i].str_len; 163 free(m[i].id); 164 free(m[i].str); 165 } 166 167 if ((out = fopen(p->fname, "w")) == NULL) { 168 error(gettext(ERR_OPEN_FAILED), p->fname); 169 /* NOTREACHED */ 170 } 171 172 /* writing header */ 173 (void) fwrite(&header, sizeof (struct gnu_msg_info), 174 1, out); 175 176 /* writing msgid offset table */ 177 (void) fwrite(id_tbl, sizeof (struct msgtbl), 178 p->nmsg, out); 179 /* writing msgstr offset table */ 180 (void) fwrite(str_tbl, sizeof (struct msgtbl), 181 p->nmsg, out); 182 /* writing hash table */ 183 (void) fwrite(hash_tbl, sizeof (unsigned int), 184 hash_size, out); 185 /* writing msgid table */ 186 (void) fwrite(ids, id_len, 1, out); 187 /* writing msgstr table */ 188 (void) fwrite(strs, str_len, 1, out); 189 190 (void) fclose(out); 191 free(p->fname); 192 free(p->msg); 193 free(id_tbl); 194 free(str_tbl); 195 free(hash_tbl); 196 free(ids); 197 free(strs); 198 op = p->next; 199 free(p); 200 p = op; 201 } 202 if (verbose_flag) { 203 diag(gettext(DIAG_RESULTS), num, fnum, unum); 204 } 205 } 206