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