File: | src/usr.bin/gencat/gencat.c |
Warning: | line 689, column 4 Attempt to free released memory |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: gencat.c,v 1.22 2022/12/26 19:16:01 jmc Exp $ */ | |||
2 | /* $NetBSD: gencat.c,v 1.9 1998/10/09 17:00:56 itohy Exp $ */ | |||
3 | ||||
4 | /*- | |||
5 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | |||
6 | * All rights reserved. | |||
7 | * | |||
8 | * This code is derived from software contributed to The NetBSD Foundation | |||
9 | * by J.T. Conklin. | |||
10 | * | |||
11 | * Redistribution and use in source and binary forms, with or without | |||
12 | * modification, are permitted provided that the following conditions | |||
13 | * are met: | |||
14 | * 1. Redistributions of source code must retain the above copyright | |||
15 | * notice, this list of conditions and the following disclaimer. | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in the | |||
18 | * documentation and/or other materials provided with the distribution. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
30 | * POSSIBILITY OF SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | ||||
34 | /*********************************************************** | |||
35 | Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. | |||
36 | ||||
37 | All Rights Reserved | |||
38 | ||||
39 | Permission to use, copy, modify, and distribute this software and its | |||
40 | documentation for any purpose and without fee is hereby granted, | |||
41 | provided that the above copyright notice appear in all copies and that | |||
42 | both that copyright notice and this permission notice appear in | |||
43 | supporting documentation, and that Alfalfa's name not be used in | |||
44 | advertising or publicity pertaining to distribution of the software | |||
45 | without specific, written prior permission. | |||
46 | ||||
47 | ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |||
48 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |||
49 | ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |||
50 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |||
51 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |||
52 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |||
53 | SOFTWARE. | |||
54 | ||||
55 | If you make any modifications, bugfixes or other changes to this software | |||
56 | we'd appreciate it if you could send a copy to us so we can keep things | |||
57 | up-to-date. Many thanks. | |||
58 | Kee Hinckley | |||
59 | Alfalfa Software, Inc. | |||
60 | 267 Allston St., #3 | |||
61 | Cambridge, MA 02139 USA | |||
62 | nazgul@alfalfa.com | |||
63 | ||||
64 | ******************************************************************/ | |||
65 | ||||
66 | #define _NLS_PRIVATE | |||
67 | ||||
68 | /* ensure 8-bit cleanliness */ | |||
69 | #define ISSPACE(c)(isascii((unsigned char)c) && isspace((unsigned char) c)) \ | |||
70 | (isascii((unsigned char)c) && isspace((unsigned char)c)) | |||
71 | ||||
72 | #include <sys/queue.h> | |||
73 | #include <ctype.h> | |||
74 | #include <err.h> | |||
75 | #include <fcntl.h> | |||
76 | #include <nl_types.h> | |||
77 | #include <stdio.h> | |||
78 | #include <stdlib.h> | |||
79 | #include <string.h> | |||
80 | #include <unistd.h> | |||
81 | ||||
82 | struct _msgT { | |||
83 | long msgId; | |||
84 | char *str; | |||
85 | LIST_ENTRY(_msgT)struct { struct _msgT *le_next; struct _msgT **le_prev; } entries; | |||
86 | }; | |||
87 | ||||
88 | struct _setT { | |||
89 | long setId; | |||
90 | LIST_HEAD(msghead, _msgT)struct msghead { struct _msgT *lh_first; } msghead; | |||
91 | LIST_ENTRY(_setT)struct { struct _setT *le_next; struct _setT **le_prev; } entries; | |||
92 | }; | |||
93 | ||||
94 | LIST_HEAD(sethead, _setT)struct sethead { struct _setT *lh_first; } sethead; | |||
95 | static struct _setT *curSet; | |||
96 | ||||
97 | static char *curline = NULL((void *)0); | |||
98 | static long lineno = 0; | |||
99 | ||||
100 | extern char *__progname; /* from crt0.o */ | |||
101 | ||||
102 | static char *cskip(char *); | |||
103 | static void error(char *, char *); | |||
104 | static void nomem(void); | |||
105 | static char *get_line(int); | |||
106 | static char *getmsg(int, char *, char); | |||
107 | static void warning(char *, char *); | |||
108 | static char *wskip(char *); | |||
109 | static char *xstrdup(const char *); | |||
110 | static void *xmalloc(size_t); | |||
111 | static void *xrealloc(void *, size_t); | |||
112 | ||||
113 | void MCParse(int fd); | |||
114 | void MCWriteCat(int fd); | |||
115 | void MCDelMsg(int msgId); | |||
116 | void MCAddMsg(int msgId, const char *msg); | |||
117 | void MCAddSet(int setId); | |||
118 | void MCDelSet(int setId); | |||
119 | int main(int, char **); | |||
120 | void usage(void); | |||
121 | ||||
122 | ||||
123 | void | |||
124 | usage(void) | |||
125 | { | |||
126 | fprintf(stderr(&__sF[2]), "usage: %s catfile msgfile ...\n", __progname); | |||
127 | exit(1); | |||
128 | } | |||
129 | ||||
130 | int | |||
131 | main(int argc, char *argv[]) | |||
132 | { | |||
133 | int ofd, ifd; | |||
134 | char *catfile = NULL((void *)0); | |||
135 | int c; | |||
136 | ||||
137 | if (pledge("stdio rpath wpath cpath", NULL((void *)0)) == -1) | |||
| ||||
138 | err(1, "pledge"); | |||
139 | ||||
140 | while ((c = getopt(argc, argv, "")) != -1) { | |||
141 | switch (c) { | |||
142 | default: | |||
143 | usage(); | |||
144 | /* NOTREACHED */ | |||
145 | } | |||
146 | } | |||
147 | argc -= optind; | |||
148 | argv += optind; | |||
149 | ||||
150 | if (argc < 2) { | |||
151 | usage(); | |||
152 | /* NOTREACHED */ | |||
153 | } | |||
154 | catfile = *argv++; | |||
155 | ||||
156 | for (; *argv; argv++) { | |||
157 | if ((ifd = open(*argv, O_RDONLY0x0000)) == -1) | |||
158 | err(1, "Unable to read %s", *argv); | |||
159 | MCParse(ifd); | |||
160 | close(ifd); | |||
161 | } | |||
162 | ||||
163 | if ((ofd = open(catfile, O_WRONLY0x0001 | O_TRUNC0x0400 | O_CREAT0x0200, 0666)) == -1) | |||
164 | err(1, "Unable to create a new %s", catfile); | |||
165 | MCWriteCat(ofd); | |||
166 | exit(0); | |||
167 | } | |||
168 | ||||
169 | static void | |||
170 | warning(char *cptr, char *msg) | |||
171 | { | |||
172 | warnx("%s on line %ld\n%s", msg, lineno, curline); | |||
173 | if (cptr) { | |||
174 | char *tptr; | |||
175 | for (tptr = curline; tptr < cptr; ++tptr) | |||
176 | putc(' ', stderr)(!__isthreaded ? __sputc(' ', (&__sF[2])) : (putc)(' ', ( &__sF[2]))); | |||
177 | fprintf(stderr(&__sF[2]), "^\n"); | |||
178 | } | |||
179 | } | |||
180 | ||||
181 | static void | |||
182 | error(char *cptr, char *msg) | |||
183 | { | |||
184 | warning(cptr, msg); | |||
185 | exit(1); | |||
186 | } | |||
187 | ||||
188 | static void | |||
189 | nomem(void) | |||
190 | { | |||
191 | error(NULL((void *)0), "out of memory"); | |||
192 | } | |||
193 | ||||
194 | static void * | |||
195 | xmalloc(size_t len) | |||
196 | { | |||
197 | void *p; | |||
198 | ||||
199 | if ((p = malloc(len)) == NULL((void *)0)) | |||
200 | nomem(); | |||
201 | return (p); | |||
202 | } | |||
203 | ||||
204 | static void * | |||
205 | xrealloc(void *ptr, size_t size) | |||
206 | { | |||
207 | if ((ptr = realloc(ptr, size)) == NULL((void *)0)) | |||
208 | nomem(); | |||
209 | return (ptr); | |||
210 | } | |||
211 | ||||
212 | static char * | |||
213 | xstrdup(const char *str) | |||
214 | { | |||
215 | char *nstr; | |||
216 | ||||
217 | if ((nstr = strdup(str)) == NULL((void *)0)) | |||
218 | nomem(); | |||
219 | return (nstr); | |||
220 | } | |||
221 | ||||
222 | static char * | |||
223 | get_line(int fd) | |||
224 | { | |||
225 | static long curlen = BUFSIZ1024; | |||
226 | static char buf[BUFSIZ1024], *bptr = buf, *bend = buf; | |||
227 | char *cptr, *cend; | |||
228 | long buflen; | |||
229 | ||||
230 | if (!curline) { | |||
231 | curline = xmalloc(curlen); | |||
232 | } | |||
233 | ++lineno; | |||
234 | ||||
235 | cptr = curline; | |||
236 | cend = curline + curlen; | |||
237 | for (;;) { | |||
238 | for (; bptr < bend && cptr < cend; ++cptr, ++bptr) { | |||
239 | if (*bptr == '\n') { | |||
240 | *cptr = '\0'; | |||
241 | ++bptr; | |||
242 | return (curline); | |||
243 | } else | |||
244 | *cptr = *bptr; | |||
245 | } | |||
246 | if (bptr == bend) { | |||
247 | buflen = read(fd, buf, BUFSIZ1024); | |||
248 | if (buflen <= 0) { | |||
249 | if (cptr > curline) { | |||
250 | *cptr = '\0'; | |||
251 | return (curline); | |||
252 | } | |||
253 | return (NULL((void *)0)); | |||
254 | } | |||
255 | bend = buf + buflen; | |||
256 | bptr = buf; | |||
257 | } | |||
258 | if (cptr == cend) { | |||
259 | cptr = curline = xrealloc(curline, curlen *= 2); | |||
260 | cend = curline + curlen; | |||
261 | } | |||
262 | } | |||
263 | } | |||
264 | ||||
265 | static char * | |||
266 | wskip(char *cptr) | |||
267 | { | |||
268 | if (!*cptr || !ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char )*cptr))) { | |||
269 | warning(cptr, "expected a space"); | |||
270 | return (cptr); | |||
271 | } | |||
272 | while (*cptr && ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char )*cptr))) | |||
273 | ++cptr; | |||
274 | return (cptr); | |||
275 | } | |||
276 | ||||
277 | static char * | |||
278 | cskip(char *cptr) | |||
279 | { | |||
280 | if (!*cptr || ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char )*cptr))) { | |||
281 | warning(cptr, "wasn't expecting a space"); | |||
282 | return (cptr); | |||
283 | } | |||
284 | while (*cptr && !ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char )*cptr))) | |||
285 | ++cptr; | |||
286 | return (cptr); | |||
287 | } | |||
288 | ||||
289 | static char * | |||
290 | getmsg(int fd, char *cptr, char quote) | |||
291 | { | |||
292 | static char *msg = NULL((void *)0); | |||
293 | static long msglen = 0; | |||
294 | long clen, i; | |||
295 | char *tptr; | |||
296 | ||||
297 | if (quote && *cptr == quote) { | |||
298 | ++cptr; | |||
299 | } | |||
300 | ||||
301 | clen = strlen(cptr) + 1; | |||
302 | if (clen > msglen) { | |||
303 | if (msglen) | |||
304 | msg = xrealloc(msg, clen); | |||
305 | else | |||
306 | msg = xmalloc(clen); | |||
307 | msglen = clen; | |||
308 | } | |||
309 | tptr = msg; | |||
310 | ||||
311 | while (*cptr) { | |||
312 | if (quote && *cptr == quote) { | |||
313 | char *tmp; | |||
314 | tmp = cptr + 1; | |||
315 | ||||
316 | if (*tmp && (!ISSPACE(*tmp)(isascii((unsigned char)*tmp) && isspace((unsigned char )*tmp)) || *wskip(tmp))) { | |||
317 | warning(cptr, "unexpected quote character, ignoring"); | |||
318 | *tptr++ = *cptr++; | |||
319 | } else { | |||
320 | *cptr = '\0'; | |||
321 | } | |||
322 | } else if (*cptr == '\\') { | |||
323 | ++cptr; | |||
324 | switch (*cptr) { | |||
325 | case '\0': | |||
326 | cptr = get_line(fd); | |||
327 | if (!cptr) | |||
328 | error(NULL((void *)0), "premature end of file"); | |||
329 | msglen += strlen(cptr); | |||
330 | i = tptr - msg; | |||
331 | msg = xrealloc(msg, msglen); | |||
332 | tptr = msg + i; | |||
333 | break; | |||
334 | case 'n': | |||
335 | *tptr++ = '\n'; | |||
336 | ++cptr; | |||
337 | break; | |||
338 | case 't': | |||
339 | *tptr++ = '\t'; | |||
340 | ++cptr; | |||
341 | break; | |||
342 | case 'v': | |||
343 | *tptr++ = '\v'; | |||
344 | ++cptr; | |||
345 | break; | |||
346 | case 'b': | |||
347 | *tptr++ = '\b'; | |||
348 | ++cptr; | |||
349 | break; | |||
350 | case 'r': | |||
351 | *tptr++ = '\r'; | |||
352 | ++cptr; | |||
353 | break; | |||
354 | case 'f': | |||
355 | *tptr++ = '\f'; | |||
356 | ++cptr; | |||
357 | break; | |||
358 | case '\\': | |||
359 | *tptr++ = '\\'; | |||
360 | ++cptr; | |||
361 | break; | |||
362 | case '"': | |||
363 | /* FALLTHROUGH */ | |||
364 | case '\'': | |||
365 | /* | |||
366 | * While it isn't necessary to | |||
367 | * escape ' and ", let's accept | |||
368 | * them escaped and not complain. | |||
369 | * (XPG4 states that '\' should be | |||
370 | * ignored when not used in a | |||
371 | * valid escape sequence) | |||
372 | */ | |||
373 | *tptr++ = '"'; | |||
374 | ++cptr; | |||
375 | break; | |||
376 | default: | |||
377 | if (quote && *cptr == quote) { | |||
378 | *tptr++ = *cptr++; | |||
379 | } else if (isdigit((unsigned char) *cptr)) { | |||
380 | *tptr = 0; | |||
381 | for (i = 0; i < 3; ++i) { | |||
382 | if (!isdigit((unsigned char) *cptr)) | |||
383 | break; | |||
384 | if (*cptr > '7') | |||
385 | warning(cptr, "octal number greater than 7?!"); | |||
386 | *tptr *= 8; | |||
387 | *tptr += (*cptr - '0'); | |||
388 | ++cptr; | |||
389 | } | |||
390 | } else { | |||
391 | warning(cptr, "unrecognized escape sequence; ignoring escape character"); | |||
392 | } | |||
393 | break; | |||
394 | } | |||
395 | } else { | |||
396 | *tptr++ = *cptr++; | |||
397 | } | |||
398 | } | |||
399 | *tptr = '\0'; | |||
400 | return (msg); | |||
401 | } | |||
402 | ||||
403 | void | |||
404 | MCParse(int fd) | |||
405 | { | |||
406 | char *cptr, *str; | |||
407 | int setid, msgid; | |||
408 | char quote = 0; | |||
409 | ||||
410 | /* XXX: init sethead? */ | |||
411 | ||||
412 | setid = 0; | |||
413 | while ((cptr = get_line(fd))) { | |||
414 | if (*cptr == '$') { | |||
415 | ++cptr; | |||
416 | if (strncmp(cptr, "set", 3) == 0) { | |||
417 | cptr += 3; | |||
418 | cptr = wskip(cptr); | |||
419 | setid = atoi(cptr); | |||
420 | MCAddSet(setid); | |||
421 | } else if (strncmp(cptr, "delset", 6) == 0) { | |||
422 | cptr += 6; | |||
423 | cptr = wskip(cptr); | |||
424 | setid = atoi(cptr); | |||
425 | MCDelSet(setid); | |||
426 | } else if (strncmp(cptr, "quote", 5) == 0) { | |||
427 | cptr += 5; | |||
428 | if (!*cptr) | |||
429 | quote = 0; | |||
430 | else { | |||
431 | cptr = wskip(cptr); | |||
432 | if (!*cptr) | |||
433 | quote = 0; | |||
434 | else | |||
435 | quote = *cptr; | |||
436 | } | |||
437 | } else if (ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char )*cptr))) { | |||
438 | ; | |||
439 | } else { | |||
440 | if (*cptr) { | |||
441 | cptr = wskip(cptr); | |||
442 | if (*cptr) | |||
443 | warning(cptr, "unrecognized line"); | |||
444 | } | |||
445 | } | |||
446 | } else { | |||
447 | /* | |||
448 | * First check for (and eat) empty lines.... | |||
449 | */ | |||
450 | if (!*cptr) | |||
451 | continue; | |||
452 | /* | |||
453 | * We have a digit? Start of a message. Else, | |||
454 | * syntax error. | |||
455 | */ | |||
456 | if (isdigit((unsigned char) *cptr)) { | |||
457 | msgid = atoi(cptr); | |||
458 | cptr = cskip(cptr); | |||
459 | cptr = wskip(cptr); | |||
460 | /* if (*cptr) ++cptr; */ | |||
461 | } else { | |||
462 | warning(cptr, "neither blank line nor start of a message id"); | |||
463 | continue; | |||
464 | } | |||
465 | if (setid == 0) { | |||
466 | setid = NL_SETD1; | |||
467 | MCAddSet(setid); | |||
468 | } | |||
469 | /* | |||
470 | * If we have a message ID, but no message, | |||
471 | * then this means "delete this message id | |||
472 | * from the catalog". | |||
473 | */ | |||
474 | if (!*cptr) { | |||
475 | MCDelMsg(msgid); | |||
476 | } else { | |||
477 | str = getmsg(fd, cptr, quote); | |||
478 | MCAddMsg(msgid, str); | |||
479 | } | |||
480 | } | |||
481 | } | |||
482 | } | |||
483 | ||||
484 | /* | |||
485 | * Write message catalog. | |||
486 | * | |||
487 | * The message catalog is first converted from its internal to its | |||
488 | * external representation in a chunk of memory allocated for this | |||
489 | * purpose. Then the completed catalog is written. This approach | |||
490 | * avoids additional housekeeping variables and/or a lot of seeks | |||
491 | * that would otherwise be required. | |||
492 | */ | |||
493 | void | |||
494 | MCWriteCat(int fd) | |||
495 | { | |||
496 | int nsets; /* number of sets */ | |||
497 | int nmsgs; /* number of msgs */ | |||
498 | int string_size; /* total size of string pool */ | |||
499 | int msgcat_size; /* total size of message catalog */ | |||
500 | void *msgcat; /* message catalog data */ | |||
501 | struct _nls_cat_hdr *cat_hdr; | |||
502 | struct _nls_set_hdr *set_hdr; | |||
503 | struct _nls_msg_hdr *msg_hdr; | |||
504 | char *strings; | |||
505 | struct _setT *set; | |||
506 | struct _msgT *msg; | |||
507 | int msg_index; | |||
508 | int msg_offset; | |||
509 | ||||
510 | /* determine number of sets, number of messages, and size of the | |||
511 | * string pool */ | |||
512 | nsets = 0; | |||
513 | nmsgs = 0; | |||
514 | string_size = 0; | |||
515 | ||||
516 | LIST_FOREACH(set, &sethead, entries)for((set) = ((&sethead)->lh_first); (set)!= ((void *)0 ); (set) = ((set)->entries.le_next)) { | |||
517 | nsets++; | |||
518 | ||||
519 | LIST_FOREACH(msg, &set->msghead, entries)for((msg) = ((&set->msghead)->lh_first); (msg)!= (( void *)0); (msg) = ((msg)->entries.le_next)) { | |||
520 | nmsgs++; | |||
521 | string_size += strlen(msg->str) + 1; | |||
522 | } | |||
523 | } | |||
524 | ||||
525 | #ifdef DEBUG | |||
526 | printf("number of sets: %d\n", nsets); | |||
527 | printf("number of msgs: %d\n", nmsgs); | |||
528 | printf("string pool size: %d\n", string_size); | |||
529 | #endif | |||
530 | ||||
531 | /* determine size and then allocate buffer for constructing external | |||
532 | * message catalog representation */ | |||
533 | msgcat_size = sizeof(struct _nls_cat_hdr) | |||
534 | + (nsets * sizeof(struct _nls_set_hdr)) | |||
535 | + (nmsgs * sizeof(struct _nls_msg_hdr)) | |||
536 | + string_size; | |||
537 | ||||
538 | msgcat = xmalloc(msgcat_size); | |||
539 | memset(msgcat, '\0', msgcat_size); | |||
540 | ||||
541 | /* fill in msg catalog header */ | |||
542 | cat_hdr = (struct _nls_cat_hdr *) msgcat; | |||
543 | cat_hdr->__magic = htonl(_NLS_MAGIC)(__uint32_t)(__builtin_constant_p(0xff88ff89) ? (__uint32_t)( ((__uint32_t)(0xff88ff89) & 0xff) << 24 | ((__uint32_t )(0xff88ff89) & 0xff00) << 8 | ((__uint32_t)(0xff88ff89 ) & 0xff0000) >> 8 | ((__uint32_t)(0xff88ff89) & 0xff000000) >> 24) : __swap32md(0xff88ff89)); | |||
544 | cat_hdr->__nsets = htonl(nsets)(__uint32_t)(__builtin_constant_p(nsets) ? (__uint32_t)(((__uint32_t )(nsets) & 0xff) << 24 | ((__uint32_t)(nsets) & 0xff00) << 8 | ((__uint32_t)(nsets) & 0xff0000) >> 8 | ((__uint32_t)(nsets) & 0xff000000) >> 24) : __swap32md (nsets)); | |||
545 | cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr))(__uint32_t)(__builtin_constant_p(msgcat_size - sizeof(struct _nls_cat_hdr)) ? (__uint32_t)(((__uint32_t)(msgcat_size - sizeof (struct _nls_cat_hdr)) & 0xff) << 24 | ((__uint32_t )(msgcat_size - sizeof(struct _nls_cat_hdr)) & 0xff00) << 8 | ((__uint32_t)(msgcat_size - sizeof(struct _nls_cat_hdr)) & 0xff0000) >> 8 | ((__uint32_t)(msgcat_size - sizeof (struct _nls_cat_hdr)) & 0xff000000) >> 24) : __swap32md (msgcat_size - sizeof(struct _nls_cat_hdr))); | |||
546 | cat_hdr->__msg_hdr_offset = | |||
547 | htonl(nsets * sizeof(struct _nls_set_hdr))(__uint32_t)(__builtin_constant_p(nsets * sizeof(struct _nls_set_hdr )) ? (__uint32_t)(((__uint32_t)(nsets * sizeof(struct _nls_set_hdr )) & 0xff) << 24 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr)) & 0xff00) << 8 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr)) & 0xff0000) >> 8 | ( (__uint32_t)(nsets * sizeof(struct _nls_set_hdr)) & 0xff000000 ) >> 24) : __swap32md(nsets * sizeof(struct _nls_set_hdr ))); | |||
548 | cat_hdr->__msg_txt_offset = | |||
549 | htonl(nsets * sizeof(struct _nls_set_hdr) +(__uint32_t)(__builtin_constant_p(nsets * sizeof(struct _nls_set_hdr ) + nmsgs * sizeof(struct _nls_msg_hdr)) ? (__uint32_t)(((__uint32_t )(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr)) & 0xff) << 24 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr )) & 0xff00) << 8 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr)) & 0xff0000 ) >> 8 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr ) + nmsgs * sizeof(struct _nls_msg_hdr)) & 0xff000000) >> 24) : __swap32md(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr))) | |||
550 | nmsgs * sizeof(struct _nls_msg_hdr))(__uint32_t)(__builtin_constant_p(nsets * sizeof(struct _nls_set_hdr ) + nmsgs * sizeof(struct _nls_msg_hdr)) ? (__uint32_t)(((__uint32_t )(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr)) & 0xff) << 24 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr )) & 0xff00) << 8 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr)) & 0xff0000 ) >> 8 | ((__uint32_t)(nsets * sizeof(struct _nls_set_hdr ) + nmsgs * sizeof(struct _nls_msg_hdr)) & 0xff000000) >> 24) : __swap32md(nsets * sizeof(struct _nls_set_hdr) + nmsgs * sizeof(struct _nls_msg_hdr))); | |||
551 | ||||
552 | /* compute offsets for set & msg header tables and string pool */ | |||
553 | set_hdr = (struct _nls_set_hdr *) ((char *) msgcat + | |||
554 | sizeof(struct _nls_cat_hdr)); | |||
555 | msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat + | |||
556 | sizeof(struct _nls_cat_hdr) + | |||
557 | nsets * sizeof(struct _nls_set_hdr)); | |||
558 | strings = (char *) msgcat + | |||
559 | sizeof(struct _nls_cat_hdr) + | |||
560 | nsets * sizeof(struct _nls_set_hdr) + | |||
561 | nmsgs * sizeof(struct _nls_msg_hdr); | |||
562 | ||||
563 | msg_index = 0; | |||
564 | msg_offset = 0; | |||
565 | LIST_FOREACH(set, &sethead, entries)for((set) = ((&sethead)->lh_first); (set)!= ((void *)0 ); (set) = ((set)->entries.le_next)) { | |||
566 | ||||
567 | nmsgs = 0; | |||
568 | LIST_FOREACH(msg, &set->msghead, entries)for((msg) = ((&set->msghead)->lh_first); (msg)!= (( void *)0); (msg) = ((msg)->entries.le_next)) { | |||
569 | int msg_len = strlen(msg->str) + 1; | |||
570 | ||||
571 | msg_hdr->__msgno = htonl(msg->msgId)(__uint32_t)(__builtin_constant_p(msg->msgId) ? (__uint32_t )(((__uint32_t)(msg->msgId) & 0xff) << 24 | ((__uint32_t )(msg->msgId) & 0xff00) << 8 | ((__uint32_t)(msg ->msgId) & 0xff0000) >> 8 | ((__uint32_t)(msg-> msgId) & 0xff000000) >> 24) : __swap32md(msg->msgId )); | |||
572 | msg_hdr->__msglen = htonl(msg_len)(__uint32_t)(__builtin_constant_p(msg_len) ? (__uint32_t)(((__uint32_t )(msg_len) & 0xff) << 24 | ((__uint32_t)(msg_len) & 0xff00) << 8 | ((__uint32_t)(msg_len) & 0xff0000) >> 8 | ((__uint32_t)(msg_len) & 0xff000000) >> 24) : __swap32md (msg_len)); | |||
573 | msg_hdr->__offset = htonl(msg_offset)(__uint32_t)(__builtin_constant_p(msg_offset) ? (__uint32_t)( ((__uint32_t)(msg_offset) & 0xff) << 24 | ((__uint32_t )(msg_offset) & 0xff00) << 8 | ((__uint32_t)(msg_offset ) & 0xff0000) >> 8 | ((__uint32_t)(msg_offset) & 0xff000000) >> 24) : __swap32md(msg_offset)); | |||
574 | ||||
575 | memcpy(strings, msg->str, msg_len); | |||
576 | strings += msg_len; | |||
577 | msg_offset += msg_len; | |||
578 | ||||
579 | nmsgs++; | |||
580 | msg_hdr++; | |||
581 | } | |||
582 | ||||
583 | set_hdr->__setno = htonl(set->setId)(__uint32_t)(__builtin_constant_p(set->setId) ? (__uint32_t )(((__uint32_t)(set->setId) & 0xff) << 24 | ((__uint32_t )(set->setId) & 0xff00) << 8 | ((__uint32_t)(set ->setId) & 0xff0000) >> 8 | ((__uint32_t)(set-> setId) & 0xff000000) >> 24) : __swap32md(set->setId )); | |||
584 | set_hdr->__nmsgs = htonl(nmsgs)(__uint32_t)(__builtin_constant_p(nmsgs) ? (__uint32_t)(((__uint32_t )(nmsgs) & 0xff) << 24 | ((__uint32_t)(nmsgs) & 0xff00) << 8 | ((__uint32_t)(nmsgs) & 0xff0000) >> 8 | ((__uint32_t)(nmsgs) & 0xff000000) >> 24) : __swap32md (nmsgs)); | |||
585 | set_hdr->__index = htonl(msg_index)(__uint32_t)(__builtin_constant_p(msg_index) ? (__uint32_t)(( (__uint32_t)(msg_index) & 0xff) << 24 | ((__uint32_t )(msg_index) & 0xff00) << 8 | ((__uint32_t)(msg_index ) & 0xff0000) >> 8 | ((__uint32_t)(msg_index) & 0xff000000) >> 24) : __swap32md(msg_index)); | |||
586 | msg_index += nmsgs; | |||
587 | set_hdr++; | |||
588 | } | |||
589 | ||||
590 | /* write out catalog. XXX: should this be done in small chunks? */ | |||
591 | write(fd, msgcat, msgcat_size); | |||
592 | } | |||
593 | ||||
594 | void | |||
595 | MCAddSet(int setId) | |||
596 | { | |||
597 | struct _setT *p, *q; | |||
598 | ||||
599 | if (setId <= 0) { | |||
600 | error(NULL((void *)0), "setId's must be greater than zero"); | |||
601 | /* NOTREACHED */ | |||
602 | } | |||
603 | #if 0 | |||
604 | /* XXX */ | |||
605 | if (setId > NL_SETMAX) { | |||
606 | error(NULL((void *)0), "setId %d exceeds limit (%d)"); | |||
607 | /* NOTREACHED */ | |||
608 | } | |||
609 | #endif | |||
610 | ||||
611 | p = LIST_FIRST(&sethead)((&sethead)->lh_first); | |||
612 | q = NULL((void *)0); | |||
613 | for (; p != NULL((void *)0) && p->setId < setId; q = p, p = LIST_NEXT(p, entries)((p)->entries.le_next)); | |||
614 | ||||
615 | if (p && p->setId == setId) { | |||
616 | ; | |||
617 | } else { | |||
618 | p = xmalloc(sizeof(struct _setT)); | |||
619 | memset(p, '\0', sizeof(struct _setT)); | |||
620 | LIST_INIT(&p->msghead)do { ((&p->msghead)->lh_first) = ((void *)0); } while (0); | |||
621 | ||||
622 | p->setId = setId; | |||
623 | ||||
624 | if (q == NULL((void *)0)) { | |||
625 | LIST_INSERT_HEAD(&sethead, p, entries)do { if (((p)->entries.le_next = (&sethead)->lh_first ) != ((void *)0)) (&sethead)->lh_first->entries.le_prev = &(p)->entries.le_next; (&sethead)->lh_first = (p); (p)->entries.le_prev = &(&sethead)->lh_first ; } while (0); | |||
626 | } else { | |||
627 | LIST_INSERT_AFTER(q, p, entries)do { if (((p)->entries.le_next = (q)->entries.le_next) != ((void *)0)) (q)->entries.le_next->entries.le_prev = & (p)->entries.le_next; (q)->entries.le_next = (p); (p)-> entries.le_prev = &(q)->entries.le_next; } while (0); | |||
628 | } | |||
629 | } | |||
630 | ||||
631 | curSet = p; | |||
632 | } | |||
633 | ||||
634 | void | |||
635 | MCAddMsg(int msgId, const char *str) | |||
636 | { | |||
637 | struct _msgT *p, *q; | |||
638 | ||||
639 | if (!curSet) | |||
640 | error(NULL((void *)0), "can't specify a message when no set exists"); | |||
641 | ||||
642 | if (msgId <= 0) { | |||
643 | error(NULL((void *)0), "msgId's must be greater than zero"); | |||
644 | /* NOTREACHED */ | |||
645 | } | |||
646 | #if 0 | |||
647 | /* XXX */ | |||
648 | if (msgId > NL_SETMAX) { | |||
649 | error(NULL((void *)0), "msgId %d exceeds limit (%d)"); | |||
650 | /* NOTREACHED */ | |||
651 | } | |||
652 | #endif | |||
653 | ||||
654 | p = LIST_FIRST(&curSet->msghead)((&curSet->msghead)->lh_first); | |||
655 | q = NULL((void *)0); | |||
656 | for (; p != NULL((void *)0) && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries)((p)->entries.le_next)); | |||
657 | ||||
658 | if (p && p->msgId == msgId) { | |||
659 | free(p->str); | |||
660 | } else { | |||
661 | p = xmalloc(sizeof(struct _msgT)); | |||
662 | memset(p, '\0', sizeof(struct _msgT)); | |||
663 | ||||
664 | if (q == NULL((void *)0)) { | |||
665 | LIST_INSERT_HEAD(&curSet->msghead, p, entries)do { if (((p)->entries.le_next = (&curSet->msghead) ->lh_first) != ((void *)0)) (&curSet->msghead)-> lh_first->entries.le_prev = &(p)->entries.le_next; ( &curSet->msghead)->lh_first = (p); (p)->entries. le_prev = &(&curSet->msghead)->lh_first; } while (0); | |||
666 | } else { | |||
667 | LIST_INSERT_AFTER(q, p, entries)do { if (((p)->entries.le_next = (q)->entries.le_next) != ((void *)0)) (q)->entries.le_next->entries.le_prev = & (p)->entries.le_next; (q)->entries.le_next = (p); (p)-> entries.le_prev = &(q)->entries.le_next; } while (0); | |||
668 | } | |||
669 | } | |||
670 | ||||
671 | p->msgId = msgId; | |||
672 | p->str = xstrdup(str); | |||
673 | } | |||
674 | ||||
675 | void | |||
676 | MCDelSet(int setId) | |||
677 | { | |||
678 | struct _setT *set; | |||
679 | struct _msgT *msg; | |||
680 | ||||
681 | set = LIST_FIRST(&sethead)((&sethead)->lh_first); | |||
682 | for (; set != NULL((void *)0) && set->setId < setId; | |||
683 | set = LIST_NEXT(set, entries)((set)->entries.le_next)); | |||
684 | ||||
685 | if (set
| |||
686 | ||||
687 | msg = LIST_FIRST(&set->msghead)((&set->msghead)->lh_first); | |||
688 | while (msg) { | |||
689 | free(msg->str); | |||
| ||||
690 | LIST_REMOVE(msg, entries)do { if ((msg)->entries.le_next != ((void *)0)) (msg)-> entries.le_next->entries.le_prev = (msg)->entries.le_prev ; *(msg)->entries.le_prev = (msg)->entries.le_next; ; ; } while (0); | |||
691 | } | |||
692 | ||||
693 | LIST_REMOVE(set, entries)do { if ((set)->entries.le_next != ((void *)0)) (set)-> entries.le_next->entries.le_prev = (set)->entries.le_prev ; *(set)->entries.le_prev = (set)->entries.le_next; ; ; } while (0); | |||
694 | return; | |||
695 | } | |||
696 | warning(NULL((void *)0), "specified set doesn't exist"); | |||
697 | } | |||
698 | ||||
699 | void | |||
700 | MCDelMsg(int msgId) | |||
701 | { | |||
702 | struct _msgT *msg; | |||
703 | ||||
704 | if (!curSet) | |||
705 | error(NULL((void *)0), "you can't delete a message before defining the set"); | |||
706 | ||||
707 | msg = LIST_FIRST(&curSet->msghead)((&curSet->msghead)->lh_first); | |||
708 | for (; msg != NULL((void *)0) && msg->msgId < msgId; | |||
709 | msg = LIST_NEXT(msg, entries)((msg)->entries.le_next)); | |||
710 | ||||
711 | if (msg && msg->msgId == msgId) { | |||
712 | free(msg->str); | |||
713 | LIST_REMOVE(msg, entries)do { if ((msg)->entries.le_next != ((void *)0)) (msg)-> entries.le_next->entries.le_prev = (msg)->entries.le_prev ; *(msg)->entries.le_prev = (msg)->entries.le_next; ; ; } while (0); | |||
714 | return; | |||
715 | } | |||
716 | warning(NULL((void *)0), "specified msg doesn't exist"); | |||
717 | } |