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 int 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 return 0; 159 } 160 161 static void writeIfChanged( 162 #if ANSI_C || defined(__cplusplus) 163 char *fname, int lang, int orConsts) 164 #else 165 fname, lang, orConsts) 166 char *fname; 167 int lang; 168 int orConsts; 169 #endif 170 { 171 char tmpname[32]; 172 char buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr; 173 int fd, tfd; 174 int diff = False; 175 int len, tlen; 176 struct stat sbuf; 177 178 /* If it doesn't exist, just create it */ 179 if (stat(fname, &sbuf)) { 180 if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) 181 errx(1, "unable to create header file %s", fname); 182 MCWriteConst(fd, lang, orConsts); 183 close(fd); 184 return; 185 } 186 187 /* If it does exist, create a temp file for now */ 188 sprintf(tmpname, "/tmp/gencat.%d", (int) getpid()); 189 if ((tfd = open(tmpname, O_RDWR|O_CREAT, 0666)) < 0) 190 errx(1, "unable to open temporary file: %s", tmpname); 191 unlink(tmpname); 192 193 /* Write to the temp file and rewind */ 194 MCWriteConst(tfd, lang, orConsts); 195 196 /* Open the real header file */ 197 if ((fd = open(fname, O_RDONLY)) < 0) 198 errx(1, "unable to read header file: %s", fname); 199 200 /* Backup to the start of the temp file */ 201 if (lseek(tfd, 0L, L_SET) < 0) 202 errx(1, "unable to seek in tempfile: %s", tmpname); 203 204 /* Now compare them */ 205 while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) { 206 if ((len = read(fd, buf, BUFSIZ)) != tlen) { 207 diff = True; 208 goto done; 209 } 210 for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) { 211 if (*tptr != *cptr) { 212 diff = True; 213 goto done; 214 } 215 } 216 } 217 done: 218 if (diff) { 219 if (lseek(tfd, 0L, L_SET) < 0) 220 errx(1, "unable to seek in tempfile: %s", tmpname); 221 close(fd); 222 if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) 223 errx(1, "unable to truncate header file: %s", fname); 224 while ((len = read(tfd, buf, BUFSIZ)) > 0) { 225 if (write(fd, buf, len) != len) 226 warnx("error writing to header file: %s", fname); 227 } 228 } 229 close(fd); 230 close(tfd); 231 } 232