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