1 /* $FreeBSD: src/usr.bin/gencat/genlib.c,v 1.8.6.3 2002/02/19 13:21:16 phantom Exp $ */
2 /* $DragonFly: src/usr.bin/gencat/Attic/genlib.c,v 1.2 2003/06/17 04:29:27 dillon Exp $ */
4 /***********************************************************
5 Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
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.
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
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.
29 Alfalfa Software, Inc.
31 Cambridge, MA 02139 USA
34 ******************************************************************/
36 #include <sys/types.h>
47 static char *curline = NULL;
48 static long lineno = 0;
51 warning(char *cptr, const char *msg)
53 warnx("%s on line %ld\n%s", msg, lineno, (curline == NULL ? "" : curline) );
56 for (tptr = curline; tptr < cptr; ++tptr) putc(' ', stderr);
57 fprintf(stderr, "^\n");
62 error(char *cptr, const char *msg)
70 error(NULL, "corrupt message catalog");
75 error(NULL, "out of memory");
81 static size_t curlen = BUFSIZ;
82 static char buf[BUFSIZ], *bptr = buf, *bend = buf;
87 curline = (char *) malloc(curlen);
88 if (!curline) nomem();
93 cend = curline + curlen;
95 for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
100 } else *cptr = *bptr;
103 buflen = read(fd, buf, BUFSIZ);
105 if (cptr > curline) {
115 cptr = curline = (char *) realloc(curline, curlen *= 2);
116 cend = curline + curlen;
124 static char tok[MAXTOKEN+1];
127 while (*cptr && isspace((unsigned char)*cptr)) ++cptr;
128 while (*cptr && !isspace((unsigned char)*cptr)) *tptr++ = *cptr++;
136 if (!*cptr || !isspace((unsigned char)*cptr)) {
137 warning(cptr, "expected a space");
140 while (*cptr && isspace((unsigned char)*cptr)) ++cptr;
147 if (!*cptr || isspace((unsigned char)*cptr)) {
148 warning(cptr, "wasn't expecting a space");
151 while (*cptr && !isspace((unsigned char)*cptr)) ++cptr;
156 getmsg(int fd, char *cptr, char quote)
158 static char *msg = NULL;
159 static size_t msglen = 0;
164 if (quote && *cptr == quote) {
167 } else needq = FALSE;
169 clen = strlen(cptr) + 1;
171 if (msglen) msg = (char *) realloc(msg, clen);
172 else msg = (char *) malloc(clen);
178 if (quote && *cptr == quote) {
181 if (*tmp && (!isspace((unsigned char)*tmp) || *wskip(tmp))) {
182 warning(cptr, "unexpected quote character, ignoring");
187 } else if (*cptr == '\\') {
192 if (!cptr) error(NULL, "premature end of file");
193 msglen += strlen(cptr);
195 msg = (char *) realloc(msg, msglen);
199 #define CASEOF(CS, CH) \
216 if (isdigit((unsigned char)*cptr)) {
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?!");
222 *tptr += (*cptr - '0');
227 warning(cptr, "unrecognized escape sequence");
239 dupstr(const char *ostr)
244 if (!nstr) error(NULL, "unable to allocate storage");
252 typedef struct _msgT {
257 struct _msgT *prev, *next;
260 typedef struct _setT {
264 struct _setT *prev, *next;
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".
279 MCGetByteOrder(void) {
281 char *cptr = (char *) &l;
283 if (cptr[0] == 0 && cptr[1] == 1 && cptr[2] == 2 && cptr[3] == 3)
284 return MC68KByteOrder;
285 else return MCn86ByteOrder;
292 int setid, msgid = 0;
293 char hconst[MAXTOKEN+1];
297 cat = (catT *) malloc(sizeof(catT));
299 bzero(cat, sizeof(catT));
304 while ((cptr = getline(fd)) != NULL) {
307 if (strncmp(cptr, "set", 3) == 0) {
312 if (*cptr) cptr = wskip(cptr);
315 MCAddSet(setid, token(cptr));
316 } else MCAddSet(setid, NULL);
318 } else if (strncmp(cptr, "delset", 6) == 0) {
323 } else if (strncmp(cptr, "quote", 5) == 0) {
325 if (!*cptr) quote = 0;
328 if (!*cptr) quote = 0;
331 } else if (isspace((unsigned char)*cptr)) {
335 strcpy(hconst, token(cptr));
340 if (*cptr) warning(cptr, "unrecognized line");
344 if (isdigit((unsigned char)*cptr) || *cptr == '#') {
349 MCAddMsg(msgid, "", hconst);
353 if (!isspace((unsigned char)*cptr)) warning(cptr, "expected a space");
356 MCAddMsg(msgid, "", hconst);
364 /* if (*cptr) ++cptr; */
366 if (!*cptr) MCDelMsg(msgid);
368 str = getmsg(fd, cptr, quote);
369 MCAddMsg(msgid, str, hconst);
388 cat = (catT *) malloc(sizeof(catT));
390 bzero(cat, sizeof(catT));
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");
397 if (lseek(fd, mcHead.firstSet, L_SET) == -1) corrupt();
400 if (read(fd, &mcSet, sizeof(mcSet)) != sizeof(mcSet)) corrupt();
401 if (mcSet.invalid) continue;
403 set = (setT *) malloc(sizeof(setT));
405 bzero(set, sizeof(*set));
407 cat->last->next = set;
408 set->prev = cat->last;
410 } else cat->first = cat->last = set;
412 set->setId = mcSet.setId;
416 data = (char *) malloc((size_t)mcSet.dataLen);
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();
422 for (i = 0; i < mcSet.numMsgs; ++i) {
423 if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg)) corrupt();
429 msg = (msgT *) malloc(sizeof(msgT));
431 bzero(msg, sizeof(*msg));
433 set->last->next = msg;
434 msg->prev = set->last;
436 } else set->first = set->last = msg;
438 msg->msgId = mcMsg.msgId;
439 msg->str = dupstr((char *) (data + mcMsg.msg.off));
443 if (!mcSet.nextSet) break;
444 if (lseek(fd, mcSet.nextSet, L_SET) == -1) corrupt();
450 printS(int fd, const char *str)
452 write(fd, str, strlen(str));
456 printL(int fd, long l)
459 sprintf(buf, "%ld", l);
460 write(fd, buf, strlen(buf));
464 printLX(int fd, long l)
467 sprintf(buf, "%lx", l);
468 write(fd, buf, strlen(buf));
472 genconst(int fd, int type, char *setConst, char *msgConst, long val)
477 printS(fd, "\n#define ");
478 printS(fd, setConst);
481 printS(fd, "#define ");
482 printS(fd, setConst);
483 printS(fd, msgConst);
489 case MCLangCPlusPlus:
492 printS(fd, "\nconst long ");
493 printS(fd, setConst);
496 printS(fd, "const long ");
497 printS(fd, setConst);
498 printS(fd, msgConst);
505 error(NULL, "not a recognized (programming) language type");
510 MCWriteConst(int fd, int type, int orConsts)
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");
527 for (set = cat->first; set; set = set->next) {
528 if (set->hconst) genconst(fd, type, set->hconst, NULL, set->setId);
530 for (msg = set->first; msg; msg = msg->next) {
532 if (orConsts) id = MCMakeId(set->setId, msg->msgId);
533 else id = msg->msgId;
534 genconst(fd, type, set->hconst, msg->hconst, id);
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 */
564 error(NULL, "cannot write empty catalog set");
566 for (cnt = 0, set = cat->first; set; set = set->next) ++cnt;
567 mcHead.numSets = cnt;
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));
575 for (set = cat->first; set; set = set->next) {
576 bzero(&mcSet, sizeof(mcSet));
578 mcSet.setId = set->setId;
579 mcSet.invalid = FALSE;
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));
585 /* Now write all the string data */
586 mcSet.data.off = lseek(fd, (off_t)0L, L_INCR);
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);
593 mcSet.u.firstMsg = lseek(fd, (off_t)0L, L_INCR);
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));
604 /* Go back and fix things up */
606 if (set == cat->last) {
608 lseek(fd, pos, L_SET);
609 write(fd, &mcSet, sizeof(mcSet));
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);
620 MCAddSet(int setId, char *hconst)
625 error(NULL, "setId's must be greater than zero");
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);
635 } else if (set->setId > setId) {
638 newSet = (setT *) malloc(sizeof(setT));
639 if (!newSet) nomem();
640 bzero(newSet, sizeof(setT));
641 newSet->prev = set->prev;
643 if (set->prev) set->prev->next = newSet;
644 else cat->first = newSet;
651 set = (setT *) malloc(sizeof(setT));
653 bzero(set, sizeof(setT));
656 set->prev = cat->last;
658 cat->last->next = set;
661 set->prev = set->next = NULL;
662 cat->first = cat->last = set;
666 if (hconst) set->hconst = dupstr(hconst);
671 MCAddMsg(int msgId, const char *str, char *hconst)
676 error(NULL, "can't specify a message when no set exists");
679 error(NULL, "msgId's must be greater than zero");
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;
690 } else if (msg->msgId > msgId) {
693 newMsg = (msgT *) malloc(sizeof(msgT));
694 if (!newMsg) nomem();
695 bzero(newMsg, sizeof(msgT));
696 newMsg->prev = msg->prev;
698 if (msg->prev) msg->prev->next = newMsg;
699 else curSet->first = newMsg;
706 msg = (msgT *) malloc(sizeof(msgT));
708 bzero(msg, sizeof(msgT));
711 msg->prev = curSet->last;
713 curSet->last->next = msg;
716 msg->prev = msg->next = NULL;
717 curSet->first = curSet->last = msg;
721 if (hconst) msg->hconst = dupstr(hconst);
722 msg->str = dupstr(str);
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);
738 if (set->hconst) free(set->hconst);
740 if (set->prev) set->prev->next = set->next;
741 else cat->first = set->next;
743 if (set->next) set->next->prev = set->prev;
744 else cat->last = set->prev;
748 } else if (set->setId > setId) break;
750 warning(NULL, "specified set doesn't exist");
759 error(NULL, "you can't delete a message before defining the set");
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);
766 if (msg->prev) msg->prev->next = msg->next;
767 else curSet->first = msg->next;
769 if (msg->next) msg->next->prev = msg->prev;
770 else curSet->last = msg->prev;
774 } else if (msg->msgId > msgId) break;
776 warning(NULL, "specified msg doesn't exist");
779 #if 0 /* this function is unsed and looks like debug thing */
789 errx(1, "no catalog open");
791 for (set = cat->first; set; set = set->next) {
792 fprintf(fp, "$set %ld", set->setId);
794 fprintf(fp, " # %s", set->hconst);
797 for (msg = set->first; msg; msg = msg->next) {
799 fprintf(fp, "# %s\n", msg->hconst);
800 fprintf(fp, "%ld\t%s\n", msg->msgId, msg->str);