Annotation of src/usr.bin/gencat/genlib.c, Revision 1.1.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: }