xref: /freebsd/usr.bin/gencat/gencat.c (revision 5ebc7e6281887681c3a348a5a4c902e262ccd656)
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