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