1142662Sphantom/* ex:ts=4 2142662Sphantom */ 3142662Sphantom 4142662Sphantom/* $NetBSD: gencat.c,v 1.18 2003/10/27 00:12:43 lukem Exp $ */ 5142662Sphantom 6142662Sphantom/* 7142662Sphantom * Copyright (c) 1996 The NetBSD Foundation, Inc. 8142662Sphantom * All rights reserved. 9142662Sphantom * 10142662Sphantom * This code is derived from software contributed to The NetBSD Foundation 11142662Sphantom * by J.T. Conklin. 12142662Sphantom * 13142662Sphantom * Redistribution and use in source and binary forms, with or without 14142662Sphantom * modification, are permitted provided that the following conditions 15142662Sphantom * are met: 16142662Sphantom * 1. Redistributions of source code must retain the above copyright 17142662Sphantom * notice, this list of conditions and the following disclaimer. 18142662Sphantom * 2. Redistributions in binary form must reproduce the above copyright 19142662Sphantom * notice, this list of conditions and the following disclaimer in the 20142662Sphantom * documentation and/or other materials provided with the distribution. 21142662Sphantom * 22142662Sphantom * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23142662Sphantom * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24142662Sphantom * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25142662Sphantom * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26142662Sphantom * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27142662Sphantom * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28142662Sphantom * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29142662Sphantom * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30142662Sphantom * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31142662Sphantom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32142662Sphantom * POSSIBILITY OF SUCH DAMAGE. 33142662Sphantom */ 34142662Sphantom 357496Sjkh/*********************************************************** 367496SjkhCopyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. 377496Sjkh 387496Sjkh All Rights Reserved 397496Sjkh 407496SjkhPermission to use, copy, modify, and distribute this software and its 417496Sjkhdocumentation for any purpose and without fee is hereby granted, 427496Sjkhprovided that the above copyright notice appear in all copies and that 437496Sjkhboth that copyright notice and this permission notice appear in 447496Sjkhsupporting documentation, and that Alfalfa's name not be used in 457496Sjkhadvertising or publicity pertaining to distribution of the software 467496Sjkhwithout specific, written prior permission. 477496Sjkh 487496SjkhALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 497496SjkhALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 507496SjkhALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 517496SjkhANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 527496SjkhWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 537496SjkhARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 547496SjkhSOFTWARE. 557496Sjkh 567496SjkhIf you make any modifications, bugfixes or other changes to this software 577496Sjkhwe'd appreciate it if you could send a copy to us so we can keep things 587496Sjkhup-to-date. Many thanks. 597496Sjkh Kee Hinckley 607496Sjkh Alfalfa Software, Inc. 617496Sjkh 267 Allston St., #3 627496Sjkh Cambridge, MA 02139 USA 637496Sjkh nazgul@alfalfa.com 648874Srgrimes 657496Sjkh******************************************************************/ 667496Sjkh 6793218Scharnier#include <sys/cdefs.h> 6893218Scharnier__FBSDID("$FreeBSD$"); 6993218Scharnier 70142662Sphantom#define _NLS_PRIVATE 71142662Sphantom 72142662Sphantom#include <sys/types.h> 73142662Sphantom#include <sys/queue.h> 74142662Sphantom 75142662Sphantom#include <arpa/inet.h> /* for htonl() */ 76142662Sphantom 77142662Sphantom#include <ctype.h> 7827274Scharnier#include <err.h> 79142662Sphantom#include <fcntl.h> 80142662Sphantom#include <limits.h> 81142662Sphantom#include <nl_types.h> 827496Sjkh#include <stdio.h> 8378717Sdd#include <stdlib.h> 8478717Sdd#include <string.h> 859251Sache#include <unistd.h> 867496Sjkh 87142662Sphantomstruct _msgT { 88142662Sphantom long msgId; 89142662Sphantom char *str; 90199236Sedwin LIST_ENTRY(_msgT) entries; 91142662Sphantom}; 927496Sjkh 93142662Sphantomstruct _setT { 94142662Sphantom long setId; 95199236Sedwin LIST_HEAD(msghead, _msgT) msghead; 96199236Sedwin LIST_ENTRY(_setT) entries; 97142662Sphantom}; 987496Sjkh 99241737Sedstatic LIST_HEAD(sethead, _setT) sethead; 100142662Sphantomstatic struct _setT *curSet; 101142662Sphantom 102142662Sphantomstatic char *curline = NULL; 103142662Sphantomstatic long lineno = 0; 104142662Sphantom 105142662Sphantomstatic char *cskip(char *); 106142662Sphantomstatic void error(const char *); 107142662Sphantomstatic char *getline(int); 108142662Sphantomstatic char *getmsg(int, char *, char); 109142662Sphantomstatic void warning(const char *, const char *); 110142662Sphantomstatic char *wskip(char *); 111142662Sphantomstatic char *xstrdup(const char *); 112142662Sphantomstatic void *xmalloc(size_t); 113142662Sphantomstatic void *xrealloc(void *, size_t); 114142662Sphantom 115142662Sphantomvoid MCParse(int); 116142662Sphantomvoid MCReadCat(int); 117142662Sphantomvoid MCWriteCat(int); 118142662Sphantomvoid MCDelMsg(int); 119142662Sphantomvoid MCAddMsg(int, const char *); 120142662Sphantomvoid MCAddSet(int); 121142662Sphantomvoid MCDelSet(int); 122142662Sphantomvoid usage(void); 123142662Sphantomint main(int, char **); 124142662Sphantom 125142662Sphantomvoid 126201227Sedusage(void) 12727274Scharnier{ 128142662Sphantom fprintf(stderr, "usage: %s catfile msgfile ...\n", getprogname()); 129199236Sedwin exit(1); 1307496Sjkh} 1317496Sjkh 13272164Sphantomint 133142662Sphantommain(int argc, char **argv) 1347496Sjkh{ 135142662Sphantom int ofd, ifd; 136199236Sedwin char *catfile = NULL; 137142662Sphantom int c; 1388874Srgrimes 139142662Sphantom#define DEPRECATEDMSG 1 140142662Sphantom 141142662Sphantom#ifdef DEPRECATEDMSG 142142662Sphantom while ((c = getopt(argc, argv, "new")) != -1) { 143142662Sphantom#else 144142662Sphantom while ((c = getopt(argc, argv, "")) != -1) { 145142662Sphantom#endif 146142662Sphantom switch (c) { 147142662Sphantom#ifdef DEPRECATEDMSG 148142662Sphantom case 'n': 149142662Sphantom fprintf(stderr, "WARNING: Usage of \"-new\" argument is deprecated.\n"); 150142662Sphantom case 'e': 151142662Sphantom case 'w': 152142662Sphantom break; 153142662Sphantom#endif 154142662Sphantom case '?': 155142662Sphantom default: 156142662Sphantom usage(); 157142662Sphantom /* NOTREACHED */ 158142662Sphantom } 159142662Sphantom } 160142662Sphantom argc -= optind; 161142662Sphantom argv += optind; 162142662Sphantom 163142662Sphantom if (argc < 2) { 164142662Sphantom usage(); 165142662Sphantom /* NOTREACHED */ 166142662Sphantom } 167142662Sphantom catfile = *argv++; 168142662Sphantom 169142662Sphantom for (; *argv; argv++) { 170142662Sphantom if ((ifd = open(*argv, O_RDONLY)) < 0) 171142662Sphantom err(1, "Unable to read %s", *argv); 172142662Sphantom MCParse(ifd); 173142662Sphantom close(ifd); 174142662Sphantom } 175142662Sphantom 176142662Sphantom if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) 177142662Sphantom err(1, "Unable to create a new %s", catfile); 178142662Sphantom MCWriteCat(ofd); 179142662Sphantom exit(0); 180142662Sphantom} 181142662Sphantom 182142662Sphantomstatic void 183142662Sphantomwarning(const char *cptr, const char *msg) 184142662Sphantom{ 185142662Sphantom fprintf(stderr, "%s: %s on line %ld\n", getprogname(), msg, lineno); 186142662Sphantom fprintf(stderr, "%s\n", curline); 187142662Sphantom if (cptr) { 188142662Sphantom char *tptr; 189142662Sphantom for (tptr = curline; tptr < cptr; ++tptr) 190142662Sphantom putc(' ', stderr); 191142662Sphantom fprintf(stderr, "^\n"); 192142662Sphantom } 193142662Sphantom} 194142662Sphantom 195142662Sphantom#define CORRUPT() { error("corrupt message catalog"); } 196142662Sphantom#define NOMEM() { error("out of memory"); } 197142662Sphantom 198142662Sphantomstatic void 199142662Sphantomerror(const char *msg) 200142662Sphantom{ 201142662Sphantom warning(NULL, msg); 202142662Sphantom exit(1); 203142662Sphantom} 204142662Sphantom 205142662Sphantomstatic void * 206142662Sphantomxmalloc(size_t len) 207142662Sphantom{ 208142662Sphantom void *p; 209142662Sphantom 210142662Sphantom if ((p = malloc(len)) == NULL) 211142662Sphantom NOMEM(); 212142662Sphantom return (p); 213142662Sphantom} 214142662Sphantom 215142662Sphantomstatic void * 216142662Sphantomxrealloc(void *ptr, size_t size) 217142662Sphantom{ 218142662Sphantom if ((ptr = realloc(ptr, size)) == NULL) 219142662Sphantom NOMEM(); 220142662Sphantom return (ptr); 221142662Sphantom} 222142662Sphantom 223142662Sphantomstatic char * 224142662Sphantomxstrdup(const char *str) 225142662Sphantom{ 226142662Sphantom char *nstr; 227142662Sphantom 228142662Sphantom if ((nstr = strdup(str)) == NULL) 229142662Sphantom NOMEM(); 230142662Sphantom return (nstr); 231142662Sphantom} 232142662Sphantom 233142662Sphantomstatic char * 234142662Sphantomgetline(int fd) 235142662Sphantom{ 236142662Sphantom static long curlen = BUFSIZ; 237142662Sphantom static char buf[BUFSIZ], *bptr = buf, *bend = buf; 238142662Sphantom char *cptr, *cend; 239142662Sphantom long buflen; 240142662Sphantom 241142662Sphantom if (!curline) { 242142662Sphantom curline = xmalloc(curlen); 243142662Sphantom } 244142662Sphantom ++lineno; 245142662Sphantom 246142662Sphantom cptr = curline; 247142662Sphantom cend = curline + curlen; 248142662Sphantom for (;;) { 249142662Sphantom for (; bptr < bend && cptr < cend; ++cptr, ++bptr) { 250142662Sphantom if (*bptr == '\n') { 251142662Sphantom *cptr = '\0'; 252142662Sphantom ++bptr; 253142662Sphantom return (curline); 254142662Sphantom } else 255142662Sphantom *cptr = *bptr; 256142662Sphantom } 257142662Sphantom if (cptr == cend) { 258142662Sphantom cptr = curline = xrealloc(curline, curlen *= 2); 259142662Sphantom cend = curline + curlen; 260142662Sphantom } 261142662Sphantom if (bptr == bend) { 262142662Sphantom buflen = read(fd, buf, BUFSIZ); 263142662Sphantom if (buflen <= 0) { 264142662Sphantom if (cptr > curline) { 265142662Sphantom *cptr = '\0'; 266142662Sphantom return (curline); 267142662Sphantom } 268142662Sphantom return (NULL); 269142662Sphantom } 270142662Sphantom bend = buf + buflen; 271142662Sphantom bptr = buf; 272142662Sphantom } 273142662Sphantom } 274142662Sphantom} 275142662Sphantom 276142662Sphantomstatic char * 277142662Sphantomwskip(char *cptr) 278142662Sphantom{ 279142662Sphantom if (!*cptr || !isspace((unsigned char) *cptr)) { 280142662Sphantom warning(cptr, "expected a space"); 281142662Sphantom return (cptr); 282142662Sphantom } 283142662Sphantom while (*cptr && isspace((unsigned char) *cptr)) 284142662Sphantom ++cptr; 285142662Sphantom return (cptr); 286142662Sphantom} 287142662Sphantom 288142662Sphantomstatic char * 289142662Sphantomcskip(char *cptr) 290142662Sphantom{ 291142662Sphantom if (!*cptr || isspace((unsigned char) *cptr)) { 292142662Sphantom warning(cptr, "wasn't expecting a space"); 293142662Sphantom return (cptr); 294142662Sphantom } 295142662Sphantom while (*cptr && !isspace((unsigned char) *cptr)) 296142662Sphantom ++cptr; 297142662Sphantom return (cptr); 298142662Sphantom} 299142662Sphantom 300142662Sphantomstatic char * 301142662Sphantomgetmsg(int fd, char *cptr, char quote) 302142662Sphantom{ 303142662Sphantom static char *msg = NULL; 304142662Sphantom static long msglen = 0; 305142662Sphantom long clen, i; 306142662Sphantom char *tptr; 307142662Sphantom 308142662Sphantom if (quote && *cptr == quote) { 309142662Sphantom ++cptr; 310142662Sphantom } 311142662Sphantom 312142662Sphantom clen = strlen(cptr) + 1; 313142662Sphantom if (clen > msglen) { 314142662Sphantom if (msglen) 315142662Sphantom msg = xrealloc(msg, clen); 316142662Sphantom else 317142662Sphantom msg = xmalloc(clen); 318142662Sphantom msglen = clen; 319142662Sphantom } 320142662Sphantom tptr = msg; 321142662Sphantom 322142662Sphantom while (*cptr) { 323142662Sphantom if (quote && *cptr == quote) { 324142662Sphantom char *tmp; 325142662Sphantom tmp = cptr + 1; 326142662Sphantom if (*tmp && (!isspace((unsigned char) *tmp) || *wskip(tmp))) { 327142662Sphantom warning(cptr, "unexpected quote character, ignoring"); 328142662Sphantom *tptr++ = *cptr++; 329142662Sphantom } else { 330142662Sphantom *cptr = '\0'; 331142662Sphantom } 332142662Sphantom } else 333142662Sphantom if (*cptr == '\\') { 334142662Sphantom ++cptr; 335142662Sphantom switch (*cptr) { 336142662Sphantom case '\0': 337142662Sphantom cptr = getline(fd); 338142662Sphantom if (!cptr) 339142662Sphantom error("premature end of file"); 340142662Sphantom msglen += strlen(cptr); 341142662Sphantom i = tptr - msg; 342142662Sphantom msg = xrealloc(msg, msglen); 343142662Sphantom tptr = msg + i; 344142662Sphantom break; 345142662Sphantom 346142662Sphantom #define CASEOF(CS, CH) \ 347142662Sphantom case CS: \ 348142662Sphantom *tptr++ = CH; \ 349142662Sphantom ++cptr; \ 350142662Sphantom break; \ 351142662Sphantom 352142662Sphantom CASEOF('n', '\n'); 353142662Sphantom CASEOF('t', '\t'); 354142662Sphantom CASEOF('v', '\v'); 355142662Sphantom CASEOF('b', '\b'); 356142662Sphantom CASEOF('r', '\r'); 357142662Sphantom CASEOF('f', '\f'); 358142662Sphantom CASEOF('"', '"'); 359142662Sphantom CASEOF('\\', '\\'); 360142662Sphantom 361142662Sphantom default: 362142662Sphantom if (quote && *cptr == quote) { 363142662Sphantom *tptr++ = *cptr++; 364142662Sphantom } else if (isdigit((unsigned char) *cptr)) { 365142662Sphantom *tptr = 0; 366142662Sphantom for (i = 0; i < 3; ++i) { 367142662Sphantom if (!isdigit((unsigned char) *cptr)) 368142662Sphantom break; 369142662Sphantom if (*cptr > '7') 370142662Sphantom warning(cptr, "octal number greater than 7?!"); 371142662Sphantom *tptr *= 8; 372142662Sphantom *tptr += (*cptr - '0'); 373142662Sphantom ++cptr; 374142662Sphantom } 375142662Sphantom } else { 376142662Sphantom warning(cptr, "unrecognized escape sequence"); 377142662Sphantom } 378142662Sphantom break; 379142662Sphantom } 380142662Sphantom } else { 381142662Sphantom *tptr++ = *cptr++; 382142662Sphantom } 383142662Sphantom } 384142662Sphantom *tptr = '\0'; 385142662Sphantom return (msg); 386142662Sphantom} 387142662Sphantom 388142662Sphantomvoid 389142662SphantomMCParse(int fd) 390142662Sphantom{ 391142662Sphantom char *cptr, *str; 392142662Sphantom int setid, msgid = 0; 393142662Sphantom char quote = 0; 394142662Sphantom 395142662Sphantom /* XXX: init sethead? */ 396142662Sphantom 397142662Sphantom while ((cptr = getline(fd))) { 398142662Sphantom if (*cptr == '$') { 399142662Sphantom ++cptr; 400142662Sphantom if (strncmp(cptr, "set", 3) == 0) { 401142662Sphantom cptr += 3; 402142662Sphantom cptr = wskip(cptr); 403142662Sphantom setid = atoi(cptr); 404142662Sphantom MCAddSet(setid); 405142662Sphantom msgid = 0; 406142662Sphantom } else if (strncmp(cptr, "delset", 6) == 0) { 407142662Sphantom cptr += 6; 408142662Sphantom cptr = wskip(cptr); 409142662Sphantom setid = atoi(cptr); 410142662Sphantom MCDelSet(setid); 411142662Sphantom } else if (strncmp(cptr, "quote", 5) == 0) { 412142662Sphantom cptr += 5; 413142662Sphantom if (!*cptr) 414142662Sphantom quote = 0; 415199236Sedwin else { 416142662Sphantom cptr = wskip(cptr); 417142662Sphantom if (!*cptr) 418142662Sphantom quote = 0; 419142662Sphantom else 420142662Sphantom quote = *cptr; 421199236Sedwin } 422142662Sphantom } else if (isspace((unsigned char) *cptr)) { 423142662Sphantom ; 424199236Sedwin } else { 425142662Sphantom if (*cptr) { 426142662Sphantom cptr = wskip(cptr); 427142662Sphantom if (*cptr) 428142662Sphantom warning(cptr, "unrecognized line"); 429142662Sphantom } 430199236Sedwin } 431199236Sedwin } else { 432142662Sphantom /* 433142662Sphantom * First check for (and eat) empty lines.... 434142662Sphantom */ 435142662Sphantom if (!*cptr) 436142662Sphantom continue; 437142662Sphantom /* 438142662Sphantom * We have a digit? Start of a message. Else, 439142662Sphantom * syntax error. 440142662Sphantom */ 441142662Sphantom if (isdigit((unsigned char) *cptr)) { 442142662Sphantom msgid = atoi(cptr); 443142662Sphantom cptr = cskip(cptr); 444142662Sphantom cptr = wskip(cptr); 445142662Sphantom /* if (*cptr) ++cptr; */ 446142662Sphantom } else { 447142662Sphantom warning(cptr, "neither blank line nor start of a message id"); 448142662Sphantom continue; 449199236Sedwin } 450142662Sphantom /* 451142662Sphantom * If we have a message ID, but no message, 452142662Sphantom * then this means "delete this message id 453142662Sphantom * from the catalog". 454142662Sphantom */ 455142662Sphantom if (!*cptr) { 456142662Sphantom MCDelMsg(msgid); 457199236Sedwin } else { 458142662Sphantom str = getmsg(fd, cptr, quote); 459142662Sphantom MCAddMsg(msgid, str); 460199236Sedwin } 461199236Sedwin } 4627496Sjkh } 463142662Sphantom} 464142662Sphantom 465142662Sphantom/* 466142662Sphantom * Write message catalog. 467142662Sphantom * 468142662Sphantom * The message catalog is first converted from its internal to its 469142662Sphantom * external representation in a chunk of memory allocated for this 470142662Sphantom * purpose. Then the completed catalog is written. This approach 471142662Sphantom * avoids additional housekeeping variables and/or a lot of seeks 472142662Sphantom * that would otherwise be required. 473142662Sphantom */ 474142662Sphantomvoid 475142662SphantomMCWriteCat(int fd) 476142662Sphantom{ 477142662Sphantom int nsets; /* number of sets */ 478142662Sphantom int nmsgs; /* number of msgs */ 479142662Sphantom int string_size; /* total size of string pool */ 480142662Sphantom int msgcat_size; /* total size of message catalog */ 481142662Sphantom void *msgcat; /* message catalog data */ 482142662Sphantom struct _nls_cat_hdr *cat_hdr; 483142662Sphantom struct _nls_set_hdr *set_hdr; 484142662Sphantom struct _nls_msg_hdr *msg_hdr; 485142662Sphantom char *strings; 486142662Sphantom struct _setT *set; 487142662Sphantom struct _msgT *msg; 488142662Sphantom int msg_index; 489142662Sphantom int msg_offset; 490142662Sphantom 491142662Sphantom /* determine number of sets, number of messages, and size of the 492142662Sphantom * string pool */ 493142662Sphantom nsets = 0; 494142662Sphantom nmsgs = 0; 495142662Sphantom string_size = 0; 496142662Sphantom 497142662Sphantom for (set = sethead.lh_first; set != NULL; 498142662Sphantom set = set->entries.le_next) { 499142662Sphantom nsets++; 500142662Sphantom 501142662Sphantom for (msg = set->msghead.lh_first; msg != NULL; 502142662Sphantom msg = msg->entries.le_next) { 503142662Sphantom nmsgs++; 504142662Sphantom string_size += strlen(msg->str) + 1; 505142662Sphantom } 506142662Sphantom } 507142662Sphantom 508142662Sphantom#ifdef DEBUG 509142662Sphantom printf("number of sets: %d\n", nsets); 510142662Sphantom printf("number of msgs: %d\n", nmsgs); 511142662Sphantom printf("string pool size: %d\n", string_size); 512142662Sphantom#endif 513142662Sphantom 514142662Sphantom /* determine size and then allocate buffer for constructing external 515142662Sphantom * message catalog representation */ 516142662Sphantom msgcat_size = sizeof(struct _nls_cat_hdr) 517142662Sphantom + (nsets * sizeof(struct _nls_set_hdr)) 518142662Sphantom + (nmsgs * sizeof(struct _nls_msg_hdr)) 519142662Sphantom + string_size; 520142662Sphantom 521142662Sphantom msgcat = xmalloc(msgcat_size); 522142662Sphantom memset(msgcat, '\0', msgcat_size); 523142662Sphantom 524142662Sphantom /* fill in msg catalog header */ 525142662Sphantom cat_hdr = (struct _nls_cat_hdr *) msgcat; 526142662Sphantom cat_hdr->__magic = htonl(_NLS_MAGIC); 527142662Sphantom cat_hdr->__nsets = htonl(nsets); 528142662Sphantom cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr)); 529142662Sphantom cat_hdr->__msg_hdr_offset = 530142662Sphantom htonl(nsets * sizeof(struct _nls_set_hdr)); 531142662Sphantom cat_hdr->__msg_txt_offset = 532142662Sphantom htonl(nsets * sizeof(struct _nls_set_hdr) + 533142662Sphantom nmsgs * sizeof(struct _nls_msg_hdr)); 534142662Sphantom 535142662Sphantom /* compute offsets for set & msg header tables and string pool */ 536142684Sru set_hdr = (struct _nls_set_hdr *)(void *)((char *)msgcat + 537142662Sphantom sizeof(struct _nls_cat_hdr)); 538142684Sru msg_hdr = (struct _nls_msg_hdr *)(void *)((char *)msgcat + 539142662Sphantom sizeof(struct _nls_cat_hdr) + 540142662Sphantom nsets * sizeof(struct _nls_set_hdr)); 541142662Sphantom strings = (char *) msgcat + 542142662Sphantom sizeof(struct _nls_cat_hdr) + 543142662Sphantom nsets * sizeof(struct _nls_set_hdr) + 544142662Sphantom nmsgs * sizeof(struct _nls_msg_hdr); 545142662Sphantom 546142662Sphantom msg_index = 0; 547142662Sphantom msg_offset = 0; 548142662Sphantom for (set = sethead.lh_first; set != NULL; 549142662Sphantom set = set->entries.le_next) { 550142662Sphantom 551142662Sphantom nmsgs = 0; 552142662Sphantom for (msg = set->msghead.lh_first; msg != NULL; 553142662Sphantom msg = msg->entries.le_next) { 554142662Sphantom int msg_len = strlen(msg->str) + 1; 555142662Sphantom 556142662Sphantom msg_hdr->__msgno = htonl(msg->msgId); 557142662Sphantom msg_hdr->__msglen = htonl(msg_len); 558142662Sphantom msg_hdr->__offset = htonl(msg_offset); 559142662Sphantom 560142662Sphantom memcpy(strings, msg->str, msg_len); 561142662Sphantom strings += msg_len; 562142662Sphantom msg_offset += msg_len; 563142662Sphantom 564142662Sphantom nmsgs++; 565142662Sphantom msg_hdr++; 566142662Sphantom } 567142662Sphantom 568142662Sphantom set_hdr->__setno = htonl(set->setId); 569142662Sphantom set_hdr->__nmsgs = htonl(nmsgs); 570142662Sphantom set_hdr->__index = htonl(msg_index); 571142662Sphantom msg_index += nmsgs; 572142662Sphantom set_hdr++; 573142662Sphantom } 574142662Sphantom 575142662Sphantom /* write out catalog. XXX: should this be done in small chunks? */ 576142662Sphantom write(fd, msgcat, msgcat_size); 577142662Sphantom} 578142662Sphantom 579142662Sphantomvoid 580142662SphantomMCAddSet(int setId) 581142662Sphantom{ 582142662Sphantom struct _setT *p, *q; 583142662Sphantom 584142662Sphantom if (setId <= 0) { 585142662Sphantom error("setId's must be greater than zero"); 586142662Sphantom /* NOTREACHED */ 587142662Sphantom } 588142662Sphantom if (setId > NL_SETMAX) { 589142662Sphantom error("setId exceeds limit"); 590142662Sphantom /* NOTREACHED */ 591142662Sphantom } 592142662Sphantom 593142662Sphantom p = sethead.lh_first; 594142662Sphantom q = NULL; 595142662Sphantom for (; p != NULL && p->setId < setId; q = p, p = p->entries.le_next); 596142662Sphantom 597142662Sphantom if (p && p->setId == setId) { 598142662Sphantom ; 599199236Sedwin } else { 600142662Sphantom p = xmalloc(sizeof(struct _setT)); 601142662Sphantom memset(p, '\0', sizeof(struct _setT)); 602142662Sphantom LIST_INIT(&p->msghead); 603142662Sphantom 604142662Sphantom p->setId = setId; 605142662Sphantom 606142662Sphantom if (q == NULL) { 607142662Sphantom LIST_INSERT_HEAD(&sethead, p, entries); 608142662Sphantom } else { 609142662Sphantom LIST_INSERT_AFTER(q, p, entries); 610199236Sedwin } 611199236Sedwin } 6127496Sjkh 613142662Sphantom curSet = p; 614142662Sphantom} 615142662Sphantom 616142662Sphantomvoid 617142662SphantomMCAddMsg(int msgId, const char *str) 6187496Sjkh{ 619142662Sphantom struct _msgT *p, *q; 6207496Sjkh 621142662Sphantom if (!curSet) 622142662Sphantom error("can't specify a message when no set exists"); 623142662Sphantom 624142662Sphantom if (msgId <= 0) { 625142662Sphantom error("msgId's must be greater than zero"); 626142662Sphantom /* NOTREACHED */ 627142662Sphantom } 628142662Sphantom if (msgId > NL_MSGMAX) { 629142662Sphantom error("msgID exceeds limit"); 630142662Sphantom /* NOTREACHED */ 631199236Sedwin } 6327496Sjkh 633142662Sphantom p = curSet->msghead.lh_first; 634142662Sphantom q = NULL; 635142662Sphantom for (; p != NULL && p->msgId < msgId; q = p, p = p->entries.le_next); 6367496Sjkh 637142662Sphantom if (p && p->msgId == msgId) { 638142662Sphantom free(p->str); 639142662Sphantom } else { 640142662Sphantom p = xmalloc(sizeof(struct _msgT)); 641142662Sphantom memset(p, '\0', sizeof(struct _msgT)); 6427496Sjkh 643142662Sphantom if (q == NULL) { 644142662Sphantom LIST_INSERT_HEAD(&curSet->msghead, p, entries); 645142662Sphantom } else { 646142662Sphantom LIST_INSERT_AFTER(q, p, entries); 647142662Sphantom } 648142662Sphantom } 6497496Sjkh 650142662Sphantom p->msgId = msgId; 651142662Sphantom p->str = xstrdup(str); 652199236Sedwin} 6537496Sjkh 654142662Sphantomvoid 655142662SphantomMCDelSet(int setId) 656142662Sphantom{ 657142662Sphantom struct _setT *set; 658142662Sphantom struct _msgT *msg; 659142662Sphantom 660142662Sphantom set = sethead.lh_first; 661142662Sphantom for (; set != NULL && set->setId < setId; set = set->entries.le_next); 662142662Sphantom 663142662Sphantom if (set && set->setId == setId) { 664142662Sphantom 665142662Sphantom msg = set->msghead.lh_first; 666142662Sphantom while (msg) { 667142662Sphantom free(msg->str); 668142662Sphantom LIST_REMOVE(msg, entries); 669199236Sedwin } 670142662Sphantom 671142662Sphantom LIST_REMOVE(set, entries); 672142662Sphantom return; 673199236Sedwin } 674142662Sphantom warning(NULL, "specified set doesn't exist"); 675199236Sedwin} 676142662Sphantom 677142662Sphantomvoid 678142662SphantomMCDelMsg(int msgId) 679142662Sphantom{ 680142662Sphantom struct _msgT *msg; 681142662Sphantom 682142662Sphantom if (!curSet) 683142662Sphantom error("you can't delete a message before defining the set"); 684142662Sphantom 685142662Sphantom msg = curSet->msghead.lh_first; 686142662Sphantom for (; msg != NULL && msg->msgId < msgId; msg = msg->entries.le_next); 687142662Sphantom 688142662Sphantom if (msg && msg->msgId == msgId) { 689142662Sphantom free(msg->str); 690142662Sphantom LIST_REMOVE(msg, entries); 691142662Sphantom return; 692199236Sedwin } 693142662Sphantom warning(NULL, "specified msg doesn't exist"); 6947496Sjkh} 695