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