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