1 /* $NetBSD: makedefs.c,v 1.8 2003/04/02 18:36:42 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
65 static const char rcsid[] =
66     "$NetBSD: makedefs.c,v 1.8 2003/04/02 18:36:42 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 
79 int             fd;
80 char            string[STRSZ];
81 
82 static void readline(void);
83 static char nextchar(void);
84 static int skipuntil(const char *);
85 static int getentry(void);
86 static void capitalize(char *);
87 static int letter(int);
88 static int digit(int);
89 
90 int main(int, char **);
91 
92 int
main(argc,argv)93 main(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 
143 char            line[LINSZ], *lp = line, *lp0 = line, *lpe = line;
144 int             eof;
145 
146 static void
readline()147 readline()
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 
159 static char
nextchar()160 nextchar()
161 {
162           if (lp == lpe) {
163                     readline();
164                     lp = lp0;
165           }
166           return ((lp == lpe) ? 0 : *lp++);
167 }
168 
169 static int
skipuntil(s)170 skipuntil(s)
171           const char           *s;
172 {
173           const char *sp0;
174           char *sp1;
175 loop:
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 
207 static int
getentry()208 getentry()
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();
222 swi:
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 
317 static void
capitalize(sp)318 capitalize(sp)
319           char           *sp;
320 {
321           if ('a' <= *sp && *sp <= 'z')
322                     *sp += 'A' - 'a';
323 }
324 
325 static int
letter(ch)326 letter(ch)
327           char            ch;
328 {
329           return (('a' <= ch && ch <= 'z') ||
330                     ('A' <= ch && ch <= 'Z'));
331 }
332 
333 static int
digit(ch)334 digit(ch)
335           char            ch;
336 {
337           return ('0' <= ch && ch <= '9');
338 }
339