Bug Summary

File:src/usr.bin/gencat/gencat.c
Warning:line 269, column 6
Branch condition evaluates to a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name gencat.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/gencat/gencat.c
1/* $OpenBSD: gencat.c,v 1.20 2019/07/25 13:53:57 schwarze 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 148
141 switch (c) {
142 case '?':
143 default:
144 usage();
145 /* NOTREACHED */
146 }
147 }
148 argc -= optind;
149 argv += optind;
150
151 if (argc < 2) {
5
Assuming 'argc' is >= 2
6
Taking false branch
152 usage();
153 /* NOTREACHED */
154 }
155 catfile = *argv++;
156
157 for (; *argv; argv++) {
7
Loop condition is true. Entering loop body
158 if ((ifd = open(*argv, O_RDONLY0x0000)) == -1)
8
Assuming the condition is false
9
Taking false branch
159 err(1, "Unable to read %s", *argv);
160 MCParse(ifd);
10
Calling 'MCParse'
161 close(ifd);
162 }
163
164 if ((ofd = open(catfile, O_WRONLY0x0001 | O_TRUNC0x0400 | O_CREAT0x0200, 0666)) == -1)
165 err(1, "Unable to create a new %s", catfile);
166 MCWriteCat(ofd);
167 exit(0);
168}
169
170static void
171warning(char *cptr, char *msg)
172{
173 warnx("%s on line %ld\n%s", msg, lineno, curline);
174 if (cptr) {
175 char *tptr;
176 for (tptr = curline; tptr < cptr; ++tptr)
177 putc(' ', stderr)(!__isthreaded ? __sputc(' ', (&__sF[2])) : (putc)(' ', (
&__sF[2])))
;
178 fprintf(stderr(&__sF[2]), "^\n");
179 }
180}
181
182static void
183error(char *cptr, char *msg)
184{
185 warning(cptr, msg);
186 exit(1);
187}
188
189static void
190nomem(void)
191{
192 error(NULL((void *)0), "out of memory");
193}
194
195static void *
196xmalloc(size_t len)
197{
198 void *p;
199
200 if ((p = malloc(len)) == NULL((void *)0))
14
Storing uninitialized value
15
Assuming the condition is false
16
Taking false branch
201 nomem();
202 return (p);
203}
204
205static void *
206xrealloc(void *ptr, size_t size)
207{
208 if ((ptr = realloc(ptr, size)) == NULL((void *)0))
209 nomem();
210 return (ptr);
211}
212
213static char *
214xstrdup(const char *str)
215{
216 char *nstr;
217
218 if ((nstr = strdup(str)) == NULL((void *)0))
219 nomem();
220 return (nstr);
221}
222
223static char *
224get_line(int fd)
225{
226 static long curlen = BUFSIZ1024;
227 static char buf[BUFSIZ1024], *bptr = buf, *bend = buf;
228 char *cptr, *cend;
229 long buflen;
230
231 if (!curline
11.1
'curline' is null
) {
12
Taking true branch
232 curline = xmalloc(curlen);
13
Calling 'xmalloc'
17
Returning from 'xmalloc'
233 }
234 ++lineno;
235
236 cptr = curline;
237 cend = curline + curlen;
238 for (;;) {
18
Loop condition is true. Entering loop body
23
Loop condition is true. Entering loop body
239 for (; bptr
18.1
'bptr' is >= 'bend'
23.1
'bptr' is < 'bend'
< bend && cptr < cend; ++cptr, ++bptr) {
24
Loop condition is true. Entering loop body
240 if (*bptr == '\n') {
25
Assuming the condition is true
26
Taking true branch
241 *cptr = '\0';
242 ++bptr;
243 return (curline);
244 } else
245 *cptr = *bptr;
246 }
247 if (bptr
18.2
'bptr' is equal to 'bend'
== bend) {
19
Taking true branch
248 buflen = read(fd, buf, BUFSIZ1024);
249 if (buflen <= 0) {
20
Assuming 'buflen' is > 0
21
Taking false branch
250 if (cptr > curline) {
251 *cptr = '\0';
252 return (curline);
253 }
254 return (NULL((void *)0));
255 }
256 bend = buf + buflen;
257 bptr = buf;
258 }
259 if (cptr
21.1
'cptr' is not equal to 'cend'
== cend) {
22
Taking false branch
260 cptr = curline = xrealloc(curline, curlen *= 2);
261 cend = curline + curlen;
262 }
263 }
264}
265
266static char *
267wskip(char *cptr)
268{
269 if (!*cptr || !ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char
)*cptr))
) {
38
Branch condition evaluates to a garbage value
270 warning(cptr, "expected a space");
271 return (cptr);
272 }
273 while (*cptr && ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char
)*cptr))
)
274 ++cptr;
275 return (cptr);
276}
277
278static char *
279cskip(char *cptr)
280{
281 if (!*cptr || ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char
)*cptr))
) {
282 warning(cptr, "wasn't expecting a space");
283 return (cptr);
284 }
285 while (*cptr && !ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char
)*cptr))
)
286 ++cptr;
287 return (cptr);
288}
289
290static char *
291getmsg(int fd, char *cptr, char quote)
292{
293 static char *msg = NULL((void *)0);
294 static long msglen = 0;
295 long clen, i;
296 char *tptr;
297
298 if (quote && *cptr == quote) {
299 ++cptr;
300 }
301
302 clen = strlen(cptr) + 1;
303 if (clen > msglen) {
304 if (msglen)
305 msg = xrealloc(msg, clen);
306 else
307 msg = xmalloc(clen);
308 msglen = clen;
309 }
310 tptr = msg;
311
312 while (*cptr) {
313 if (quote && *cptr == quote) {
314 char *tmp;
315 tmp = cptr + 1;
316
317 if (*tmp && (!ISSPACE(*tmp)(isascii((unsigned char)*tmp) && isspace((unsigned char
)*tmp))
|| *wskip(tmp))) {
318 warning(cptr, "unexpected quote character, ignoring");
319 *tptr++ = *cptr++;
320 } else {
321 *cptr = '\0';
322 }
323 } else if (*cptr == '\\') {
324 ++cptr;
325 switch (*cptr) {
326 case '\0':
327 cptr = get_line(fd);
328 if (!cptr)
329 error(NULL((void *)0), "premature end of file");
330 msglen += strlen(cptr);
331 i = tptr - msg;
332 msg = xrealloc(msg, msglen);
333 tptr = msg + i;
334 break;
335 case 'n':
336 *tptr++ = '\n';
337 ++cptr;
338 break;
339 case 't':
340 *tptr++ = '\t';
341 ++cptr;
342 break;
343 case 'v':
344 *tptr++ = '\v';
345 ++cptr;
346 break;
347 case 'b':
348 *tptr++ = '\b';
349 ++cptr;
350 break;
351 case 'r':
352 *tptr++ = '\r';
353 ++cptr;
354 break;
355 case 'f':
356 *tptr++ = '\f';
357 ++cptr;
358 break;
359 case '\\':
360 *tptr++ = '\\';
361 ++cptr;
362 break;
363 case '"':
364 /* FALLTHROUGH */
365 case '\'':
366 /*
367 * While it isn't necessary to
368 * escape ' and ", let's accept
369 * them escaped and not complain.
370 * (XPG4 states that '\' should be
371 * ignored when not used in a
372 * valid escape sequence)
373 */
374 *tptr++ = '"';
375 ++cptr;
376 break;
377 default:
378 if (quote && *cptr == quote) {
379 *tptr++ = *cptr++;
380 } else if (isdigit((unsigned char) *cptr)) {
381 *tptr = 0;
382 for (i = 0; i < 3; ++i) {
383 if (!isdigit((unsigned char) *cptr))
384 break;
385 if (*cptr > '7')
386 warning(cptr, "octal number greater than 7?!");
387 *tptr *= 8;
388 *tptr += (*cptr - '0');
389 ++cptr;
390 }
391 } else {
392 warning(cptr, "unrecognized escape sequence; ignoring esacpe character");
393 }
394 break;
395 }
396 } else {
397 *tptr++ = *cptr++;
398 }
399 }
400 *tptr = '\0';
401 return (msg);
402}
403
404void
405MCParse(int fd)
406{
407 char *cptr, *str;
408 int setid, msgid;
409 char quote = 0;
410
411 /* XXX: init sethead? */
412
413 setid = 0;
414 while ((cptr = get_line(fd))) {
11
Calling 'get_line'
27
Returning from 'get_line'
28
Loop condition is true. Entering loop body
32
Loop condition is true. Entering loop body
415 if (*cptr == '$') {
29
Taking false branch
33
Assuming the condition is true
34
Taking true branch
416 ++cptr;
417 if (strncmp(cptr, "set", 3) == 0) {
35
Assuming the condition is true
36
Taking true branch
418 cptr += 3;
419 cptr = wskip(cptr);
37
Calling 'wskip'
420 setid = atoi(cptr);
421 MCAddSet(setid);
422 } else if (strncmp(cptr, "delset", 6) == 0) {
423 cptr += 6;
424 cptr = wskip(cptr);
425 setid = atoi(cptr);
426 MCDelSet(setid);
427 } else if (strncmp(cptr, "quote", 5) == 0) {
428 cptr += 5;
429 if (!*cptr)
430 quote = 0;
431 else {
432 cptr = wskip(cptr);
433 if (!*cptr)
434 quote = 0;
435 else
436 quote = *cptr;
437 }
438 } else if (ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char
)*cptr))
) {
439 ;
440 } else {
441 if (*cptr) {
442 cptr = wskip(cptr);
443 if (*cptr)
444 warning(cptr, "unrecognized line");
445 }
446 }
447 } else {
448 /*
449 * First check for (and eat) empty lines....
450 */
451 if (!*cptr)
30
Taking true branch
452 continue;
31
Execution continues on line 414
453 /*
454 * We have a digit? Start of a message. Else,
455 * syntax error.
456 */
457 if (isdigit((unsigned char) *cptr)) {
458 msgid = atoi(cptr);
459 cptr = cskip(cptr);
460 cptr = wskip(cptr);
461 /* if (*cptr) ++cptr; */
462 } else {
463 warning(cptr, "neither blank line nor start of a message id");
464 continue;
465 }
466 if (setid == 0) {
467 setid = NL_SETD1;
468 MCAddSet(setid);
469 }
470 /*
471 * If we have a message ID, but no message,
472 * then this means "delete this message id
473 * from the catalog".
474 */
475 if (!*cptr) {
476 MCDelMsg(msgid);
477 } else {
478 str = getmsg(fd, cptr, quote);
479 MCAddMsg(msgid, str);
480 }
481 }
482 }
483}
484
485/*
486 * Write message catalog.
487 *
488 * The message catalog is first converted from its internal to its
489 * external representation in a chunk of memory allocated for this
490 * purpose. Then the completed catalog is written. This approach
491 * avoids additional housekeeping variables and/or a lot of seeks
492 * that would otherwise be required.
493 */
494void
495MCWriteCat(int fd)
496{
497 int nsets; /* number of sets */
498 int nmsgs; /* number of msgs */
499 int string_size; /* total size of string pool */
500 int msgcat_size; /* total size of message catalog */
501 void *msgcat; /* message catalog data */
502 struct _nls_cat_hdr *cat_hdr;
503 struct _nls_set_hdr *set_hdr;
504 struct _nls_msg_hdr *msg_hdr;
505 char *strings;
506 struct _setT *set;
507 struct _msgT *msg;
508 int msg_index;
509 int msg_offset;
510
511 /* determine number of sets, number of messages, and size of the
512 * string pool */
513 nsets = 0;
514 nmsgs = 0;
515 string_size = 0;
516
517 LIST_FOREACH(set, &sethead, entries)for((set) = ((&sethead)->lh_first); (set)!= ((void *)0
); (set) = ((set)->entries.le_next))
{
518 nsets++;
519
520 LIST_FOREACH(msg, &set->msghead, entries)for((msg) = ((&set->msghead)->lh_first); (msg)!= ((
void *)0); (msg) = ((msg)->entries.le_next))
{
521 nmsgs++;
522 string_size += strlen(msg->str) + 1;
523 }
524 }
525
526#ifdef DEBUG
527 printf("number of sets: %d\n", nsets);
528 printf("number of msgs: %d\n", nmsgs);
529 printf("string pool size: %d\n", string_size);
530#endif
531
532 /* determine size and then allocate buffer for constructing external
533 * message catalog representation */
534 msgcat_size = sizeof(struct _nls_cat_hdr)
535 + (nsets * sizeof(struct _nls_set_hdr))
536 + (nmsgs * sizeof(struct _nls_msg_hdr))
537 + string_size;
538
539 msgcat = xmalloc(msgcat_size);
540 memset(msgcat, '\0', msgcat_size);
541
542 /* fill in msg catalog header */
543 cat_hdr = (struct _nls_cat_hdr *) msgcat;
544 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))
;
545 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))
;
546 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)))
;
547 cat_hdr->__msg_hdr_offset =
548 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
)))
;
549 cat_hdr->__msg_txt_offset =
550 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)))
551 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)))
;
552
553 /* compute offsets for set & msg header tables and string pool */
554 set_hdr = (struct _nls_set_hdr *) ((char *) msgcat +
555 sizeof(struct _nls_cat_hdr));
556 msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat +
557 sizeof(struct _nls_cat_hdr) +
558 nsets * sizeof(struct _nls_set_hdr));
559 strings = (char *) msgcat +
560 sizeof(struct _nls_cat_hdr) +
561 nsets * sizeof(struct _nls_set_hdr) +
562 nmsgs * sizeof(struct _nls_msg_hdr);
563
564 msg_index = 0;
565 msg_offset = 0;
566 LIST_FOREACH(set, &sethead, entries)for((set) = ((&sethead)->lh_first); (set)!= ((void *)0
); (set) = ((set)->entries.le_next))
{
567
568 nmsgs = 0;
569 LIST_FOREACH(msg, &set->msghead, entries)for((msg) = ((&set->msghead)->lh_first); (msg)!= ((
void *)0); (msg) = ((msg)->entries.le_next))
{
570 int msg_len = strlen(msg->str) + 1;
571
572 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
))
;
573 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))
;
574 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))
;
575
576 memcpy(strings, msg->str, msg_len);
577 strings += msg_len;
578 msg_offset += msg_len;
579
580 nmsgs++;
581 msg_hdr++;
582 }
583
584 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
))
;
585 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))
;
586 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))
;
587 msg_index += nmsgs;
588 set_hdr++;
589 }
590
591 /* write out catalog. XXX: should this be done in small chunks? */
592 write(fd, msgcat, msgcat_size);
593}
594
595void
596MCAddSet(int setId)
597{
598 struct _setT *p, *q;
599
600 if (setId <= 0) {
601 error(NULL((void *)0), "setId's must be greater than zero");
602 /* NOTREACHED */
603 }
604#if 0
605 /* XXX */
606 if (setId > NL_SETMAX) {
607 error(NULL((void *)0), "setId %d exceeds limit (%d)");
608 /* NOTREACHED */
609 }
610#endif
611
612 p = LIST_FIRST(&sethead)((&sethead)->lh_first);
613 q = NULL((void *)0);
614 for (; p != NULL((void *)0) && p->setId < setId; q = p, p = LIST_NEXT(p, entries)((p)->entries.le_next));
615
616 if (p && p->setId == setId) {
617 ;
618 } else {
619 p = xmalloc(sizeof(struct _setT));
620 memset(p, '\0', sizeof(struct _setT));
621 LIST_INIT(&p->msghead)do { ((&p->msghead)->lh_first) = ((void *)0); } while
(0)
;
622
623 p->setId = setId;
624
625 if (q == NULL((void *)0)) {
626 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)
;
627 } else {
628 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)
;
629 }
630 }
631
632 curSet = p;
633}
634
635void
636MCAddMsg(int msgId, const char *str)
637{
638 struct _msgT *p, *q;
639
640 if (!curSet)
641 error(NULL((void *)0), "can't specify a message when no set exists");
642
643 if (msgId <= 0) {
644 error(NULL((void *)0), "msgId's must be greater than zero");
645 /* NOTREACHED */
646 }
647#if 0
648 /* XXX */
649 if (msgId > NL_SETMAX) {
650 error(NULL((void *)0), "msgId %d exceeds limit (%d)");
651 /* NOTREACHED */
652 }
653#endif
654
655 p = LIST_FIRST(&curSet->msghead)((&curSet->msghead)->lh_first);
656 q = NULL((void *)0);
657 for (; p != NULL((void *)0) && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries)((p)->entries.le_next));
658
659 if (p && p->msgId == msgId) {
660 free(p->str);
661 } else {
662 p = xmalloc(sizeof(struct _msgT));
663 memset(p, '\0', sizeof(struct _msgT));
664
665 if (q == NULL((void *)0)) {
666 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)
;
667 } else {
668 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)
;
669 }
670 }
671
672 p->msgId = msgId;
673 p->str = xstrdup(str);
674}
675
676void
677MCDelSet(int setId)
678{
679 struct _setT *set;
680 struct _msgT *msg;
681
682 set = LIST_FIRST(&sethead)((&sethead)->lh_first);
683 for (; set != NULL((void *)0) && set->setId < setId;
684 set = LIST_NEXT(set, entries)((set)->entries.le_next));
685
686 if (set && set->setId == setId) {
687
688 msg = LIST_FIRST(&set->msghead)((&set->msghead)->lh_first);
689 while (msg) {
690 free(msg->str);
691 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)
;
692 }
693
694 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)
;
695 return;
696 }
697 warning(NULL((void *)0), "specified set doesn't exist");
698}
699
700void
701MCDelMsg(int msgId)
702{
703 struct _msgT *msg;
704
705 if (!curSet)
706 error(NULL((void *)0), "you can't delete a message before defining the set");
707
708 msg = LIST_FIRST(&curSet->msghead)((&curSet->msghead)->lh_first);
709 for (; msg != NULL((void *)0) && msg->msgId < msgId;
710 msg = LIST_NEXT(msg, entries)((msg)->entries.le_next));
711
712 if (msg && msg->msgId == msgId) {
713 free(msg->str);
714 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)
;
715 return;
716 }
717 warning(NULL((void *)0), "specified msg doesn't exist");
718}