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