Merge from vendor branch LIBARCHIVE:
[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         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 }