File: | src/usr.bin/gencat/gencat.c |
Warning: | line 373, column 13 Dereference of null pointer |
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
| ||||
239 | if (*bptr == '\n') { | ||||
240 | *cptr = '\0'; | ||||
241 | ++bptr; | ||||
242 | return (curline); | ||||
243 | } else | ||||
244 | *cptr = *bptr; | ||||
245 | } | ||||
246 | if (bptr
| ||||
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
| ||||
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
| ||||
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
| ||||
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
| ||||
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 && set->setId == setId) { | ||||
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 | } |