]>
git.cameronkatri.com Git - apple_cmds.git/blob - adv_cmds/gencat/genlib.c
1 /***********************************************************
2 Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
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.
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
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.
26 Alfalfa Software, Inc.
28 Cambridge, MA 02139 USA
31 ******************************************************************/
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 $");
44 #include <machine/endian.h>
45 /* libkern/OSByteOrder is needed for the 64 bit byte swap */
46 #include <libkern/OSByteOrder.h>
49 #define htonll(x) OSSwapHostToBigInt64(x)
50 #define ntohll(x) OSSwapBigToHostInt64(x)
53 static char *curline
= NULL
;
54 static long lineno
= 0;
57 warning(char *cptr
, const char *msg
)
59 warnx("%s on line %ld\n%s", msg
, lineno
, (curline
== NULL
? "" : curline
) );
62 for (tptr
= curline
; tptr
< cptr
; ++tptr
) putc(' ', stderr
);
63 fprintf(stderr
, "^\n");
68 error(char *cptr
, const char *msg
)
76 error(NULL
, "corrupt message catalog");
81 error(NULL
, "out of memory");
85 gencat_getline(int fd
)
87 static size_t curlen
= BUFSIZ
;
88 static char buf
[BUFSIZ
], *bptr
= buf
, *bend
= buf
;
93 curline
= (char *) malloc(curlen
);
94 if (!curline
) nomem();
99 cend
= curline
+ curlen
;
101 for (; bptr
< bend
&& cptr
< cend
; ++cptr
, ++bptr
) {
106 } else *cptr
= *bptr
;
109 buflen
= read(fd
, buf
, BUFSIZ
);
111 if (cptr
> curline
) {
121 cptr
= curline
= (char *) realloc(curline
, curlen
*= 2);
122 if (!curline
) nomem();
123 cend
= curline
+ curlen
;
131 static char tok
[MAXTOKEN
+1];
134 while (*cptr
&& isspace((unsigned char)*cptr
)) ++cptr
;
135 while (*cptr
&& !isspace((unsigned char)*cptr
)) *tptr
++ = *cptr
++;
143 if (!*cptr
|| !isspace((unsigned char)*cptr
)) {
144 warning(cptr
, "expected a space");
147 while (*cptr
&& isspace((unsigned char)*cptr
)) ++cptr
;
154 if (!*cptr
|| isspace((unsigned char)*cptr
)) {
155 warning(cptr
, "wasn't expecting a space");
158 while (*cptr
&& !isspace((unsigned char)*cptr
)) ++cptr
;
163 getmsg(int fd
, char *cptr
, char quote
)
165 static char *msg
= NULL
;
166 static size_t msglen
= 0;
171 if (quote
&& *cptr
== quote
) {
174 } else needq
= FALSE
;
176 clen
= strlen(cptr
) + 1;
178 if (msglen
) msg
= (char *) realloc(msg
, clen
);
179 else msg
= (char *) malloc(clen
);
186 if (quote
&& *cptr
== quote
) {
189 if (*tmp
&& (!isspace((unsigned char)*tmp
) || *wskip(tmp
))) {
190 warning(cptr
, "unexpected quote character, ignoring");
195 } else if (*cptr
== '\\') {
199 cptr
= gencat_getline(fd
);
200 if (!cptr
) error(NULL
, "premature end of file");
201 msglen
+= strlen(cptr
);
203 msg
= (char *) realloc(msg
, msglen
);
208 #define CASEOF(CS, CH) \
225 if (isdigit((unsigned char)*cptr
)) {
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?!");
231 *tptr
+= (*cptr
- '0');
236 warning(cptr
, "unrecognized escape sequence");
248 dupstr(const char *ostr
)
253 if (!nstr
) error(NULL
, "unable to allocate storage");
261 typedef struct _msgT
{
266 struct _msgT
*prev
, *next
;
269 typedef struct _setT
{
273 struct _setT
*prev
, *next
;
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".
288 MCGetByteOrder(void) {
290 char *cptr
= (char *) &l
;
292 if (cptr
[0] == 0 && cptr
[1] == 1 && cptr
[2] == 2 && cptr
[3] == 3)
293 return MC68KByteOrder
;
294 else return MCn86ByteOrder
;
301 int setid
= 1, msgid
= 0;
302 char hconst
[MAXTOKEN
+1];
306 cat
= (catT
*) malloc(sizeof(catT
));
308 bzero(cat
, sizeof(catT
));
313 while ((cptr
= gencat_getline(fd
)) != NULL
) {
316 if (strncmp(cptr
, "set", 3) == 0) {
321 if (*cptr
) cptr
= wskip(cptr
);
324 MCAddSet(setid
, token(cptr
));
325 } else MCAddSet(setid
, NULL
);
327 } else if (strncmp(cptr
, "delset", 6) == 0) {
332 } else if (strncmp(cptr
, "quote", 5) == 0) {
334 if (!*cptr
) quote
= 0;
337 if (!*cptr
) quote
= 0;
340 } else if (isspace((unsigned char)*cptr
)) {
344 strcpy(hconst
, token(cptr
));
349 if (*cptr
) warning(cptr
, "unrecognized line");
353 if (!curSet
) MCAddSet(setid
, NULL
);
354 if (isdigit((unsigned char)*cptr
) || *cptr
== '#') {
359 MCAddMsg(msgid
, "", hconst
);
363 if (!isspace((unsigned char)*cptr
)) warning(cptr
, "expected a space");
366 MCAddMsg(msgid
, "", hconst
);
375 /* if (*cptr) ++cptr; */
378 if (isspace(cptr
[-1])) {
379 MCAddMsg(msgid
, "", hconst
);
385 str
= getmsg(fd
, cptr
, quote
);
386 MCAddMsg(msgid
, str
, hconst
);
405 cat
= (catT
*) malloc(sizeof(catT
));
407 bzero(cat
, sizeof(catT
));
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 */
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");
419 if (lseek(fd
, ntohll(mcHead
.firstSet
), L_SET
) == -1) corrupt();
422 if (read(fd
, &mcSet
, sizeof(mcSet
)) != sizeof(mcSet
)) corrupt();
423 if (mcSet
.invalid
) continue;
425 set
= (setT
*) malloc(sizeof(setT
));
427 bzero(set
, sizeof(*set
));
429 cat
->last
->next
= set
;
430 set
->prev
= cat
->last
;
432 } else cat
->first
= cat
->last
= set
;
434 set
->setId
= ntohl(mcSet
.setId
);
438 data
= (char *) malloc((size_t)ntohl(mcSet
.dataLen
));
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();
444 for (i
= 0; i
< ntohl(mcSet
.numMsgs
); ++i
) {
445 if (read(fd
, &mcMsg
, sizeof(mcMsg
)) != sizeof(mcMsg
)) corrupt();
451 msg
= (msgT
*) malloc(sizeof(msgT
));
453 bzero(msg
, sizeof(*msg
));
455 set
->last
->next
= msg
;
456 msg
->prev
= set
->last
;
458 } else set
->first
= set
->last
= msg
;
460 msg
->msgId
= ntohl(mcMsg
.msgId
);
461 msg
->str
= dupstr((char *) (data
+ ntohll(mcMsg
.msg
.off
)));
465 if (!mcSet
.nextSet
) break;
466 if (lseek(fd
, ntohll(mcSet
.nextSet
), L_SET
) == -1) corrupt();
472 printS(int fd
, const char *str
)
475 write(fd
, str
, strlen(str
));
479 printL(int fd
, long l
)
482 sprintf(buf
, "%ld", l
);
483 write(fd
, buf
, strlen(buf
));
487 printLX(int fd
, long l
)
490 sprintf(buf
, "%lx", l
);
491 write(fd
, buf
, strlen(buf
));
495 genconst(int fd
, int type
, char *setConst
, char *msgConst
, long val
)
500 printS(fd
, "\n#define ");
501 printS(fd
, setConst
);
504 printS(fd
, "#define ");
505 printS(fd
, setConst
);
506 printS(fd
, msgConst
);
512 case MCLangCPlusPlus
:
515 printS(fd
, "\nconst long ");
516 printS(fd
, setConst
);
519 printS(fd
, "const long ");
520 printS(fd
, setConst
);
521 printS(fd
, msgConst
);
528 error(NULL
, "not a recognized (programming) language type");
533 MCWriteConst(int fd
, int type
, int orConsts
)
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");
550 for (set
= cat
->first
; set
; set
= set
->next
) {
551 if (set
->hconst
) genconst(fd
, type
, set
->hconst
, NULL
, set
->setId
);
553 for (msg
= set
->first
; msg
; msg
= msg
->next
) {
555 if (orConsts
) id
= MCMakeId(set
->setId
, msg
->msgId
);
556 else id
= msg
->msgId
;
557 genconst(fd
, type
, set
->hconst
, msg
->hconst
, id
);
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 */
587 error(NULL
, "cannot write empty catalog set");
589 for (cnt
= 0, set
= cat
->first
; set
; set
= set
->next
) ++cnt
;
590 mcHead
.numSets
= htonl(cnt
);
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)' */
596 /* Also, this code doesn't seem to check returns from write! */
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
));
604 for (set
= cat
->first
; set
; set
= set
->next
) {
605 bzero(&mcSet
, sizeof(mcSet
));
607 mcSet
.setId
= htonl(set
->setId
);
608 mcSet
.invalid
= FALSE
;
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
));
614 /* Now write all the string data */
615 mcSet
.data
.off
= htonll(lseek(fd
, (off_t
)0L, L_INCR
));
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);
622 mcSet
.u
.firstMsg
= htonll(lseek(fd
, (off_t
)0L, L_INCR
));
623 mcSet
.numMsgs
= htonl(cnt
);
624 mcSet
.dataLen
= htonl(mcSet
.dataLen
);
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
));
634 /* Go back and fix things up */
636 if (set
== cat
->last
) {
638 lseek(fd
, pos
, L_SET
);
639 write(fd
, &mcSet
, sizeof(mcSet
));
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
);
650 MCAddSet(int setId
, char *hconst
)
655 error(NULL
, "setId's must be greater than zero");
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
);
665 } else if (set
->setId
> setId
) {
668 newSet
= (setT
*) malloc(sizeof(setT
));
669 if (!newSet
) nomem();
670 bzero(newSet
, sizeof(setT
));
671 newSet
->prev
= set
->prev
;
673 if (set
->prev
) set
->prev
->next
= newSet
;
674 else cat
->first
= newSet
;
681 set
= (setT
*) malloc(sizeof(setT
));
683 bzero(set
, sizeof(setT
));
686 set
->prev
= cat
->last
;
688 cat
->last
->next
= set
;
691 set
->prev
= set
->next
= NULL
;
692 cat
->first
= cat
->last
= set
;
696 if (hconst
) set
->hconst
= dupstr(hconst
);
701 MCAddMsg(int msgId
, const char *str
, char *hconst
)
706 error(NULL
, "can't specify a message when no set exists");
709 error(NULL
, "msgId's must be greater than zero");
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
;
720 } else if (msg
->msgId
> msgId
) {
723 newMsg
= (msgT
*) malloc(sizeof(msgT
));
724 if (!newMsg
) nomem();
725 bzero(newMsg
, sizeof(msgT
));
726 newMsg
->prev
= msg
->prev
;
728 if (msg
->prev
) msg
->prev
->next
= newMsg
;
729 else curSet
->first
= newMsg
;
736 msg
= (msgT
*) malloc(sizeof(msgT
));
738 bzero(msg
, sizeof(msgT
));
741 msg
->prev
= curSet
->last
;
743 curSet
->last
->next
= msg
;
746 msg
->prev
= msg
->next
= NULL
;
747 curSet
->first
= curSet
->last
= msg
;
751 if (hconst
) msg
->hconst
= dupstr(hconst
);
752 msg
->str
= dupstr(str
);
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
);
768 if (set
->hconst
) free(set
->hconst
);
770 if (set
->prev
) set
->prev
->next
= set
->next
;
771 else cat
->first
= set
->next
;
773 if (set
->next
) set
->next
->prev
= set
->prev
;
774 else cat
->last
= set
->prev
;
778 } else if (set
->setId
> setId
) break;
780 warning(NULL
, "specified set doesn't exist");
789 error(NULL
, "you can't delete a message before defining the set");
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
);
796 if (msg
->prev
) msg
->prev
->next
= msg
->next
;
797 else curSet
->first
= msg
->next
;
799 if (msg
->next
) msg
->next
->prev
= msg
->prev
;
800 else curSet
->last
= msg
->prev
;
804 } else if (msg
->msgId
> msgId
) break;
806 warning(NULL
, "specified msg doesn't exist");
809 #if 0 /* this function is unsed and looks like debug thing */
819 errx(1, "no catalog open");
821 for (set
= cat
->first
; set
; set
= set
->next
) {
822 fprintf(fp
, "$set %ld", set
->setId
);
824 fprintf(fp
, " # %s", set
->hconst
);
827 for (msg
= set
->first
; msg
; msg
= msg
->next
) {
829 fprintf(fp
, "# %s\n", msg
->hconst
);
830 fprintf(fp
, "%ld\t%s\n", msg
->msgId
, msg
->str
);