xref: /netbsd-src/games/hack/makedefs.c (revision ace896fac114f559f7469472324fbe68bbe378e5)
1 /*	$NetBSD: makedefs.c,v 1.5 1997/10/19 16:59:36 christos Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: makedefs.c,v 1.5 1997/10/19 16:59:36 christos Exp $");
10 #endif				/* not lint */
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 
17 /* construct definitions of object constants */
18 #define	LINSZ	1000
19 #define	STRSZ	40
20 
21 int             fd;
22 char            string[STRSZ];
23 
24 static void readline __P((void));
25 static char nextchar __P((void));
26 static int skipuntil __P((char *));
27 static int getentry __P((void));
28 static void capitalize __P((char *));
29 static int letter __P((int));
30 static int digit __P((int));
31 
32 int main __P((int, char **));
33 
34 int
35 main(argc, argv)
36 	int             argc;
37 	char          **argv;
38 {
39 	int             i = 0;
40 	int             propct = 0;
41 	char           *sp;
42 	if (argc != 2) {
43 		(void) fprintf(stderr, "usage: makedefs file\n");
44 		exit(1);
45 	}
46 	if ((fd = open(argv[1], 0)) < 0) {
47 		perror(argv[1]);
48 		exit(1);
49 	}
50 	skipuntil("objects[] = {");
51 	while (getentry()) {
52 		if (!*string) {
53 			i++;
54 			continue;
55 		}
56 		for (sp = string; *sp; sp++)
57 			if (*sp == ' ' || *sp == '\t' || *sp == '-')
58 				*sp = '_';
59 		if (!strncmp(string, "RIN_", 4)) {
60 			capitalize(string + 4);
61 			printf("#define	%s	u.uprops[%d].p_flgs\n",
62 			       string + 4, propct++);
63 		}
64 		for (sp = string; *sp; sp++)
65 			capitalize(sp);
66 		/* avoid trouble with stupid C preprocessors */
67 		if (!strncmp(string, "WORTHLESS_PIECE_OF_", 19))
68 			printf("/* #define %s	%d */\n", string, i);
69 		else
70 			printf("#define	%s	%d\n", string, i);
71 		i++;
72 	}
73 	printf("\n#define	CORPSE	DEAD_HUMAN\n");
74 	printf("#define	LAST_GEM	(JADE+1)\n");
75 	printf("#define	LAST_RING	%d\n", propct);
76 	printf("#define	NROFOBJECTS	%d\n", i - 1);
77 	exit(0);
78 }
79 
80 char            line[LINSZ], *lp = line, *lp0 = line, *lpe = line;
81 int             eof;
82 
83 static void
84 readline()
85 {
86 	int             n = read(fd, lp0, (line + LINSZ) - lp0);
87 	if (n < 0) {
88 		printf("Input error.\n");
89 		exit(1);
90 	}
91 	if (n == 0)
92 		eof++;
93 	lpe = lp0 + n;
94 }
95 
96 static char
97 nextchar()
98 {
99 	if (lp == lpe) {
100 		readline();
101 		lp = lp0;
102 	}
103 	return ((lp == lpe) ? 0 : *lp++);
104 }
105 
106 static int
107 skipuntil(s)
108 	char           *s;
109 {
110 	char           *sp0, *sp1;
111 loop:
112 	while (*s != nextchar())
113 		if (eof) {
114 			printf("Cannot skipuntil %s\n", s);
115 			exit(1);
116 		}
117 	if (strlen(s) > lpe - lp + 1) {
118 		char           *lp1, *lp2;
119 		lp2 = lp;
120 		lp1 = lp = lp0;
121 		while (lp2 != lpe)
122 			*lp1++ = *lp2++;
123 		lp2 = lp0;	/* save value */
124 		lp0 = lp1;
125 		readline();
126 		lp0 = lp2;
127 		if (strlen(s) > lpe - lp + 1) {
128 			printf("error in skipuntil");
129 			exit(1);
130 		}
131 	}
132 	sp0 = s + 1;
133 	sp1 = lp;
134 	while (*sp0 && *sp0 == *sp1)
135 		sp0++, sp1++;
136 	if (!*sp0) {
137 		lp = sp1;
138 		return (1);
139 	}
140 	goto loop;
141 }
142 
143 static int
144 getentry()
145 {
146 	int             inbraces = 0, inparens = 0, stringseen = 0, commaseen = 0;
147 	int             prefix = 0;
148 	char            ch;
149 #define	NSZ	10
150 	char            identif[NSZ], *ip;
151 	string[0] = string[4] = 0;
152 	/*
153 	 * read until {...} or XXX(...) followed by , skip comment and
154 	 * #define lines deliver 0 on failure
155 	 */
156 	while (1) {
157 		ch = nextchar();
158 swi:
159 		if (letter(ch)) {
160 			ip = identif;
161 			do {
162 				if (ip < identif + NSZ - 1)
163 					*ip++ = ch;
164 				ch = nextchar();
165 			} while (letter(ch) || digit(ch));
166 			*ip = 0;
167 			while (ch == ' ' || ch == '\t')
168 				ch = nextchar();
169 			if (ch == '(' && !inparens && !stringseen)
170 				if (!strcmp(identif, "WAND") ||
171 				    !strcmp(identif, "RING") ||
172 				    !strcmp(identif, "POTION") ||
173 				    !strcmp(identif, "SCROLL"))
174 					(void) strncpy(string, identif, 3),
175 						string[3] = '_',
176 						prefix = 4;
177 		}
178 		switch (ch) {
179 		case '/':
180 			/* watch for comment */
181 			if ((ch = nextchar()) == '*')
182 				skipuntil("*/");
183 			goto swi;
184 		case '{':
185 			inbraces++;
186 			continue;
187 		case '(':
188 			inparens++;
189 			continue;
190 		case '}':
191 			inbraces--;
192 			if (inbraces < 0)
193 				return (0);
194 			continue;
195 		case ')':
196 			inparens--;
197 			if (inparens < 0) {
198 				printf("too many ) ?");
199 				exit(1);
200 			}
201 			continue;
202 		case '\n':
203 			/* watch for #define at begin of line */
204 			if ((ch = nextchar()) == '#') {
205 				char            pch;
206 				/* skip until '\n' not preceded by '\\' */
207 				do {
208 					pch = ch;
209 					ch = nextchar();
210 				} while (ch != '\n' || pch == '\\');
211 				continue;
212 			}
213 			goto swi;
214 		case ',':
215 			if (!inparens && !inbraces) {
216 				if (prefix && !string[prefix])
217 					string[0] = 0;
218 				if (stringseen)
219 					return (1);
220 				printf("unexpected ,\n");
221 				exit(1);
222 			}
223 			commaseen++;
224 			continue;
225 		case '\'':
226 			if ((ch = nextchar()) == '\\')
227 				ch = nextchar();
228 			if (nextchar() != '\'') {
229 				printf("strange character denotation?\n");
230 				exit(1);
231 			}
232 			continue;
233 		case '"':
234 			{
235 				char           *sp = string + prefix;
236 				char            pch;
237 				int             store = (inbraces || inparens)
238 				&& !stringseen++ && !commaseen;
239 				do {
240 					pch = ch;
241 					ch = nextchar();
242 					if (store && sp < string + STRSZ)
243 						*sp++ = ch;
244 				} while (ch != '"' || pch == '\\');
245 				if (store)
246 					*--sp = 0;
247 				continue;
248 			}
249 		}
250 	}
251 }
252 
253 static void
254 capitalize(sp)
255 	char           *sp;
256 {
257 	if ('a' <= *sp && *sp <= 'z')
258 		*sp += 'A' - 'a';
259 }
260 
261 static int
262 letter(ch)
263 	char            ch;
264 {
265 	return (('a' <= ch && ch <= 'z') ||
266 		('A' <= ch && ch <= 'Z'));
267 }
268 
269 static int
270 digit(ch)
271 	char            ch;
272 {
273 	return ('0' <= ch && ch <= '9');
274 }
275