gencat.c revision 8874
17496Sjkh
27496Sjkh/***********************************************************
37496SjkhCopyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
47496Sjkh
57496Sjkh                        All Rights Reserved
67496Sjkh
77496SjkhPermission to use, copy, modify, and distribute this software and its
87496Sjkhdocumentation for any purpose and without fee is hereby granted,
97496Sjkhprovided that the above copyright notice appear in all copies and that
107496Sjkhboth that copyright notice and this permission notice appear in
117496Sjkhsupporting documentation, and that Alfalfa's name not be used in
127496Sjkhadvertising or publicity pertaining to distribution of the software
137496Sjkhwithout specific, written prior permission.
147496Sjkh
157496SjkhALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
167496SjkhALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
177496SjkhALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
187496SjkhANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
197496SjkhWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
207496SjkhARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
217496SjkhSOFTWARE.
227496Sjkh
237496SjkhIf you make any modifications, bugfixes or other changes to this software
247496Sjkhwe'd appreciate it if you could send a copy to us so we can keep things
257496Sjkhup-to-date.  Many thanks.
267496Sjkh				Kee Hinckley
277496Sjkh				Alfalfa Software, Inc.
287496Sjkh				267 Allston St., #3
297496Sjkh				Cambridge, MA 02139  USA
307496Sjkh				nazgul@alfalfa.com
318874Srgrimes
327496Sjkh******************************************************************/
337496Sjkh
347496Sjkh/* Edit History
357496Sjkh
367496Sjkh01/18/91   3 hamilton	#if not reparsed
377496Sjkh01/12/91   2 schulert	conditionally use prototypes
387496Sjkh12/23/90   2 hamilton	Fix fd == NULL to fd < 0
397496Sjkh11/03/90   1 hamilton	Alphalpha->Alfalfa & OmegaMail->Poste
407496Sjkh08/13/90   1 schulert	move from ua to omu
417496Sjkh*/
427496Sjkh
437496Sjkh#include <stdio.h>
447496Sjkh#include <sys/types.h>
457496Sjkh#ifdef SYSV
467496Sjkh#include <sys/fcntl.h>
477496Sjkh#define L_SET SEEK_SET
487496Sjkh#define L_INCR SEEK_CUR
497496Sjkh#endif
507496Sjkh#include <sys/file.h>
517496Sjkh#include <sys/stat.h>
527496Sjkh#include "gencat.h"
537496Sjkh
547496Sjkh/*
557496Sjkh * The spec says the syntax is "gencat catfile msgfile...".
567496Sjkh * We extend it to:
577496Sjkh * 	gencat [-lang C|C++|ANSIC] catfile msgfile [-h <header-file>]...
587496Sjkh * Flags are order dependant, we'll take whatever lang was most recently chosen
597496Sjkh * and use it to generate the next header file.  The header files are generated
607496Sjkh * at the point in the command line they are listed.  Thus the sequence:
617496Sjkh *	gencat -lang C foo.cat foo.mcs -h foo.h -lang C++ bar.mcs -h bar.H
627496Sjkh * will put constants from foo.mcs into foo.h and constants from bar.mcs into
637496Sjkh * bar.h.  Constants are not saved in the catalog file, so nothing will come
647496Sjkh * from that, even if things have been defined before.  The constants in foo.h
657496Sjkh * will be in C syntax, in bar.H in C++ syntax.
667496Sjkh */
677496Sjkh
687496Sjkh#if ANSI_C || defined(__cplusplus)
697496Sjkh# define P_(x) x
707496Sjkh#else
717496Sjkh# define P_(x) /**/
727496Sjkh#endif
737496Sjkh
747496Sjkhstatic void writeIfChanged P_((char *fname, int lang, int orConsts));
757496Sjkh
767496Sjkh#undef P_
777496Sjkh
787496Sjkhvoid usage() {
797496Sjkh    fprintf(stderr, "Use: gencat [-new] [-or] [-lang C|C++|ANSIC]\n");
807496Sjkh    fprintf(stderr, "            catfile msgfile [-h <header-file>]...\n");
817496Sjkh}
827496Sjkh
837496Sjkhvoid main(
847496Sjkh#if ANSI_C || defined(__cplusplus)
857496Sjkh		int argc, char *argv[])
867496Sjkh#else
877496Sjkh		argc, argv)
887496Sjkhint argc;
897496Sjkhchar *argv[];
907496Sjkh#endif
917496Sjkh{
927496Sjkh    int		ofd, ifd, i;
937496Sjkh    FILE	*fptr;
947496Sjkh    char	*catfile = NULL;
957496Sjkh    char	*input = NULL;
967496Sjkh    int		lang = MCLangC;
977496Sjkh    int		new = False;
987496Sjkh    int		orConsts = False;
998874Srgrimes
1007496Sjkh    for (i = 1; i < argc; ++i) {
1017496Sjkh	if (argv[i][0] == '-') {
1027496Sjkh	    if (strcmp(argv[i], "-lang") == 0) {
1037496Sjkh		++i;
1047496Sjkh		if (strcmp(argv[i], "C") == 0) lang = MCLangC;
1057496Sjkh		else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus;
1067496Sjkh		else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC;
1077496Sjkh		else {
1087496Sjkh		    fprintf(stderr, "gencat: Unrecognized language: %s\n", argv[i]);
1097496Sjkh		    exit(1);
1108874Srgrimes		}
1117496Sjkh	    } else if (strcmp(argv[i], "-h") == 0) {
1127496Sjkh		if (!input) {
1137496Sjkh		    fprintf(stderr, "gencat: Can't write to a header before reading something.\n");
1147496Sjkh		    exit(1);
1157496Sjkh		}
1167496Sjkh		++i;
1177496Sjkh		writeIfChanged(argv[i], lang, orConsts);
1187496Sjkh	    } else if (strcmp(argv[i], "-new") == 0) {
1197496Sjkh		if (catfile) {
1207496Sjkh		    fprintf(stderr, "gencat: You must specify -new before the catalog file name\n");
1217496Sjkh		    exit(1);
1227496Sjkh		}
1237496Sjkh		new = True;
1247496Sjkh	    } else if (strcmp(argv[i], "-or") == 0) {
1257496Sjkh		orConsts = ~orConsts;
1267496Sjkh	    } else {
1277496Sjkh		usage();
1287496Sjkh		exit(1);
1297496Sjkh	    }
1307496Sjkh        } else {
1317496Sjkh	    if (!catfile) {
1327496Sjkh		catfile = argv[i];
1337496Sjkh		if (new) {
1347496Sjkh		    if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
1357496Sjkh			fprintf(stderr, "gencat: Unable to create a new %s.\n", catfile);
1367496Sjkh			exit(1);
1377496Sjkh		    }
1387496Sjkh		} else if ((ofd = open(catfile, O_RDONLY)) < 0) {
1397496Sjkh		    if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0) {
1407496Sjkh			fprintf(stderr, "gencat: Unable to create %s.\n", catfile);
1417496Sjkh			exit(1);
1427496Sjkh		    }
1437496Sjkh		} else {
1447496Sjkh		    MCReadCat(ofd);
1457496Sjkh		    close(ofd);
1467496Sjkh		    if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0) {
1477496Sjkh			fprintf(stderr, "gencat: Unable to truncate %s.\n", catfile);
1487496Sjkh			exit(1);
1497496Sjkh		    }
1507496Sjkh		}
1517496Sjkh	    } else {
1527496Sjkh		input = argv[i];
1537496Sjkh		if ((ifd = open(input, O_RDONLY)) < 0) {
1547496Sjkh		    fprintf(stderr, "gencat: Unable to read %s\n", input);
1557496Sjkh		    exit(1);
1567496Sjkh		}
1577496Sjkh		MCParse(ifd);
1587496Sjkh		close(ifd);
1597496Sjkh	    }
1607496Sjkh	}
1617496Sjkh    }
1627496Sjkh    if (catfile) {
1637496Sjkh	MCWriteCat(ofd);
1647496Sjkh	exit(0);
1657496Sjkh    } else {
1667496Sjkh	usage();
1677496Sjkh	exit(1);
1687496Sjkh    }
1697496Sjkh}
1707496Sjkh
1717496Sjkhstatic void writeIfChanged(
1727496Sjkh#if ANSI_C || defined(__cplusplus)
1737496Sjkh		char *fname, int lang, int orConsts)
1747496Sjkh#else
1757496Sjkh		fname, lang, orConsts)
1767496Sjkhchar *fname;
1777496Sjkhint lang;
1787496Sjkhint orConsts;
1797496Sjkh#endif
1807496Sjkh{
1817496Sjkh    char	tmpname[32];
1827496Sjkh    char	buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr;
1837496Sjkh    int		fd, tfd;
1847496Sjkh    int		diff = False;
1857496Sjkh    int		c, len, tlen;
1867496Sjkh    struct stat	sbuf;
1877496Sjkh
1887496Sjkh    /* If it doesn't exist, just create it */
1897496Sjkh    if (stat(fname, &sbuf)) {
1907496Sjkh	if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) {
1917496Sjkh	    fprintf(stderr, "gencat: Unable to create header file %s.\n", fname);
1927496Sjkh	    exit(1);
1937496Sjkh	}
1947496Sjkh	MCWriteConst(fd, lang, orConsts);
1957496Sjkh	close(fd);
1967496Sjkh	return;
1977496Sjkh    }
1987496Sjkh
1997496Sjkh    /* If it does exist, create a temp file for now */
2007496Sjkh    sprintf(tmpname, "/tmp/gencat.%d", (int) getpid());
2017496Sjkh    if ((tfd = open(tmpname, O_RDWR|O_CREAT, 0666)) < 0) {
2027496Sjkh	fprintf(stderr, "gencat: Unable to open temporary file: %s\n", tmpname);
2037496Sjkh	exit(1);
2047496Sjkh    }
2057496Sjkh    unlink(tmpname);
2067496Sjkh
2077496Sjkh    /* Write to the temp file and rewind */
2087496Sjkh    MCWriteConst(tfd, lang, orConsts);
2097496Sjkh
2107496Sjkh    /* Open the real header file */
2117496Sjkh    if ((fd = open(fname, O_RDONLY)) < 0) {
2127496Sjkh	fprintf(stderr, "gencat: Unable to read header file: %s\n", fname);
2137496Sjkh	exit(1);
2147496Sjkh    }
2157496Sjkh
2167496Sjkh    /* Backup to the start of the temp file */
2177496Sjkh    if (lseek(tfd, 0L, L_SET) < 0) {
2187496Sjkh	fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname);
2197496Sjkh	exit(1);
2207496Sjkh    }
2217496Sjkh
2227496Sjkh    /* Now compare them */
2237496Sjkh    while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) {
2247496Sjkh	if ((len = read(fd, buf, BUFSIZ)) != tlen) {
2257496Sjkh	    diff = True;
2267496Sjkh	    goto done;
2277496Sjkh	}
2287496Sjkh	for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) {
2297496Sjkh	    if (*tptr != *cptr) {
2307496Sjkh		diff = True;
2317496Sjkh		goto done;
2327496Sjkh	    }
2337496Sjkh	}
2347496Sjkh    }
2358874Srgrimesdone:
2367496Sjkh    if (diff) {
2377496Sjkh	if (lseek(tfd, 0L, L_SET) < 0) {
2387496Sjkh	    fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname);
2397496Sjkh	    exit(1);
2407496Sjkh	}
2417496Sjkh	close(fd);
2427496Sjkh	if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) {
2437496Sjkh	    fprintf(stderr, "gencat: Unable to truncate header file: %s\n", fname);
2447496Sjkh	    exit(1);
2457496Sjkh	}
2467496Sjkh	while ((len = read(tfd, buf, BUFSIZ)) > 0) {
2477496Sjkh	    if (write(fd, buf, len) != len) {
2487496Sjkh		fprintf(stderr, "gencat: Error writing to header file: %s\n", fname);
2497496Sjkh	    }
2507496Sjkh	}
2517496Sjkh    }
2527496Sjkh    close(fd);
2537496Sjkh    close(tfd);
2547496Sjkh}
255