| File: | src/usr.bin/gencat/gencat.c |
| Warning: | line 336, column 13 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | /*********************************************************** | ||||
| 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 | case '?': | ||||
| 143 | default: | ||||
| 144 | usage(); | ||||
| 145 | /* NOTREACHED */ | ||||
| 146 | } | ||||
| 147 | } | ||||
| 148 | argc -= optind; | ||||
| 149 | argv += optind; | ||||
| 150 | |||||
| 151 | if (argc < 2) { | ||||
| 152 | usage(); | ||||
| 153 | /* NOTREACHED */ | ||||
| 154 | } | ||||
| 155 | catfile = *argv++; | ||||
| 156 | |||||
| 157 | for (; *argv; argv++) { | ||||
| 158 | if ((ifd = open(*argv, O_RDONLY0x0000)) == -1) | ||||
| 159 | err(1, "Unable to read %s", *argv); | ||||
| 160 | MCParse(ifd); | ||||
| 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 | |||||
| 170 | static void | ||||
| 171 | warning(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 | |||||
| 182 | static void | ||||
| 183 | error(char *cptr, char *msg) | ||||
| 184 | { | ||||
| 185 | warning(cptr, msg); | ||||
| 186 | exit(1); | ||||
| 187 | } | ||||
| 188 | |||||
| 189 | static void | ||||
| 190 | nomem(void) | ||||
| 191 | { | ||||
| 192 | error(NULL((void *)0), "out of memory"); | ||||
| 193 | } | ||||
| 194 | |||||
| 195 | static void * | ||||
| 196 | xmalloc(size_t len) | ||||
| 197 | { | ||||
| 198 | void *p; | ||||
| 199 | |||||
| 200 | if ((p = malloc(len)) == NULL((void *)0)) | ||||
| 201 | nomem(); | ||||
| 202 | return (p); | ||||
| 203 | } | ||||
| 204 | |||||
| 205 | static void * | ||||
| 206 | xrealloc(void *ptr, size_t size) | ||||
| 207 | { | ||||
| 208 | if ((ptr = realloc(ptr, size)) == NULL((void *)0)) | ||||
| 209 | nomem(); | ||||
| 210 | return (ptr); | ||||
| 211 | } | ||||
| 212 | |||||
| 213 | static char * | ||||
| 214 | xstrdup(const char *str) | ||||
| 215 | { | ||||
| 216 | char *nstr; | ||||
| 217 | |||||
| 218 | if ((nstr = strdup(str)) == NULL((void *)0)) | ||||
| 219 | nomem(); | ||||
| 220 | return (nstr); | ||||
| 221 | } | ||||
| 222 | |||||
| 223 | static char * | ||||
| 224 | get_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
| ||||
| 232 | curline = xmalloc(curlen); | ||||
| 233 | } | ||||
| 234 | ++lineno; | ||||
| 235 | |||||
| 236 | cptr = curline; | ||||
| 237 | cend = curline + curlen; | ||||
| 238 | for (;;) { | ||||
| 239 | for (; bptr
| ||||
| 240 | if (*bptr == '\n') { | ||||
| 241 | *cptr = '\0'; | ||||
| 242 | ++bptr; | ||||
| 243 | return (curline); | ||||
| 244 | } else | ||||
| 245 | *cptr = *bptr; | ||||
| 246 | } | ||||
| 247 | if (bptr
| ||||
| 248 | buflen = read(fd, buf, BUFSIZ1024); | ||||
| 249 | if (buflen <= 0) { | ||||
| 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
| ||||
| 260 | cptr = curline = xrealloc(curline, curlen *= 2); | ||||
| 261 | cend = curline + curlen; | ||||
| 262 | } | ||||
| 263 | } | ||||
| 264 | } | ||||
| 265 | |||||
| 266 | static char * | ||||
| 267 | wskip(char *cptr) | ||||
| 268 | { | ||||
| 269 | if (!*cptr || !ISSPACE(*cptr)(isascii((unsigned char)*cptr) && isspace((unsigned char )*cptr))) { | ||||
| 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 | |||||
| 278 | static char * | ||||
| 279 | cskip(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 | |||||
| 290 | static char * | ||||
| 291 | getmsg(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
| ||||
| 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
| ||||
| 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 | |||||
| 404 | void | ||||
| 405 | MCParse(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))) { | ||||
| 415 | if (*cptr == '$') { | ||||
| 416 | ++cptr; | ||||
| 417 | if (strncmp(cptr, "set", 3) == 0) { | ||||
| 418 | cptr += 3; | ||||
| 419 | cptr = wskip(cptr); | ||||
| 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) | ||||
| 452 | continue; | ||||
| 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
| ||||
| 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 | */ | ||||
| 494 | void | ||||
| 495 | MCWriteCat(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 | |||||
| 595 | void | ||||
| 596 | MCAddSet(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 | |||||
| 635 | void | ||||
| 636 | MCAddMsg(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 | |||||
| 676 | void | ||||
| 677 | MCDelSet(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 | |||||
| 700 | void | ||||
| 701 | MCDelMsg(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 | } |