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 <stdio.h> 44 #include <sys/types.h> 45 #include <unistd.h> 46 #ifdef SYSV 47 #include <sys/fcntl.h> 48 #define L_SET SEEK_SET 49 #define L_INCR SEEK_CUR 50 #endif 51 #include <sys/file.h> 52 #include <sys/stat.h> 53 #include "gencat.h" 54 55 /* 56 * The spec says the syntax is "gencat catfile msgfile...". 57 * We extend it to: 58 * gencat [-lang C|C++|ANSIC] catfile msgfile [-h <header-file>]... 59 * Flags are order dependant, we'll take whatever lang was most recently chosen 60 * and use it to generate the next header file. The header files are generated 61 * at the point in the command line they are listed. Thus the sequence: 62 * gencat -lang C foo.cat foo.mcs -h foo.h -lang C++ bar.mcs -h bar.H 63 * will put constants from foo.mcs into foo.h and constants from bar.mcs into 64 * bar.h. Constants are not saved in the catalog file, so nothing will come 65 * from that, even if things have been defined before. The constants in foo.h 66 * will be in C syntax, in bar.H in C++ syntax. 67 */ 68 69 #if ANSI_C || defined(__cplusplus) 70 # define P_(x) x 71 #else 72 # define P_(x) /**/ 73 #endif 74 75 static void writeIfChanged P_((char *fname, int lang, int orConsts)); 76 77 #undef P_ 78 79 void usage() { 80 fprintf(stderr, "Use: gencat [-new] [-or] [-lang C|C++|ANSIC]\n"); 81 fprintf(stderr, " catfile msgfile [-h <header-file>]...\n"); 82 } 83 84 void main( 85 #if ANSI_C || defined(__cplusplus) 86 int argc, char *argv[]) 87 #else 88 argc, argv) 89 int argc; 90 char *argv[]; 91 #endif 92 { 93 int ofd, ifd, i; 94 FILE *fptr; 95 char *catfile = NULL; 96 char *input = NULL; 97 int lang = MCLangC; 98 int new = False; 99 int orConsts = False; 100 101 for (i = 1; i < argc; ++i) { 102 if (argv[i][0] == '-') { 103 if (strcmp(argv[i], "-lang") == 0) { 104 ++i; 105 if (strcmp(argv[i], "C") == 0) lang = MCLangC; 106 else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus; 107 else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC; 108 else { 109 fprintf(stderr, "gencat: Unrecognized language: %s\n", argv[i]); 110 exit(1); 111 } 112 } else if (strcmp(argv[i], "-h") == 0) { 113 if (!input) { 114 fprintf(stderr, "gencat: Can't write to a header before reading something.\n"); 115 exit(1); 116 } 117 ++i; 118 writeIfChanged(argv[i], lang, orConsts); 119 } else if (strcmp(argv[i], "-new") == 0) { 120 if (catfile) { 121 fprintf(stderr, "gencat: You must specify -new before the catalog file name\n"); 122 exit(1); 123 } 124 new = True; 125 } else if (strcmp(argv[i], "-or") == 0) { 126 orConsts = ~orConsts; 127 } else { 128 usage(); 129 exit(1); 130 } 131 } else { 132 if (!catfile) { 133 catfile = argv[i]; 134 if (new) { 135 if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { 136 fprintf(stderr, "gencat: Unable to create a new %s.\n", catfile); 137 exit(1); 138 } 139 } else if ((ofd = open(catfile, O_RDONLY)) < 0) { 140 if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0) { 141 fprintf(stderr, "gencat: Unable to create %s.\n", catfile); 142 exit(1); 143 } 144 } else { 145 MCReadCat(ofd); 146 close(ofd); 147 if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0) { 148 fprintf(stderr, "gencat: Unable to truncate %s.\n", catfile); 149 exit(1); 150 } 151 } 152 } else { 153 input = argv[i]; 154 if ((ifd = open(input, O_RDONLY)) < 0) { 155 fprintf(stderr, "gencat: Unable to read %s\n", input); 156 exit(1); 157 } 158 MCParse(ifd); 159 close(ifd); 160 } 161 } 162 } 163 if (catfile) { 164 MCWriteCat(ofd); 165 exit(0); 166 } else { 167 usage(); 168 exit(1); 169 } 170 } 171 172 static void writeIfChanged( 173 #if ANSI_C || defined(__cplusplus) 174 char *fname, int lang, int orConsts) 175 #else 176 fname, lang, orConsts) 177 char *fname; 178 int lang; 179 int orConsts; 180 #endif 181 { 182 char tmpname[32]; 183 char buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr; 184 int fd, tfd; 185 int diff = False; 186 int c, len, tlen; 187 struct stat sbuf; 188 189 /* If it doesn't exist, just create it */ 190 if (stat(fname, &sbuf)) { 191 if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) { 192 fprintf(stderr, "gencat: Unable to create header file %s.\n", fname); 193 exit(1); 194 } 195 MCWriteConst(fd, lang, orConsts); 196 close(fd); 197 return; 198 } 199 200 /* If it does exist, create a temp file for now */ 201 sprintf(tmpname, "/tmp/gencat.%d", (int) getpid()); 202 if ((tfd = open(tmpname, O_RDWR|O_CREAT, 0666)) < 0) { 203 fprintf(stderr, "gencat: Unable to open temporary file: %s\n", tmpname); 204 exit(1); 205 } 206 unlink(tmpname); 207 208 /* Write to the temp file and rewind */ 209 MCWriteConst(tfd, lang, orConsts); 210 211 /* Open the real header file */ 212 if ((fd = open(fname, O_RDONLY)) < 0) { 213 fprintf(stderr, "gencat: Unable to read header file: %s\n", fname); 214 exit(1); 215 } 216 217 /* Backup to the start of the temp file */ 218 if (lseek(tfd, 0L, L_SET) < 0) { 219 fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname); 220 exit(1); 221 } 222 223 /* Now compare them */ 224 while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) { 225 if ((len = read(fd, buf, BUFSIZ)) != tlen) { 226 diff = True; 227 goto done; 228 } 229 for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) { 230 if (*tptr != *cptr) { 231 diff = True; 232 goto done; 233 } 234 } 235 } 236 done: 237 if (diff) { 238 if (lseek(tfd, 0L, L_SET) < 0) { 239 fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname); 240 exit(1); 241 } 242 close(fd); 243 if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) { 244 fprintf(stderr, "gencat: Unable to truncate header file: %s\n", fname); 245 exit(1); 246 } 247 while ((len = read(tfd, buf, BUFSIZ)) > 0) { 248 if (write(fd, buf, len) != len) { 249 fprintf(stderr, "gencat: Error writing to header file: %s\n", fname); 250 } 251 } 252 } 253 close(fd); 254 close(tfd); 255 } 256