Home | History | Annotate | Line # | Download | only in gencat
gencat.c revision 1.1
      1  1.1  jtc 
      2  1.1  jtc /***********************************************************
      3  1.1  jtc Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
      4  1.1  jtc 
      5  1.1  jtc                         All Rights Reserved
      6  1.1  jtc 
      7  1.1  jtc Permission to use, copy, modify, and distribute this software and its
      8  1.1  jtc documentation for any purpose and without fee is hereby granted,
      9  1.1  jtc provided that the above copyright notice appear in all copies and that
     10  1.1  jtc both that copyright notice and this permission notice appear in
     11  1.1  jtc supporting documentation, and that Alfalfa's name not be used in
     12  1.1  jtc advertising or publicity pertaining to distribution of the software
     13  1.1  jtc without specific, written prior permission.
     14  1.1  jtc 
     15  1.1  jtc ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     16  1.1  jtc ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     17  1.1  jtc ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     18  1.1  jtc ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     19  1.1  jtc WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     20  1.1  jtc ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     21  1.1  jtc SOFTWARE.
     22  1.1  jtc 
     23  1.1  jtc If you make any modifications, bugfixes or other changes to this software
     24  1.1  jtc we'd appreciate it if you could send a copy to us so we can keep things
     25  1.1  jtc up-to-date.  Many thanks.
     26  1.1  jtc 				Kee Hinckley
     27  1.1  jtc 				Alfalfa Software, Inc.
     28  1.1  jtc 				267 Allston St., #3
     29  1.1  jtc 				Cambridge, MA 02139  USA
     30  1.1  jtc 				nazgul (at) alfalfa.com
     31  1.1  jtc 
     32  1.1  jtc ******************************************************************/
     33  1.1  jtc 
     34  1.1  jtc /* Edit History
     35  1.1  jtc 
     36  1.1  jtc 01/18/91   3 hamilton	#if not reparsed
     37  1.1  jtc 01/12/91   2 schulert	conditionally use prototypes
     38  1.1  jtc 12/23/90   2 hamilton	Fix fd == NULL to fd < 0
     39  1.1  jtc 11/03/90   1 hamilton	Alphalpha->Alfalfa & OmegaMail->Poste
     40  1.1  jtc 08/13/90   1 schulert	move from ua to omu
     41  1.1  jtc */
     42  1.1  jtc 
     43  1.1  jtc #include <stdio.h>
     44  1.1  jtc #include <sys/types.h>
     45  1.1  jtc #ifdef SYSV
     46  1.1  jtc #include <sys/fcntl.h>
     47  1.1  jtc #define L_SET SEEK_SET
     48  1.1  jtc #define L_INCR SEEK_CUR
     49  1.1  jtc #endif
     50  1.1  jtc #include <sys/file.h>
     51  1.1  jtc #include <sys/stat.h>
     52  1.1  jtc #include "gencat.h"
     53  1.1  jtc 
     54  1.1  jtc /*
     55  1.1  jtc  * The spec says the syntax is "gencat catfile msgfile...".
     56  1.1  jtc  * We extend it to:
     57  1.1  jtc  * 	gencat [-lang C|C++|ANSIC] catfile msgfile [-h <header-file>]...
     58  1.1  jtc  * Flags are order dependant, we'll take whatever lang was most recently chosen
     59  1.1  jtc  * and use it to generate the next header file.  The header files are generated
     60  1.1  jtc  * at the point in the command line they are listed.  Thus the sequence:
     61  1.1  jtc  *	gencat -lang C foo.cat foo.mcs -h foo.h -lang C++ bar.mcs -h bar.H
     62  1.1  jtc  * will put constants from foo.mcs into foo.h and constants from bar.mcs into
     63  1.1  jtc  * bar.h.  Constants are not saved in the catalog file, so nothing will come
     64  1.1  jtc  * from that, even if things have been defined before.  The constants in foo.h
     65  1.1  jtc  * will be in C syntax, in bar.H in C++ syntax.
     66  1.1  jtc  */
     67  1.1  jtc 
     68  1.1  jtc #if ANSI_C || defined(__cplusplus)
     69  1.1  jtc # define P_(x) x
     70  1.1  jtc #else
     71  1.1  jtc # define P_(x) /**/
     72  1.1  jtc #endif
     73  1.1  jtc 
     74  1.1  jtc static void writeIfChanged P_((char *fname, int lang, int orConsts));
     75  1.1  jtc 
     76  1.1  jtc #undef P_
     77  1.1  jtc 
     78  1.1  jtc void usage() {
     79  1.1  jtc     fprintf(stderr, "Use: gencat [-new] [-or] [-lang C|C++|ANSIC]\n");
     80  1.1  jtc     fprintf(stderr, "            catfile msgfile [-h <header-file>]...\n");
     81  1.1  jtc }
     82  1.1  jtc 
     83  1.1  jtc void main(
     84  1.1  jtc #if ANSI_C || defined(__cplusplus)
     85  1.1  jtc 		int argc, char *argv[])
     86  1.1  jtc #else
     87  1.1  jtc 		argc, argv)
     88  1.1  jtc int argc;
     89  1.1  jtc char *argv[];
     90  1.1  jtc #endif
     91  1.1  jtc {
     92  1.1  jtc     int		ofd, ifd, i;
     93  1.1  jtc     FILE	*fptr;
     94  1.1  jtc     char	*catfile = NULL;
     95  1.1  jtc     char	*input = NULL;
     96  1.1  jtc     int		lang = MCLangC;
     97  1.1  jtc     int		new = False;
     98  1.1  jtc     int		orConsts = False;
     99  1.1  jtc 
    100  1.1  jtc     for (i = 1; i < argc; ++i) {
    101  1.1  jtc 	if (argv[i][0] == '-') {
    102  1.1  jtc 	    if (strcmp(argv[i], "-lang") == 0) {
    103  1.1  jtc 		++i;
    104  1.1  jtc 		if (strcmp(argv[i], "C") == 0) lang = MCLangC;
    105  1.1  jtc 		else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus;
    106  1.1  jtc 		else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC;
    107  1.1  jtc 		else {
    108  1.1  jtc 		    fprintf(stderr, "gencat: Unrecognized language: %s\n", argv[i]);
    109  1.1  jtc 		    exit(1);
    110  1.1  jtc 		}
    111  1.1  jtc 	    } else if (strcmp(argv[i], "-h") == 0) {
    112  1.1  jtc 		if (!input) {
    113  1.1  jtc 		    fprintf(stderr, "gencat: Can't write to a header before reading something.\n");
    114  1.1  jtc 		    exit(1);
    115  1.1  jtc 		}
    116  1.1  jtc 		++i;
    117  1.1  jtc 		writeIfChanged(argv[i], lang, orConsts);
    118  1.1  jtc 	    } else if (strcmp(argv[i], "-new") == 0) {
    119  1.1  jtc 		if (catfile) {
    120  1.1  jtc 		    fprintf(stderr, "gencat: You must specify -new before the catalog file name\n");
    121  1.1  jtc 		    exit(1);
    122  1.1  jtc 		}
    123  1.1  jtc 		new = True;
    124  1.1  jtc 	    } else if (strcmp(argv[i], "-or") == 0) {
    125  1.1  jtc 		orConsts = ~orConsts;
    126  1.1  jtc 	    } else {
    127  1.1  jtc 		usage();
    128  1.1  jtc 		exit(1);
    129  1.1  jtc 	    }
    130  1.1  jtc         } else {
    131  1.1  jtc 	    if (!catfile) {
    132  1.1  jtc 		catfile = argv[i];
    133  1.1  jtc 		if (new) {
    134  1.1  jtc 		    if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
    135  1.1  jtc 			fprintf(stderr, "gencat: Unable to create a new %s.\n", catfile);
    136  1.1  jtc 			exit(1);
    137  1.1  jtc 		    }
    138  1.1  jtc 		} else if ((ofd = open(catfile, O_RDONLY)) < 0) {
    139  1.1  jtc 		    if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0) {
    140  1.1  jtc 			fprintf(stderr, "gencat: Unable to create %s.\n", catfile);
    141  1.1  jtc 			exit(1);
    142  1.1  jtc 		    }
    143  1.1  jtc 		} else {
    144  1.1  jtc 		    MCReadCat(ofd);
    145  1.1  jtc 		    close(ofd);
    146  1.1  jtc 		    if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0) {
    147  1.1  jtc 			fprintf(stderr, "gencat: Unable to truncate %s.\n", catfile);
    148  1.1  jtc 			exit(1);
    149  1.1  jtc 		    }
    150  1.1  jtc 		}
    151  1.1  jtc 	    } else {
    152  1.1  jtc 		input = argv[i];
    153  1.1  jtc 		if ((ifd = open(input, O_RDONLY)) < 0) {
    154  1.1  jtc 		    fprintf(stderr, "gencat: Unable to read %s\n", input);
    155  1.1  jtc 		    exit(1);
    156  1.1  jtc 		}
    157  1.1  jtc 		MCParse(ifd);
    158  1.1  jtc 		close(ifd);
    159  1.1  jtc 	    }
    160  1.1  jtc 	}
    161  1.1  jtc     }
    162  1.1  jtc     if (catfile) {
    163  1.1  jtc 	MCWriteCat(ofd);
    164  1.1  jtc 	exit(0);
    165  1.1  jtc     } else {
    166  1.1  jtc 	usage();
    167  1.1  jtc 	exit(1);
    168  1.1  jtc     }
    169  1.1  jtc }
    170  1.1  jtc 
    171  1.1  jtc static void writeIfChanged(
    172  1.1  jtc #if ANSI_C || defined(__cplusplus)
    173  1.1  jtc 		char *fname, int lang, int orConsts)
    174  1.1  jtc #else
    175  1.1  jtc 		fname, lang, orConsts)
    176  1.1  jtc char *fname;
    177  1.1  jtc int lang;
    178  1.1  jtc int orConsts;
    179  1.1  jtc #endif
    180  1.1  jtc {
    181  1.1  jtc     char	tmpname[32];
    182  1.1  jtc     char	buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr;
    183  1.1  jtc     int		fd, tfd;
    184  1.1  jtc     int		diff = False;
    185  1.1  jtc     int		c, len, tlen;
    186  1.1  jtc     struct stat	sbuf;
    187  1.1  jtc 
    188  1.1  jtc     /* If it doesn't exist, just create it */
    189  1.1  jtc     if (stat(fname, &sbuf)) {
    190  1.1  jtc 	if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) {
    191  1.1  jtc 	    fprintf(stderr, "gencat: Unable to create header file %s.\n", fname);
    192  1.1  jtc 	    exit(1);
    193  1.1  jtc 	}
    194  1.1  jtc 	MCWriteConst(fd, lang, orConsts);
    195  1.1  jtc 	close(fd);
    196  1.1  jtc 	return;
    197  1.1  jtc     }
    198  1.1  jtc 
    199  1.1  jtc     /* If it does exist, create a temp file for now */
    200  1.1  jtc     sprintf(tmpname, "/tmp/gencat.%d", (int) getpid());
    201  1.1  jtc     if ((tfd = open(tmpname, O_RDWR|O_CREAT, 0666)) < 0) {
    202  1.1  jtc 	fprintf(stderr, "gencat: Unable to open temporary file: %s\n", tmpname);
    203  1.1  jtc 	exit(1);
    204  1.1  jtc     }
    205  1.1  jtc     unlink(tmpname);
    206  1.1  jtc 
    207  1.1  jtc     /* Write to the temp file and rewind */
    208  1.1  jtc     MCWriteConst(tfd, lang, orConsts);
    209  1.1  jtc 
    210  1.1  jtc     /* Open the real header file */
    211  1.1  jtc     if ((fd = open(fname, O_RDONLY)) < 0) {
    212  1.1  jtc 	fprintf(stderr, "gencat: Unable to read header file: %s\n", fname);
    213  1.1  jtc 	exit(1);
    214  1.1  jtc     }
    215  1.1  jtc 
    216  1.1  jtc     /* Backup to the start of the temp file */
    217  1.1  jtc     if (lseek(tfd, 0L, L_SET) < 0) {
    218  1.1  jtc 	fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname);
    219  1.1  jtc 	exit(1);
    220  1.1  jtc     }
    221  1.1  jtc 
    222  1.1  jtc     /* Now compare them */
    223  1.1  jtc     while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) {
    224  1.1  jtc 	if ((len = read(fd, buf, BUFSIZ)) != tlen) {
    225  1.1  jtc 	    diff = True;
    226  1.1  jtc 	    goto done;
    227  1.1  jtc 	}
    228  1.1  jtc 	for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) {
    229  1.1  jtc 	    if (*tptr != *cptr) {
    230  1.1  jtc 		diff = True;
    231  1.1  jtc 		goto done;
    232  1.1  jtc 	    }
    233  1.1  jtc 	}
    234  1.1  jtc     }
    235  1.1  jtc done:
    236  1.1  jtc     if (diff) {
    237  1.1  jtc 	if (lseek(tfd, 0L, L_SET) < 0) {
    238  1.1  jtc 	    fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname);
    239  1.1  jtc 	    exit(1);
    240  1.1  jtc 	}
    241  1.1  jtc 	close(fd);
    242  1.1  jtc 	if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) {
    243  1.1  jtc 	    fprintf(stderr, "gencat: Unable to truncate header file: %s\n", fname);
    244  1.1  jtc 	    exit(1);
    245  1.1  jtc 	}
    246  1.1  jtc 	while ((len = read(tfd, buf, BUFSIZ)) > 0) {
    247  1.1  jtc 	    if (write(fd, buf, len) != len) {
    248  1.1  jtc 		fprintf(stderr, "gencat: Error writing to header file: %s\n", fname);
    249  1.1  jtc 	    }
    250  1.1  jtc 	}
    251  1.1  jtc     }
    252  1.1  jtc     close(fd);
    253  1.1  jtc     close(tfd);
    254  1.1  jtc }
    255