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 } 267