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