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 #include "gnu_msgfmt.h" 28 #include "../../lib/libc/inc/msgfmt.h" 29 30 static unsigned int 31 doswap(unsigned int n) 32 { 33 unsigned int r; 34 35 r = (n << 24) | ((n & 0xff00) << 8) | 36 ((n >> 8) & 0xff00) | (n >> 24); 37 return (r); 38 } 39 40 struct messages * 41 search_msg(struct catalog *p, const char *id, unsigned int hash_val) 42 { 43 unsigned int i, idx, inc; 44 struct messages *m; 45 46 idx = hash_val % p->thash_size; 47 inc = 1 + (hash_val % (p->thash_size - 2)); 48 if (!p->thash[idx]) 49 return (NULL); 50 51 m = p->msg; 52 for (m = p->msg; (i = p->thash[idx]) != 0; 53 idx = (idx + inc) % p->thash_size) { 54 if (strcmp(m[i - 1].id, id) == 0) { 55 /* found */ 56 return (&m[i - 1]); 57 } 58 } 59 return (NULL); 60 } 61 62 static int 63 msg_cmp(struct messages *m1, struct messages *m2) 64 { 65 return (strcmp(m1->id, m2->id)); 66 } 67 68 void 69 output_all_gnu_mo_files(void) 70 { 71 struct catalog *p, *op; 72 struct messages *m; 73 size_t id_len, str_len, id_off, str_off, ids_top, strs_top; 74 unsigned int *hash_tbl; 75 unsigned int hash_size, off_msgstr_tbl, off_hashtbl; 76 unsigned int num = 0, fnum = 0, unum = 0; 77 unsigned int i, idx; 78 char *ids, *strs; 79 struct msgtbl *id_tbl, *str_tbl; 80 struct gnu_msg_info header; 81 FILE *out; 82 83 p = catalog_head; 84 85 while (p) { 86 num += p->nmsg; 87 fnum += p->fnum; 88 unum += p->unum; 89 90 if (p->header) 91 num--; 92 93 p->msg = (struct messages *)Xrealloc(p->msg, 94 sizeof (struct messages) * p->nmsg); 95 96 free(p->thash); 97 /* 98 * Sort the message array 99 */ 100 qsort(p->msg, p->nmsg, sizeof (struct messages), 101 (int (*)(const void *, const void *))msg_cmp); 102 103 104 hash_size = find_prime(p->nmsg); 105 hash_tbl = (unsigned int *)Xcalloc(hash_size, 106 sizeof (unsigned int)); 107 108 109 /* Setting Header info */ 110 off_msgstr_tbl = sizeof (struct gnu_msg_info) + 111 p->nmsg * sizeof (struct msgtbl); 112 off_hashtbl = off_msgstr_tbl + 113 p->nmsg * sizeof (struct msgtbl); 114 115 header.magic = doswap(GNU_MAGIC); 116 header.revision = doswap(GNU_REVISION); 117 header.num_of_str = doswap(p->nmsg); 118 header.off_msgid_tbl = 119 doswap(sizeof (struct gnu_msg_info)); 120 header.off_msgstr_tbl = doswap(off_msgstr_tbl); 121 header.sz_hashtbl = doswap(hash_size); 122 header.off_hashtbl = doswap(off_hashtbl); 123 124 m = p->msg; 125 126 id_len = 0; 127 str_len = 0; 128 for (i = 0; i < p->nmsg; i++) { 129 id_len += m[i].id_len; 130 str_len += m[i].str_len; 131 } 132 ids = (char *)Xmalloc(id_len); 133 strs = (char *)Xmalloc(str_len); 134 id_tbl = (struct msgtbl *)Xmalloc(sizeof (struct msgtbl) * 135 p->nmsg); 136 str_tbl = (struct msgtbl *)Xmalloc(sizeof (struct msgtbl) * 137 p->nmsg); 138 id_off = 0; 139 str_off = 0; 140 ids_top = off_hashtbl + 141 sizeof (unsigned int) * hash_size; 142 strs_top = ids_top + id_len; 143 for (i = 0; i < p->nmsg; i++) { 144 /* 145 * Set the hash table 146 */ 147 idx = get_hash_index(hash_tbl, m[i].hash, hash_size); 148 hash_tbl[idx] = doswap(i + 1); 149 150 /* 151 * rearrange msgid and msgstr 152 */ 153 id_tbl[i].len = doswap(m[i].id_len - 1); 154 str_tbl[i].len = doswap(m[i].str_len - 1); 155 id_tbl[i].offset = doswap(id_off + ids_top); 156 str_tbl[i].offset = doswap(str_off + strs_top); 157 (void) memcpy(ids + id_off, m[i].id, m[i].id_len); 158 (void) memcpy(strs + str_off, m[i].str, m[i].str_len); 159 id_off += m[i].id_len; 160 str_off += m[i].str_len; 161 free(m[i].id); 162 free(m[i].str); 163 } 164 165 if ((out = fopen(p->fname, "w")) == NULL) { 166 error(gettext(ERR_OPEN_FAILED), p->fname); 167 /* NOTREACHED */ 168 } 169 170 /* writing header */ 171 (void) fwrite(&header, sizeof (struct gnu_msg_info), 172 1, out); 173 174 /* writing msgid offset table */ 175 (void) fwrite(id_tbl, sizeof (struct msgtbl), 176 p->nmsg, out); 177 /* writing msgstr offset table */ 178 (void) fwrite(str_tbl, sizeof (struct msgtbl), 179 p->nmsg, out); 180 /* writing hash table */ 181 (void) fwrite(hash_tbl, sizeof (unsigned int), 182 hash_size, out); 183 /* writing msgid table */ 184 (void) fwrite(ids, id_len, 1, out); 185 /* writing msgstr table */ 186 (void) fwrite(strs, str_len, 1, out); 187 188 (void) fclose(out); 189 free(p->fname); 190 free(p->msg); 191 free(id_tbl); 192 free(str_tbl); 193 free(hash_tbl); 194 free(ids); 195 free(strs); 196 op = p->next; 197 free(p); 198 p = op; 199 } 200 if (verbose_flag) { 201 diag(gettext(DIAG_RESULTS), num, fnum, unum); 202 } 203 } 204