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