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