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