source: vendor/FreeBSD-usr.bin/current/genlib.c@ 2362

Last change on this file since 2362 was 1308, checked in by bird, 21 years ago

Initial revision

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