gencat.c revision 1.1 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 (at) 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