| File: | src/usr.bin/gencat/gencat.c |
| Warning: | line 690, column 4 Attempt to free released memory |
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 < bend && cptr < cend; ++cptr, ++bptr) { | |||
| 240 | if (*bptr == '\n') { | |||
| 241 | *cptr = '\0'; | |||
| 242 | ++bptr; | |||
| 243 | return (curline); | |||
| 244 | } else | |||
| 245 | *cptr = *bptr; | |||
| 246 | } | |||
| 247 | if (bptr == bend) { | |||
| 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 == cend) { | |||
| 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 && *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 | ||||
| 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 == 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 | */ | |||
| 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
| |||
| 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 | } |