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