xref: /openbsd/games/hack/makedefs.c (revision 9b7c3dbb)
1 /*	$OpenBSD: makedefs.c,v 1.10 2016/01/09 18:33:15 mestre 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 <ctype.h>
65 #include <err.h>
66 #include <fcntl.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71 
72 /* construct definitions of object constants */
73 #define	LINSZ	1000
74 #define	STRSZ	40
75 
76 int fd;
77 char string[STRSZ];
78 
79 void capitalize(char *sp);
80 int  getentry(void);
81 int  skipuntil(char *s);
82 char nextchar(void);
83 void readline(void);
84 
85 int
86 main(int argc, char **argv)
87 {
88 	int index = 0;
89 	int propct = 0;
90 	char *sp;
91 
92 	if (pledge("stdio rpath", NULL) == -1)
93 		err(1, "pledge");
94 
95 	if (argc != 2) {
96 		(void)fprintf(stderr, "usage: makedefs file\n");
97 		return 1;
98 	}
99 	if ((fd = open(argv[1], O_RDONLY)) < 0) {
100 		perror(argv[1]);
101 		return 1;
102 	}
103 	skipuntil("objects[] = {");
104 	while(getentry()) {
105 		if(!*string){
106 			index++;
107 			continue;
108 		}
109 		for(sp = string; *sp; sp++)
110 			if(*sp == ' ' || *sp == '\t' || *sp == '-')
111 				*sp = '_';
112 		if(!strncmp(string, "RIN_", 4)){
113 			capitalize(string+4);
114 			printf("#define	%s	u.uprops[%d].p_flgs\n",
115 				string+4, propct++);
116 		}
117 		for(sp = string; *sp; sp++) capitalize(sp);
118 		/* avoid trouble with stupid C preprocessors */
119 		if(!strncmp(string, "WORTHLESS_PIECE_OF_", 19))
120 			printf("/* #define %s	%d */\n", string, index);
121 		else
122 			printf("#define	%s	%d\n", string, index);
123 		index++;
124 	}
125 	printf("\n#define	CORPSE	DEAD_HUMAN\n");
126 	printf("#define	LAST_GEM	(JADE+1)\n");
127 	printf("#define	LAST_RING	%d\n", propct);
128 	printf("#define	NROFOBJECTS	%d\n", index-1);
129 	return 0;
130 }
131 
132 char line[LINSZ], *lp = line, *lp0 = line, *lpe = line;
133 int eof;
134 
135 void
136 readline(void)
137 {
138 	int n = read(fd, lp0, (line+LINSZ)-lp0);
139 
140 	if(n < 0){
141 		printf("Input error.\n");
142 		exit(1);
143 	}
144 	if(n == 0) eof++;
145 	lpe = lp0+n;
146 }
147 
148 char
149 nextchar(void)
150 {
151 	if(lp == lpe){
152 		readline();
153 		lp = lp0;
154 	}
155 	return((lp == lpe) ? 0 : *lp++);
156 }
157 
158 int
159 skipuntil(char *s)
160 {
161 	char *sp0, *sp1;
162 
163 loop:
164 	while(*s != nextchar())
165 		if(eof) {
166 			printf("Cannot skipuntil %s\n", s);
167 			exit(1);
168 		}
169 	if(strlen(s) > lpe-lp+1){
170 		char *lp1, *lp2;
171 		lp2 = lp;
172 		lp1 = lp = lp0;
173 		while(lp2 != lpe) *lp1++ = *lp2++;
174 		lp2 = lp0;	/* save value */
175 		lp0 = lp1;
176 		readline();
177 		lp0 = lp2;
178 		if(strlen(s) > lpe-lp+1) {
179 			printf("error in skipuntil");
180 			exit(1);
181 		}
182 	}
183 	sp0 = s+1;
184 	sp1 = lp;
185 	while(*sp0 && *sp0 == *sp1) sp0++, sp1++;
186 	if(!*sp0){
187 		lp = sp1;
188 		return(1);
189 	}
190 	goto loop;
191 }
192 
193 int
194 getentry(void)
195 {
196 	int inbraces = 0, inparens = 0, stringseen = 0, commaseen = 0;
197 	int prefix = 0;
198 	char ch;
199 #define	NSZ	10
200 	char identif[NSZ], *ip;
201 
202 	string[0] = string[4] = 0;
203 	/* read until {...} or XXX(...) followed by ,
204 	   skip comment and #define lines
205 	   deliver 0 on failure
206 	 */
207 	while(1) {
208 		ch = nextchar();
209 	swi:
210 		if(isalpha((unsigned char)ch)){
211 			ip = identif;
212 			do {
213 				if(ip < identif+NSZ-1) *ip++ = ch;
214 				ch = nextchar();
215 			} while(isalpha((unsigned char)ch) || isdigit((unsigned char)ch));
216 			*ip = 0;
217 			while(ch == ' ' || ch == '\t') ch = nextchar();
218 			if(ch == '(' && !inparens && !stringseen)
219 				if(!strcmp(identif, "WAND") ||
220 				   !strcmp(identif, "RING") ||
221 				   !strcmp(identif, "POTION") ||
222 				   !strcmp(identif, "SCROLL"))
223 				(void) strncpy(string, identif, 3),
224 				string[3] = '_',
225 				prefix = 4;
226 		}
227 		switch(ch) {
228 		case '/':
229 			/* watch for comment */
230 			if((ch = nextchar()) == '*')
231 				skipuntil("*/");
232 			goto swi;
233 		case '{':
234 			inbraces++;
235 			continue;
236 		case '(':
237 			inparens++;
238 			continue;
239 		case '}':
240 			inbraces--;
241 			if(inbraces < 0) return(0);
242 			continue;
243 		case ')':
244 			inparens--;
245 			if(inparens < 0) {
246 				printf("too many ) ?");
247 				exit(1);
248 			}
249 			continue;
250 		case '\n':
251 			/* watch for #define at begin of line */
252 			if((ch = nextchar()) == '#'){
253 				char pch;
254 				/* skip until '\n' not preceded by '\\' */
255 				do {
256 					pch = ch;
257 					ch = nextchar();
258 				} while(ch != '\n' || pch == '\\');
259 				continue;
260 			}
261 			goto swi;
262 		case ',':
263 			if(!inparens && !inbraces){
264 				if(prefix && !string[prefix])
265 					string[0] = 0;
266 				if(stringseen) return(1);
267 				printf("unexpected ,\n");
268 				exit(1);
269 			}
270 			commaseen++;
271 			continue;
272 		case '\'':
273 			if((ch = nextchar()) == '\\') ch = nextchar();
274 			if(nextchar() != '\''){
275 				printf("strange character denotation?\n");
276 				exit(1);
277 			}
278 			continue;
279 		case '"':
280 			{
281 				char *sp = string + prefix;
282 				char pch;
283 				int store = (inbraces || inparens)
284 					&& !stringseen++ && !commaseen;
285 				do {
286 					pch = ch;
287 					ch = nextchar();
288 					if(store && sp < string+STRSZ)
289 						*sp++ = ch;
290 				} while(ch != '"' || pch == '\\');
291 				if(store) *--sp = 0;
292 				continue;
293 			}
294 		}
295 	}
296 }
297 
298 void
299 capitalize(char *sp)
300 {
301 	*sp = (char)toupper((unsigned char)*sp);
302 }
303