Bug Summary

File:src/usr.bin/gencat/gencat.c
Warning:line 343, column 13
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name gencat.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/gencat/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/gencat/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/gencat/gencat.c
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/***********************************************************
35Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
36
37 All Rights Reserved
38
39Permission to use, copy, modify, and distribute this software and its
40documentation for any purpose and without fee is hereby granted,
41provided that the above copyright notice appear in all copies and that
42both that copyright notice and this permission notice appear in
43supporting documentation, and that Alfalfa's name not be used in
44advertising or publicity pertaining to distribution of the software
45without specific, written prior permission.
46
47ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53SOFTWARE.
54
55If you make any modifications, bugfixes or other changes to this software
56we'd appreciate it if you could send a copy to us so we can keep things
57up-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
82struct _msgT {
83 long msgId;
84 char *str;
85 LIST_ENTRY(_msgT)struct { struct _msgT *le_next; struct _msgT **le_prev; } entries;
86};
87
88struct _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
94LIST_HEAD(sethead, _setT)struct sethead { struct _setT *lh_first; } sethead;
95static struct _setT *curSet;
96
97static char *curline = NULL((void *)0);
98static long lineno = 0;
99
100extern char *__progname; /* from crt0.o */
101
102static char *cskip(char *);
103static void error(char *, char *);
104static void nomem(void);
105static char *get_line(int);
106static char *getmsg(int, char *, char);
107static void warning(char *, char *);
108static char *wskip(char *);
109static char *xstrdup(const char *);
110static void *xmalloc(size_t);
111static void *xrealloc(void *, size_t);
112
113void MCParse(int fd);
114void MCWriteCat(int fd);
115void MCDelMsg(int msgId);
116void MCAddMsg(int msgId, const char *msg);
117void MCAddSet(int setId);
118void MCDelSet(int setId);
119int main(int, char **);
120void usage(void);
121
122
123void
124usage(void)
125{
126 fprintf(stderr(&__sF[2]), "usage: %s catfile msgfile ...\n", __progname);
127 exit(1);
128}
129
130int
131main(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)
1
Assuming the condition is false
2
Taking false branch
138 err(1, "pledge");
139
140 while ((c = getopt(argc, argv, "")) != -1) {
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 147
141 switch (c) {
142 default:
143 usage();
144 /* NOTREACHED */
145 }
146 }
147 argc -= optind;
148 argv += optind;
149
150 if (argc < 2) {
5
Assuming 'argc' is >= 2
6
Taking false branch
151 usage();
152 /* NOTREACHED */
153 }
154 catfile = *argv++;
155
156 for (; *argv; argv++) {
7
Loop condition is true. Entering loop body
157 if ((ifd = open(*argv, O_RDONLY0x0000)) == -1)
8
Assuming the condition is false
9
Taking false branch
158 err(1, "Unable to read %s", *argv);
159 MCParse(ifd);
10
Calling 'MCParse'
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
169static void
170warning(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
181static void
182error(char *cptr, char *msg)
183{
184 warning(cptr, msg);
185 exit(1);
186}
187
188static void
189nomem(void)
190{
191 error(NULL((void *)0), "out of memory");
192}
193
194static void *
195xmalloc(size_t len)
196{
197 void *p;
198
199 if ((p = malloc(len)) == NULL((void *)0))
200 nomem();
201 return (p);
202}
203
204static void *
205xrealloc(void *ptr, size_t size)
206{
207 if ((ptr = realloc(ptr, size)) == NULL((void *)0))
208 nomem();
209 return (ptr);
210}
211
212static char *
213xstrdup(const char *str)
214{
215 char *nstr;
216
217 if ((nstr = strdup(str)) == NULL((void *)0))
218 nomem();
219 return (nstr);
220}
221
222static char *
223get_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
11.1
'curline' is null
26.1
'curline' is non-null
) {
12
Taking true branch
27
Taking false branch
231 curline = xmalloc(curlen);
232 }
233 ++lineno;
234
235 cptr = curline;
236 cend = curline + curlen;
237 for (;;) {
238 for (; bptr
12.1
'bptr' is >= 'bend'
16.1
'bptr' is < 'bend'
< bend
&& cptr < cend; ++cptr, ++bptr) {
17
Loop condition is true. Entering loop body
28
Assuming 'bptr' is < 'bend'
29
Loop condition is true. Entering loop body
33
Assuming 'bptr' is < 'bend'
34
Loop condition is true. Entering loop body
239 if (*bptr == '\n') {
18
Assuming the condition is true
19
Taking true branch
30
Assuming the condition is false
31
Taking false branch
35
Assuming the condition is true
36
Taking true branch
240 *cptr = '\0';
20
Assigning 0, which participates in a condition later
241 ++bptr;
242 return (curline);
243 } else
244 *cptr = *bptr;
32
Assigning value, which participates in a condition later
245 }
246 if (bptr
12.2
'bptr' is equal to 'bend'
== bend) {
13
Taking true branch
247 buflen = read(fd, buf, BUFSIZ1024);
248 if (buflen <= 0) {
14
Assuming 'buflen' is > 0
15
Taking false branch
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
15.1
'cptr' is not equal to 'cend'
== cend) {
16
Taking false branch
259 cptr = curline = xrealloc(curline, curlen *= 2);
260 cend = curline + curlen;
261 }
262 }
263}
264
265static char *
266wskip(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
277static char *
278cskip(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
289static char *
290getmsg(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
48.1
'quote' is 0
&& *cptr == quote) {
298 ++cptr;
299 }
300
301 clen = strlen(cptr) + 1;
302 if (clen > msglen) {
49
Assuming 'clen' is <= 'msglen'
50
Taking false branch
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
50.1
'quote' is 0
&& *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 == '\\') {
51
Assuming the condition is true
52
Taking true branch
323 ++cptr;
324 switch (*cptr) {
53
Control jumps to 'case 118:' at line 342
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';
54
Null pointer value stored to 'tptr'
55
Dereference of null pointer
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
403void
404MCParse(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))) {
11
Calling 'get_line'
21
Returning from 'get_line'
22
Loop condition is true. Entering loop body
25
Execution continues on line 413
26
Calling 'get_line'
37
Returning from 'get_line'
38
Loop condition is true. Entering loop body
414 if (*cptr == '$') {
23
Taking false branch
39
Assuming the condition is false
40
Taking false branch
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)
24
Taking true branch
41
Assuming the condition is false
42
Taking false branch
451 continue;
452 /*
453 * We have a digit? Start of a message. Else,
454 * syntax error.
455 */
456 if (isdigit((unsigned char) *cptr)) {
43
Assuming the character is a digit
44
Taking true branch
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
44.1
'setid' is equal to 0
== 0) {
45
Taking true branch
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) {
46
Assuming the condition is false
47
Taking false branch
475 MCDelMsg(msgid);
476 } else {
477 str = getmsg(fd, cptr, quote);
48
Calling 'getmsg'
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 */
493void
494MCWriteCat(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
594void
595MCAddSet(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
634void
635MCAddMsg(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
675void
676MCDelSet(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
699void
700MCDelMsg(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}