xref: /dragonfly/games/hack/makedefs.c (revision 029e6489)
1 /* $NetBSD: makedefs.c,v 1.8 2003/04/02 18:36:42 jsm Exp $ */
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <fcntl.h>
68 #include <unistd.h>
69 
70 /* construct definitions of object constants */
71 #define	LINSZ	1000
72 #define	STRSZ	40
73 
74 int             fd;
75 char            string[STRSZ];
76 
77 static void readline(void);
78 static char nextchar(void);
79 static int skipuntil(const char *);
80 static int getentry(void);
81 static void capitalize(char *);
82 static int letter(char);
83 static int digit(char);
84 
85 int
86 main(int argc, char **argv)
87 {
88 	int             i = 0;
89 	int             propct = 0;
90 	char           *sp;
91 	if (argc != 2) {
92 		(void) fprintf(stderr, "usage: makedefs file\n");
93 		exit(1);
94 	}
95 	if ((fd = open(argv[1], O_RDONLY)) < 0) {
96 		perror(argv[1]);
97 		exit(1);
98 	}
99 	skipuntil("objects[] = {");
100 	while (getentry()) {
101 		if (!*string) {
102 			i++;
103 			continue;
104 		}
105 		for (sp = string; *sp; sp++)
106 			if (*sp == ' ' || *sp == '\t' || *sp == '-')
107 				*sp = '_';
108 		if (!strncmp(string, "RIN_", 4)) {
109 			capitalize(string + 4);
110 			printf("#define	%s	u.uprops[%d].p_flgs\n",
111 			       string + 4, propct++);
112 		}
113 		for (sp = string; *sp; sp++)
114 			capitalize(sp);
115 		/* avoid trouble with stupid C preprocessors */
116 		if (!strncmp(string, "WORTHLESS_PIECE_OF_", 19))
117 			printf("/* #define %s	%d */\n", string, i);
118 		else
119 			printf("#define	%s	%d\n", string, i);
120 		i++;
121 	}
122 	printf("\n#define	CORPSE	DEAD_HUMAN\n");
123 	printf("#define	LAST_GEM	(JADE+1)\n");
124 	printf("#define	LAST_RING	%d\n", propct);
125 	printf("#define	NROFOBJECTS	%d\n", i - 1);
126 	fflush(stdout);
127 	if (ferror(stdout)) {
128 		perror("standard output");
129 		exit(1);
130 	}
131 	exit(0);
132 }
133 
134 char            line[LINSZ], *lp = line, *lp0 = line, *lpe = line;
135 int             eof;
136 
137 static void
138 readline(void)
139 {
140 	int             n = read(fd, lp0, (line + LINSZ) - lp0);
141 	if (n < 0) {
142 		printf("Input error.\n");
143 		exit(1);
144 	}
145 	if (n == 0)
146 		eof++;
147 	lpe = lp0 + n;
148 }
149 
150 static char
151 nextchar(void)
152 {
153 	if (lp == lpe) {
154 		readline();
155 		lp = lp0;
156 	}
157 	return ((lp == lpe) ? 0 : *lp++);
158 }
159 
160 static int
161 skipuntil(const char *s)
162 {
163 	const char *sp0;
164 	char *sp1;
165 loop:
166 	while (*s != nextchar())
167 		if (eof) {
168 			printf("Cannot skipuntil %s\n", s);
169 			exit(1);
170 		}
171 	if (strlen(s) > (size_t)(lpe - lp + 1)) {
172 		char           *lp1, *lp2;
173 		lp2 = lp;
174 		lp1 = lp = lp0;
175 		while (lp2 != lpe)
176 			*lp1++ = *lp2++;
177 		lp2 = lp0;	/* save value */
178 		lp0 = lp1;
179 		readline();
180 		lp0 = lp2;
181 		if (strlen(s) > (size_t)(lpe - lp + 1)) {
182 			printf("error in skipuntil");
183 			exit(1);
184 		}
185 	}
186 	sp0 = s + 1;
187 	sp1 = lp;
188 	while (*sp0 && *sp0 == *sp1)
189 		sp0++, sp1++;
190 	if (!*sp0) {
191 		lp = sp1;
192 		return (1);
193 	}
194 	goto loop;
195 }
196 
197 static int
198 getentry(void)
199 {
200 	int             inbraces = 0, inparens = 0, stringseen = 0, commaseen = 0;
201 	int             prefix = 0;
202 	char            ch;
203 #define	NSZ	10
204 	char            identif[NSZ], *ip;
205 	string[0] = string[4] = 0;
206 	/*
207 	 * read until {...} or XXX(...) followed by , skip comment and
208 	 * #define lines deliver 0 on failure
209 	 */
210 	while (1) {
211 		ch = nextchar();
212 swi:
213 		if (letter(ch)) {
214 			ip = identif;
215 			do {
216 				if (ip < identif + NSZ - 1)
217 					*ip++ = ch;
218 				ch = nextchar();
219 			} while (letter(ch) || digit(ch));
220 			*ip = 0;
221 			while (ch == ' ' || ch == '\t')
222 				ch = nextchar();
223 			if (ch == '(' && !inparens && !stringseen)
224 				if (!strcmp(identif, "WAND") ||
225 				    !strcmp(identif, "RING") ||
226 				    !strcmp(identif, "POTION") ||
227 				    !strcmp(identif, "SCROLL"))
228 					(void) strncpy(string, identif, 3),
229 						string[3] = '_',
230 						prefix = 4;
231 		}
232 		switch (ch) {
233 		case '/':
234 			/* watch for comment */
235 			if ((ch = nextchar()) == '*')
236 				skipuntil("*/");
237 			goto swi;
238 		case '{':
239 			inbraces++;
240 			continue;
241 		case '(':
242 			inparens++;
243 			continue;
244 		case '}':
245 			inbraces--;
246 			if (inbraces < 0)
247 				return (0);
248 			continue;
249 		case ')':
250 			inparens--;
251 			if (inparens < 0) {
252 				printf("too many ) ?");
253 				exit(1);
254 			}
255 			continue;
256 		case '\n':
257 			/* watch for #define at begin of line */
258 			if ((ch = nextchar()) == '#') {
259 				char            pch;
260 				/* skip until '\n' not preceded by '\\' */
261 				do {
262 					pch = ch;
263 					ch = nextchar();
264 				} while (ch != '\n' || pch == '\\');
265 				continue;
266 			}
267 			goto swi;
268 		case ',':
269 			if (!inparens && !inbraces) {
270 				if (prefix && !string[prefix])
271 					string[0] = 0;
272 				if (stringseen)
273 					return (1);
274 				printf("unexpected ,\n");
275 				exit(1);
276 			}
277 			commaseen++;
278 			continue;
279 		case '\'':
280 			if ((ch = nextchar()) == '\\')
281 				ch = nextchar();
282 			if (nextchar() != '\'') {
283 				printf("strange character denotation?\n");
284 				exit(1);
285 			}
286 			continue;
287 		case '"':
288 			{
289 				char           *sp = string + prefix;
290 				char            pch;
291 				int             store = (inbraces || inparens)
292 				&& !stringseen++ && !commaseen;
293 				do {
294 					pch = ch;
295 					ch = nextchar();
296 					if (store && sp < string + STRSZ)
297 						*sp++ = ch;
298 				} while (ch != '"' || pch == '\\');
299 				if (store)
300 					*--sp = 0;
301 				continue;
302 			}
303 		}
304 	}
305 }
306 
307 static void
308 capitalize(char *sp)
309 {
310 	if ('a' <= *sp && *sp <= 'z')
311 		*sp += 'A' - 'a';
312 }
313 
314 static int
315 letter(char ch)
316 {
317 	return (('a' <= ch && ch <= 'z') ||
318 		('A' <= ch && ch <= 'Z'));
319 }
320 
321 static int
322 digit(char ch)
323 {
324 	return ('0' <= ch && ch <= '9');
325 }
326