Annotation of src/usr.bin/gencat/genlib.c, Revision 1.1
1.1 ! deraadt 1: /* -*-c++-*- */
! 2:
! 3:
! 4: /***********************************************************
! 5: Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
! 6:
! 7: All Rights Reserved
! 8:
! 9: Permission to use, copy, modify, and distribute this software and its
! 10: documentation for any purpose and without fee is hereby granted,
! 11: provided that the above copyright notice appear in all copies and that
! 12: both that copyright notice and this permission notice appear in
! 13: supporting documentation, and that Alfalfa's name not be used in
! 14: advertising or publicity pertaining to distribution of the software
! 15: without specific, written prior permission.
! 16:
! 17: ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
! 18: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
! 19: ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
! 20: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
! 21: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
! 22: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
! 23: SOFTWARE.
! 24:
! 25: If you make any modifications, bugfixes or other changes to this software
! 26: we'd appreciate it if you could send a copy to us so we can keep things
! 27: up-to-date. Many thanks.
! 28: Kee Hinckley
! 29: Alfalfa Software, Inc.
! 30: 267 Allston St., #3
! 31: Cambridge, MA 02139 USA
! 32: nazgul@alfalfa.com
! 33:
! 34: ******************************************************************/
! 35:
! 36: /* Edit History
! 37:
! 38: 02/25/91 5 nazgul Added flag for MS byteorder
! 39: 01/14/91 4 nazgul Off by one on number specified entries
! 40: */
! 41:
! 42: #include <stdio.h>
! 43: #include <stdlib.h>
! 44: #include <string.h>
! 45: #ifdef SYSV
! 46: #include <sys/types.h>
! 47: #include <unistd.h>
! 48: #define L_SET SEEK_SET
! 49: #define L_INCR SEEK_CUR
! 50: #include <memory.h>
! 51: static int bcopy(src, dst, length)
! 52: char *src, *dst;
! 53: int length;
! 54: {
! 55: memcpy(dst, src, length);
! 56: }
! 57: static int bzero(b, length)
! 58: char *b;
! 59: int length;
! 60: {
! 61: memset(b, '\0', length);
! 62: }
! 63: #endif
! 64: #include <sys/file.h>
! 65: #include <ctype.h>
! 66: #include "msgcat.h"
! 67: #include "gencat.h"
! 68:
! 69: static char *curline = NULL;
! 70: static long lineno = 0;
! 71:
! 72: static void warning(cptr, msg)
! 73: char *cptr;
! 74: char *msg;
! 75: {
! 76: fprintf(stderr, "gencat: %s on line %d\n", msg, lineno);
! 77: fprintf(stderr, "%s\n", curline);
! 78: if (cptr) {
! 79: char *tptr;
! 80: for (tptr = curline; tptr < cptr; ++tptr) putc(' ', stderr);
! 81: fprintf(stderr, "^\n");
! 82: }
! 83: }
! 84:
! 85: static void error(cptr, msg)
! 86: char *cptr;
! 87: char *msg;
! 88: {
! 89: warning(cptr, msg);
! 90: exit(1);
! 91: }
! 92:
! 93: static void corrupt() {
! 94: error(NULL, "corrupt message catalog");
! 95: }
! 96: static void nomem() {
! 97: error(NULL, "out of memory");
! 98: }
! 99:
! 100: static char *getline(fd)
! 101: int fd;
! 102: {
! 103: static long len = 0, curlen = BUFSIZ;
! 104: static char buf[BUFSIZ], *bptr = buf, *bend = buf;
! 105: char *cptr, *cend;
! 106: long buflen;
! 107:
! 108: if (!curline) {
! 109: curline = (char *) malloc(curlen);
! 110: if (!curline) nomem();
! 111: }
! 112: ++lineno;
! 113:
! 114: cptr = curline;
! 115: cend = curline + curlen;
! 116: while (True) {
! 117: for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
! 118: if (*bptr == '\n') {
! 119: *cptr = '\0';
! 120: ++bptr;
! 121: return(curline);
! 122: } else *cptr = *bptr;
! 123: }
! 124: if (bptr == bend) {
! 125: buflen = read(fd, buf, BUFSIZ);
! 126: if (buflen <= 0) {
! 127: if (cptr > curline) {
! 128: *cptr = '\0';
! 129: return(curline);
! 130: }
! 131: return(NULL);
! 132: }
! 133: bend = buf + buflen;
! 134: bptr = buf;
! 135: }
! 136: if (cptr == cend) {
! 137: cptr = curline = (char *) realloc(curline, curlen *= 2);
! 138: cend = curline + curlen;
! 139: }
! 140: }
! 141: }
! 142:
! 143:
! 144: static char *token(cptr)
! 145: char *cptr;
! 146: {
! 147: static char tok[MAXTOKEN+1];
! 148: char *tptr = tok;
! 149:
! 150: while (*cptr && isspace(*cptr)) ++cptr;
! 151: while (*cptr && !isspace(*cptr)) *tptr++ = *cptr++;
! 152: *tptr = '\0';
! 153: return(tok);
! 154: }
! 155: static char *wskip(cptr)
! 156: char *cptr;
! 157: {
! 158: if (!*cptr || !isspace(*cptr)) {
! 159: warning(cptr, "expected a space");
! 160: return(cptr);
! 161: }
! 162: while (*cptr && isspace(*cptr)) ++cptr;
! 163: return(cptr);
! 164: }
! 165: static char *cskip(cptr)
! 166: char *cptr;
! 167: {
! 168: if (!*cptr || isspace(*cptr)) {
! 169: warning(cptr, "wasn't expecting a space");
! 170: return(cptr);
! 171: }
! 172: while (*cptr && !isspace(*cptr)) ++cptr;
! 173: return(cptr);
! 174: }
! 175:
! 176: static char *getmsg(fd, cptr, quote)
! 177: int fd;
! 178: char *cptr;
! 179: char quote;
! 180: {
! 181: static char *msg = NULL;
! 182: static long msglen = 0;
! 183: long clen, i;
! 184: char *tptr;
! 185:
! 186: int needq;
! 187:
! 188: if (quote && *cptr == quote) {
! 189: needq = True;
! 190: ++cptr;
! 191: } else needq = False;
! 192:
! 193: clen = strlen(cptr) + 1;
! 194: if (clen > msglen) {
! 195: if (msglen) msg = (char *) realloc(msg, clen);
! 196: else msg = (char *) malloc(clen);
! 197: msglen = clen;
! 198: }
! 199: tptr = msg;
! 200:
! 201: while (*cptr) {
! 202: if (quote && *cptr == quote) {
! 203: char *tmp;
! 204: tmp = cptr+1;
! 205: if (*tmp && (!isspace(*tmp) || *wskip(tmp))) {
! 206: warning(cptr, "unexpected quote character, ignoreing");
! 207: *tptr++ = *cptr++;
! 208: } else {
! 209: *cptr = '\0';
! 210: }
! 211: } else if (*cptr == '\\') {
! 212: ++cptr;
! 213: switch (*cptr) {
! 214: case '\0':
! 215: cptr = getline(fd);
! 216: if (!cptr) error(NULL, "premature end of file");
! 217: msglen += strlen(cptr);
! 218: i = tptr - msg;
! 219: msg = (char *) realloc(msg, msglen);
! 220: tptr = msg + i;
! 221: break;
! 222: case 'n':
! 223: *tptr++ = '\n';
! 224: ++cptr;
! 225: break;
! 226: case 't':
! 227: *tptr++ = '\t';
! 228: ++cptr;
! 229: break;
! 230: case 'v':
! 231: *tptr++ = '\v';
! 232: ++cptr;
! 233: break;
! 234: case 'b':
! 235: *tptr++ = '\b';
! 236: ++cptr;
! 237: break;
! 238: case 'r':
! 239: *tptr++ = '\r';
! 240: ++cptr;
! 241: break;
! 242: case 'f':
! 243: *tptr++ = '\f';
! 244: ++cptr;
! 245: break;
! 246: case '\\':
! 247: *tptr++ = '\\';
! 248: ++cptr;
! 249: break;
! 250: default:
! 251: if (isdigit(*cptr)) {
! 252: *tptr = 0;
! 253: for (i = 0; i < 3; ++i) {
! 254: if (!isdigit(*cptr)) break;
! 255: if (*cptr > '7') warning(cptr, "octal number greater than 7?!");
! 256: *tptr *= 8;
! 257: *tptr += (*cptr - '0');
! 258: ++cptr;
! 259: }
! 260: } else {
! 261: warning(cptr, "unrecognized escape sequence");
! 262: }
! 263: }
! 264: } else {
! 265: *tptr++ = *cptr++;
! 266: }
! 267: }
! 268: *tptr = '\0';
! 269: return(msg);
! 270: }
! 271:
! 272:
! 273:
! 274: static char *dupstr(ostr)
! 275: char *ostr;
! 276: {
! 277: char *nstr;
! 278:
! 279: nstr = (char *) malloc(strlen(ostr) + 1);
! 280: if (!nstr) error(NULL, "unable to allocate storage");
! 281: strcpy(nstr, ostr);
! 282: return(nstr);
! 283: }
! 284:
! 285:
! 286: /*
! 287: * The Global Stuff
! 288: */
! 289:
! 290:
! 291: typedef struct _msgT {
! 292: long msgId;
! 293: char *str;
! 294: char *hconst;
! 295: long offset;
! 296: struct _msgT *prev, *next;
! 297: } msgT;
! 298: typedef struct _setT {
! 299: long setId;
! 300: char *hconst;
! 301: msgT *first, *last;
! 302: struct _setT *prev, *next;
! 303: } setT;
! 304: typedef struct {
! 305: setT *first, *last;
! 306: } catT;
! 307:
! 308: static setT *curSet;
! 309: static catT *cat;
! 310:
! 311: /*
! 312: * Find the current byte order. There are of course some others, but this will do
! 313: * for now. Note that all we care about is "long".
! 314: */
! 315: long MCGetByteOrder() {
! 316: long l = 0x00010203;
! 317: char *cptr = (char *) &l;
! 318:
! 319: if (cptr[0] == 0 && cptr[1] == 1 && cptr[2] == 2 && cptr[3] == 3)
! 320: return MC68KByteOrder;
! 321: else return MCn86ByteOrder;
! 322: }
! 323:
! 324:
! 325: void MCParse(
! 326: #if PROTO
! 327: int fd)
! 328: #else
! 329: fd)
! 330: int fd;
! 331: #endif
! 332: {
! 333: char *cptr, *str;
! 334: int setid, msgid = 0;
! 335: char hconst[MAXTOKEN+1];
! 336: char quote = 0;
! 337: int i;
! 338:
! 339: if (!cat) {
! 340: cat = (catT *) malloc(sizeof(catT));
! 341: if (!cat) nomem();
! 342: bzero(cat, sizeof(catT));
! 343: }
! 344:
! 345: hconst[0] = '\0';
! 346:
! 347: while (cptr = getline(fd)) {
! 348: if (*cptr == '$') {
! 349: ++cptr;
! 350: if (strncmp(cptr, "set", 3) == 0) {
! 351: cptr += 3;
! 352: cptr = wskip(cptr);
! 353: setid = atoi(cptr);
! 354: cptr = cskip(cptr);
! 355: if (*cptr) cptr = wskip(cptr);
! 356: if (*cptr == '#') {
! 357: ++cptr;
! 358: MCAddSet(setid, token(cptr));
! 359: } else MCAddSet(setid, NULL);
! 360: msgid = 0;
! 361: } else if (strncmp(cptr, "delset", 6) == 0) {
! 362: cptr += 6;
! 363: cptr = wskip(cptr);
! 364: setid = atoi(cptr);
! 365: MCDelSet(setid);
! 366: } else if (strncmp(cptr, "quote", 5) == 0) {
! 367: cptr += 5;
! 368: if (!*cptr) quote = 0;
! 369: else {
! 370: cptr = wskip(cptr);
! 371: if (!*cptr) quote = 0;
! 372: else quote = *cptr;
! 373: }
! 374: } else if (isspace(*cptr)) {
! 375: cptr = wskip(cptr);
! 376: if (*cptr == '#') {
! 377: ++cptr;
! 378: strcpy(hconst, token(cptr));
! 379: }
! 380: } else {
! 381: if (*cptr) {
! 382: cptr = wskip(cptr);
! 383: if (*cptr) warning(cptr, "unrecognized line");
! 384: }
! 385: }
! 386: } else {
! 387: if (isdigit(*cptr) || *cptr == '#') {
! 388: if (*cptr == '#') {
! 389: ++msgid;
! 390: ++cptr;
! 391: if (!*cptr) {
! 392: MCAddMsg(msgid, "", hconst);
! 393: hconst[0] = '\0';
! 394: continue;
! 395: }
! 396: if (!isspace(*cptr)) warning(cptr, "expected a space");
! 397: ++cptr;
! 398: if (!*cptr) {
! 399: MCAddMsg(msgid, "", hconst);
! 400: hconst[0] = '\0';
! 401: continue;
! 402: }
! 403: } else {
! 404: msgid = atoi(cptr);
! 405: cptr = cskip(cptr);
! 406: cptr = wskip(cptr);
! 407: /* if (*cptr) ++cptr; */
! 408: }
! 409: if (!*cptr) MCDelMsg(msgid);
! 410: else {
! 411: str = getmsg(fd, cptr, quote);
! 412: MCAddMsg(msgid, str, hconst);
! 413: hconst[0] = '\0';
! 414: }
! 415: }
! 416: }
! 417: }
! 418: }
! 419:
! 420: void MCReadCat(
! 421: #if PROTO
! 422: int fd)
! 423: #else
! 424: fd)
! 425: int fd;
! 426: #endif
! 427: {
! 428: MCHeaderT mcHead;
! 429: MCMsgT mcMsg;
! 430: MCSetT mcSet;
! 431: msgT *msg;
! 432: setT *set;
! 433: int i;
! 434: char *data;
! 435:
! 436: cat = (catT *) malloc(sizeof(catT));
! 437: if (!cat) nomem();
! 438: bzero(cat, sizeof(catT));
! 439:
! 440: if (read(fd, &mcHead, sizeof(mcHead)) != sizeof(mcHead)) corrupt();
! 441: if (strncmp(mcHead.magic, MCMagic, MCMagicLen) != 0) corrupt();
! 442: if (mcHead.majorVer != MCMajorVer) error(NULL, "unrecognized catalog version");
! 443: if ((mcHead.flags & MCGetByteOrder()) == 0) error(NULL, "wrong byte order");
! 444:
! 445: if (lseek(fd, mcHead.firstSet, L_SET) == -1) corrupt();
! 446:
! 447: while (True) {
! 448: if (read(fd, &mcSet, sizeof(mcSet)) != sizeof(mcSet)) corrupt();
! 449: if (mcSet.invalid) continue;
! 450:
! 451: set = (setT *) malloc(sizeof(setT));
! 452: if (!set) nomem();
! 453: bzero(set, sizeof(*set));
! 454: if (cat->first) {
! 455: cat->last->next = set;
! 456: set->prev = cat->last;
! 457: cat->last = set;
! 458: } else cat->first = cat->last = set;
! 459:
! 460: set->setId = mcSet.setId;
! 461:
! 462: /* Get the data */
! 463: if (mcSet.dataLen) {
! 464: data = (char *) malloc(mcSet.dataLen);
! 465: if (!data) nomem();
! 466: if (lseek(fd, mcSet.data.off, L_SET) == -1) corrupt();
! 467: if (read(fd, data, mcSet.dataLen) != mcSet.dataLen) corrupt();
! 468: if (lseek(fd, mcSet.u.firstMsg, L_SET) == -1) corrupt();
! 469:
! 470: for (i = 0; i < mcSet.numMsgs; ++i) {
! 471: if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg)) corrupt();
! 472: if (mcMsg.invalid) {
! 473: --i;
! 474: continue;
! 475: }
! 476:
! 477: msg = (msgT *) malloc(sizeof(msgT));
! 478: if (!msg) nomem();
! 479: bzero(msg, sizeof(*msg));
! 480: if (set->first) {
! 481: set->last->next = msg;
! 482: msg->prev = set->last;
! 483: set->last = msg;
! 484: } else set->first = set->last = msg;
! 485:
! 486: msg->msgId = mcMsg.msgId;
! 487: msg->str = dupstr((char *) (data + mcMsg.msg.off));
! 488: }
! 489: free(data);
! 490: }
! 491: if (!mcSet.nextSet) break;
! 492: if (lseek(fd, mcSet.nextSet, L_SET) == -1) corrupt();
! 493: }
! 494: }
! 495:
! 496:
! 497: static void printS(fd, str)
! 498: int fd;
! 499: char *str;
! 500: {
! 501: write(fd, str, strlen(str));
! 502: }
! 503: static void printL(fd, l)
! 504: int fd;
! 505: long l;
! 506: {
! 507: char buf[32];
! 508: sprintf(buf, "%ld", l);
! 509: write(fd, buf, strlen(buf));
! 510: }
! 511: static void printLX(fd, l)
! 512: int fd;
! 513: long l;
! 514: {
! 515: char buf[32];
! 516: sprintf(buf, "%lx", l);
! 517: write(fd, buf, strlen(buf));
! 518: }
! 519:
! 520: static void genconst(fd, type, setConst, msgConst, val)
! 521: int fd;
! 522: int type;
! 523: char *setConst;
! 524: char *msgConst;
! 525: long val;
! 526: {
! 527: switch (type) {
! 528: case MCLangC:
! 529: if (!msgConst) {
! 530: printS(fd, "\n#define ");
! 531: printS(fd, setConst);
! 532: printS(fd, "Set");
! 533: } else {
! 534: printS(fd, "#define ");
! 535: printS(fd, setConst);
! 536: printS(fd, msgConst);
! 537: }
! 538: printS(fd, "\t0x");
! 539: printLX(fd, val);
! 540: printS(fd, "\n");
! 541: break;
! 542: case MCLangCPlusPlus:
! 543: case MCLangANSIC:
! 544: if (!msgConst) {
! 545: printS(fd, "\nconst long ");
! 546: printS(fd, setConst);
! 547: printS(fd, "Set");
! 548: } else {
! 549: printS(fd, "const long ");
! 550: printS(fd, setConst);
! 551: printS(fd, msgConst);
! 552: }
! 553: printS(fd, "\t= ");
! 554: printL(fd, val);
! 555: printS(fd, ";\n");
! 556: break;
! 557: default:
! 558: error(NULL, "not a recognized (programming) language type");
! 559: }
! 560: }
! 561:
! 562: void MCWriteConst(
! 563: #if PROTO
! 564: int fd, int type, int orConsts)
! 565: #else
! 566: fd, type, orConsts)
! 567: int fd;
! 568: int type;
! 569: int orConsts;
! 570: #endif
! 571: {
! 572: msgT *msg;
! 573: setT *set;
! 574: long id;
! 575:
! 576: if (orConsts && (type == MCLangC || type == MCLangCPlusPlus || type == MCLangANSIC)) {
! 577: printS(fd, "/* Use these Macros to compose and decompose setId's and msgId's */\n");
! 578: printS(fd, "#ifndef MCMakeId\n");
! 579: printS(fd, "# define MCMakeId(s,m)\t(unsigned long)(((unsigned short)s<<(sizeof(short)*8))\\\n");
! 580: printS(fd, "\t\t\t\t\t|(unsigned short)m)\n");
! 581: printS(fd, "# define MCSetId(id)\t(unsigned int) (id >> (sizeof(short) * 8))\n");
! 582: printS(fd, "# define MCMsgId(id)\t(unsigned int) ((id << (sizeof(short) * 8))\\\n");
! 583: printS(fd, "\t\t\t\t\t>> (sizeof(short) * 8))\n");
! 584: printS(fd, "#endif\n");
! 585: }
! 586:
! 587: for (set = cat->first; set; set = set->next) {
! 588: if (set->hconst) genconst(fd, type, set->hconst, NULL, set->setId);
! 589:
! 590: for (msg = set->first; msg; msg = msg->next) {
! 591: if (msg->hconst) {
! 592: if (orConsts) id = MCMakeId(set->setId, msg->msgId);
! 593: else id = msg->msgId;
! 594: genconst(fd, type, set->hconst, msg->hconst, id);
! 595: free(msg->hconst);
! 596: msg->hconst = NULL;
! 597: }
! 598: }
! 599: if (set->hconst) {
! 600: free(set->hconst);
! 601: set->hconst = NULL;
! 602: }
! 603: }
! 604: }
! 605:
! 606: void MCWriteCat(
! 607: #if PROTO
! 608: int fd)
! 609: #else
! 610: fd)
! 611: int fd;
! 612: #endif
! 613: {
! 614: MCHeaderT mcHead;
! 615: int cnt;
! 616: setT *set;
! 617: msgT *msg;
! 618: MCSetT mcSet;
! 619: MCMsgT mcMsg;
! 620: off_t pos;
! 621:
! 622: bcopy(MCMagic, mcHead.magic, MCMagicLen);
! 623: mcHead.majorVer = MCMajorVer;
! 624: mcHead.minorVer = MCMinorVer;
! 625: mcHead.flags = MCGetByteOrder();
! 626: mcHead.firstSet = 0; /* We'll be back to set this in a minute */
! 627:
! 628: for (cnt = 0, set = cat->first; set; set = set->next) ++cnt;
! 629: mcHead.numSets = cnt;
! 630:
! 631: lseek(fd, 0L, L_SET);
! 632: write(fd, &mcHead, sizeof(mcHead));
! 633: mcHead.firstSet = lseek(fd, 0, L_INCR);
! 634: lseek(fd, 0L, L_SET);
! 635: write(fd, &mcHead, sizeof(mcHead));
! 636:
! 637: for (set = cat->first; set; set = set->next) {
! 638: bzero(&mcSet, sizeof(mcSet));
! 639:
! 640: mcSet.setId = set->setId;
! 641: mcSet.invalid = False;
! 642:
! 643: /* The rest we'll have to come back and change in a moment */
! 644: pos = lseek(fd, 0, L_INCR);
! 645: write(fd, &mcSet, sizeof(mcSet));
! 646:
! 647: /* Now write all the string data */
! 648: mcSet.data.off = lseek(fd, 0, L_INCR);
! 649: cnt = 0;
! 650: for (msg = set->first; msg; msg = msg->next) {
! 651: msg->offset = lseek(fd, 0, L_INCR) - mcSet.data.off;
! 652: mcSet.dataLen += write(fd, msg->str, strlen(msg->str) + 1);
! 653: ++cnt;
! 654: }
! 655: mcSet.u.firstMsg = lseek(fd, 0, L_INCR);
! 656: mcSet.numMsgs = cnt;
! 657:
! 658: /* Now write the message headers */
! 659: for (msg = set->first; msg; msg = msg->next) {
! 660: mcMsg.msgId = msg->msgId;
! 661: mcMsg.msg.off = msg->offset;
! 662: mcMsg.invalid = False;
! 663: write(fd, &mcMsg, sizeof(mcMsg));
! 664: }
! 665:
! 666: /* Go back and fix things up */
! 667:
! 668: if (set == cat->last) {
! 669: mcSet.nextSet = 0;
! 670: lseek(fd, pos, L_SET);
! 671: write(fd, &mcSet, sizeof(mcSet));
! 672: } else {
! 673: mcSet.nextSet = lseek(fd, 0, L_INCR);
! 674: lseek(fd, pos, L_SET);
! 675: write(fd, &mcSet, sizeof(mcSet));
! 676: lseek(fd, mcSet.nextSet, L_SET);
! 677: }
! 678: }
! 679: }
! 680:
! 681:
! 682: void MCAddSet(
! 683: #if PROTO
! 684: int setId, char *hconst)
! 685: #else
! 686: setId, hconst)
! 687: int setId;
! 688: char *hconst;
! 689: #endif
! 690: {
! 691: setT *set;
! 692:
! 693: if (setId <= 0) {
! 694: error(NULL, "setId's must be greater than zero");
! 695: return;
! 696: }
! 697:
! 698: if (hconst && !*hconst) hconst = NULL;
! 699: for (set = cat->first; set; set = set->next) {
! 700: if (set->setId == setId) {
! 701: if (set->hconst && hconst) free(set->hconst);
! 702: set->hconst = NULL;
! 703: break;
! 704: } else if (set->setId > setId) {
! 705: setT *newSet;
! 706:
! 707: newSet = (setT *) malloc(sizeof(setT));
! 708: if (!newSet) nomem();
! 709: bzero(newSet, sizeof(setT));
! 710: newSet->prev = set->prev;
! 711: newSet->next = set;
! 712: if (set->prev) set->prev->next = newSet;
! 713: else cat->first = newSet;
! 714: set->prev = newSet;
! 715: set = newSet;
! 716: break;
! 717: }
! 718: }
! 719: if (!set) {
! 720: set = (setT *) malloc(sizeof(setT));
! 721: if (!set) nomem();
! 722: bzero(set, sizeof(setT));
! 723:
! 724: if (cat->first) {
! 725: set->prev = cat->last;
! 726: set->next = NULL;
! 727: cat->last->next = set;
! 728: cat->last = set;
! 729: } else {
! 730: set->prev = set->next = NULL;
! 731: cat->first = cat->last = set;
! 732: }
! 733: }
! 734: set->setId = setId;
! 735: if (hconst) set->hconst = dupstr(hconst);
! 736: curSet = set;
! 737: }
! 738:
! 739: void MCAddMsg(
! 740: #if PROTO
! 741: int msgId, char *str, char *hconst)
! 742: #else
! 743: msgId, str, hconst)
! 744: int msgId;
! 745: char *str;
! 746: char *hconst;
! 747: #endif
! 748: {
! 749: msgT *msg;
! 750:
! 751: if (!curSet) error(NULL, "can't specify a message when no set exists");
! 752:
! 753: if (msgId <= 0) {
! 754: error(NULL, "msgId's must be greater than zero");
! 755: return;
! 756: }
! 757:
! 758: if (hconst && !*hconst) hconst = NULL;
! 759: for (msg = curSet->first; msg; msg = msg->next) {
! 760: if (msg->msgId == msgId) {
! 761: if (msg->hconst && hconst) free(msg->hconst);
! 762: if (msg->str) free(msg->str);
! 763: msg->hconst = msg->str = NULL;
! 764: break;
! 765: } else if (msg->msgId > msgId) {
! 766: msgT *newMsg;
! 767:
! 768: newMsg = (msgT *) malloc(sizeof(msgT));
! 769: if (!newMsg) nomem();
! 770: bzero(newMsg, sizeof(msgT));
! 771: newMsg->prev = msg->prev;
! 772: newMsg->next = msg;
! 773: if (msg->prev) msg->prev->next = newMsg;
! 774: else curSet->first = newMsg;
! 775: msg->prev = newMsg;
! 776: msg = newMsg;
! 777: break;
! 778: }
! 779: }
! 780: if (!msg) {
! 781: msg = (msgT *) malloc(sizeof(msgT));
! 782: if (!msg) nomem();
! 783: bzero(msg, sizeof(msgT));
! 784:
! 785: if (curSet->first) {
! 786: msg->prev = curSet->last;
! 787: msg->next = NULL;
! 788: curSet->last->next = msg;
! 789: curSet->last = msg;
! 790: } else {
! 791: msg->prev = msg->next = NULL;
! 792: curSet->first = curSet->last = msg;
! 793: }
! 794: }
! 795: msg->msgId = msgId;
! 796: if (hconst) msg->hconst = dupstr(hconst);
! 797: msg->str = dupstr(str);
! 798: }
! 799:
! 800: void MCDelSet(
! 801: #if PROTO
! 802: int setId)
! 803: #else
! 804: setId)
! 805: int setId;
! 806: #endif
! 807: {
! 808: setT *set;
! 809: msgT *msg;
! 810:
! 811: for (set = cat->first; set; set = set->next) {
! 812: if (set->setId == setId) {
! 813: for (msg = set->first; msg; msg = msg->next) {
! 814: if (msg->hconst) free(msg->hconst);
! 815: if (msg->str) free(msg->str);
! 816: free(msg);
! 817: }
! 818: if (set->hconst) free(set->hconst);
! 819:
! 820: if (set->prev) set->prev->next = set->next;
! 821: else cat->first = set->next;
! 822:
! 823: if (set->next) set->next->prev = set->prev;
! 824: else cat->last = set->prev;
! 825:
! 826: free(set);
! 827: return;
! 828: } else if (set->setId > setId) break;
! 829: }
! 830: warning(NULL, "specified set doesn't exist");
! 831: }
! 832:
! 833: void MCDelMsg(
! 834: #if PROTO
! 835: int msgId)
! 836: #else
! 837: msgId)
! 838: int msgId;
! 839: #endif
! 840: {
! 841: msgT *msg;
! 842:
! 843: if (!curSet) error(NULL, "you can't delete a message before defining the set");
! 844:
! 845: for (msg = curSet->first; msg; msg = msg->next) {
! 846: if (msg->msgId == msgId) {
! 847: if (msg->hconst) free(msg->hconst);
! 848: if (msg->str) free(msg->str);
! 849:
! 850: if (msg->prev) msg->prev->next = msg->next;
! 851: else curSet->first = msg->next;
! 852:
! 853: if (msg->next) msg->next->prev = msg->prev;
! 854: else curSet->last = msg->prev;
! 855:
! 856: free(msg);
! 857: return;
! 858: } else if (msg->msgId > msgId) break;
! 859: }
! 860: warning(NULL, "specified msg doesn't exist");
! 861: }
! 862:
! 863: void MCDumpcat(fp)
! 864: FILE *fp;
! 865: {
! 866: msgT *msg;
! 867: setT *set;
! 868:
! 869: if (!cat) {
! 870: fprintf(stderr, "No catalog open\n");
! 871: exit (1);
! 872: }
! 873:
! 874: for (set = cat->first; set; set = set->next) {
! 875: fprintf(fp, "$set %d", set->setId);
! 876: if (set->hconst)
! 877: fprintf(fp, " # %s", set->hconst);
! 878: fprintf(fp, "\n\n");
! 879:
! 880: for (msg = set->first; msg; msg = msg->next) {
! 881: if (msg->hconst)
! 882: fprintf(fp, "# %s\n", msg->hconst);
! 883: fprintf(fp, "%d\t%s\n", msg->msgId, msg->str);
! 884: }
! 885: fprintf(fp, "\n");
! 886: }
! 887:
! 888: }