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