1*cdf0e10cSrcweir /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */ 2*cdf0e10cSrcweir /* 3*cdf0e10cSrcweir 4*cdf0e10cSrcweir Copyright (c) 1993, 1994 X Consortium 5*cdf0e10cSrcweir 6*cdf0e10cSrcweir Permission is hereby granted, free of charge, to any person obtaining a copy 7*cdf0e10cSrcweir of this software and associated documentation files (the "Software"), to deal 8*cdf0e10cSrcweir in the Software without restriction, including without limitation the rights 9*cdf0e10cSrcweir to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10*cdf0e10cSrcweir copies of the Software, and to permit persons to whom the Software is 11*cdf0e10cSrcweir furnished to do so, subject to the following conditions: 12*cdf0e10cSrcweir 13*cdf0e10cSrcweir The above copyright notice and this permission notice shall be included in 14*cdf0e10cSrcweir all copies or substantial portions of the Software. 15*cdf0e10cSrcweir 16*cdf0e10cSrcweir THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*cdf0e10cSrcweir IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*cdf0e10cSrcweir FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19*cdf0e10cSrcweir X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20*cdf0e10cSrcweir AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21*cdf0e10cSrcweir CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22*cdf0e10cSrcweir 23*cdf0e10cSrcweir Except as contained in this notice, the name of the X Consortium shall not be 24*cdf0e10cSrcweir used in advertising or otherwise to promote the sale, use or other dealings 25*cdf0e10cSrcweir in this Software without prior written authorization from the X Consortium. 26*cdf0e10cSrcweir 27*cdf0e10cSrcweir */ 28*cdf0e10cSrcweir 29*cdf0e10cSrcweir #include "def.h" 30*cdf0e10cSrcweir char *hash_lookup( char *symbol, struct symhash *symbols ); 31*cdf0e10cSrcweir void hash_undefine( char *symbol, struct symhash *symbols ); 32*cdf0e10cSrcweir int gobble( register struct filepointer *filep, struct inclist *file, 33*cdf0e10cSrcweir struct inclist *file_red, struct symhash *symbols ); 34*cdf0e10cSrcweir int deftype ( register char *line, register struct filepointer *filep, 35*cdf0e10cSrcweir register struct inclist *file_red, register struct inclist *file, 36*cdf0e10cSrcweir int parse_it, struct symhash *symbols); 37*cdf0e10cSrcweir int zero_value(register char *exp, register struct filepointer *filep, 38*cdf0e10cSrcweir register struct inclist *file_red, register struct symhash *symbols); 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir extern char *directives[]; 41*cdf0e10cSrcweir extern struct symhash *maininclist; 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir int find_includes(filep, file, file_red, recursion, failOK, incCollection, symbols) 44*cdf0e10cSrcweir struct filepointer *filep; 45*cdf0e10cSrcweir struct inclist *file, *file_red; 46*cdf0e10cSrcweir int recursion; 47*cdf0e10cSrcweir boolean failOK; 48*cdf0e10cSrcweir struct IncludesCollection* incCollection; 49*cdf0e10cSrcweir struct symhash *symbols; 50*cdf0e10cSrcweir { 51*cdf0e10cSrcweir register char *line; 52*cdf0e10cSrcweir register int type; 53*cdf0e10cSrcweir boolean recfailOK; 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir while ((line = get_line(filep))) { 56*cdf0e10cSrcweir switch(type = deftype(line, filep, file_red, file, TRUE, symbols)) { 57*cdf0e10cSrcweir case IF: 58*cdf0e10cSrcweir doif: 59*cdf0e10cSrcweir type = find_includes(filep, file, 60*cdf0e10cSrcweir file_red, recursion+1, failOK, incCollection, symbols); 61*cdf0e10cSrcweir while ((type == ELIF) || (type == ELIFFALSE) || 62*cdf0e10cSrcweir (type == ELIFGUESSFALSE)) 63*cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols); 64*cdf0e10cSrcweir if (type == ELSE) 65*cdf0e10cSrcweir gobble(filep, file, file_red, symbols); 66*cdf0e10cSrcweir break; 67*cdf0e10cSrcweir case IFFALSE: 68*cdf0e10cSrcweir case IFGUESSFALSE: 69*cdf0e10cSrcweir doiffalse: 70*cdf0e10cSrcweir if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) 71*cdf0e10cSrcweir recfailOK = TRUE; 72*cdf0e10cSrcweir else 73*cdf0e10cSrcweir recfailOK = failOK; 74*cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols); 75*cdf0e10cSrcweir if (type == ELSE) 76*cdf0e10cSrcweir find_includes(filep, file, 77*cdf0e10cSrcweir file_red, recursion+1, recfailOK, incCollection, symbols); 78*cdf0e10cSrcweir else 79*cdf0e10cSrcweir if (type == ELIF) 80*cdf0e10cSrcweir goto doif; 81*cdf0e10cSrcweir else 82*cdf0e10cSrcweir if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) 83*cdf0e10cSrcweir goto doiffalse; 84*cdf0e10cSrcweir break; 85*cdf0e10cSrcweir case IFDEF: 86*cdf0e10cSrcweir case IFNDEF: 87*cdf0e10cSrcweir if ((type == IFDEF && hash_lookup(line, symbols)) 88*cdf0e10cSrcweir || (type == IFNDEF && !hash_lookup(line, symbols))) { 89*cdf0e10cSrcweir debug(1,(type == IFNDEF ? 90*cdf0e10cSrcweir "line %d: %s !def'd in %s via %s%s\n" : "", 91*cdf0e10cSrcweir filep->f_line, line, 92*cdf0e10cSrcweir file->i_file, file_red->i_file, ": doit")); 93*cdf0e10cSrcweir type = find_includes(filep, file, 94*cdf0e10cSrcweir file_red, recursion+1, failOK, incCollection, symbols); 95*cdf0e10cSrcweir while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) 96*cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols); 97*cdf0e10cSrcweir if (type == ELSE) 98*cdf0e10cSrcweir gobble(filep, file, file_red, symbols); 99*cdf0e10cSrcweir } 100*cdf0e10cSrcweir else { 101*cdf0e10cSrcweir debug(1,(type == IFDEF ? 102*cdf0e10cSrcweir "line %d: %s !def'd in %s via %s%s\n" : "", 103*cdf0e10cSrcweir filep->f_line, line, 104*cdf0e10cSrcweir file->i_file, file_red->i_file, ": gobble")); 105*cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols); 106*cdf0e10cSrcweir if (type == ELSE) 107*cdf0e10cSrcweir find_includes(filep, file, 108*cdf0e10cSrcweir file_red, recursion + 1, failOK, incCollection, symbols); 109*cdf0e10cSrcweir else if (type == ELIF) 110*cdf0e10cSrcweir goto doif; 111*cdf0e10cSrcweir else if (type == ELIFFALSE || type == ELIFGUESSFALSE) 112*cdf0e10cSrcweir goto doiffalse; 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir break; 115*cdf0e10cSrcweir case ELSE: 116*cdf0e10cSrcweir case ELIFFALSE: 117*cdf0e10cSrcweir case ELIFGUESSFALSE: 118*cdf0e10cSrcweir case ELIF: 119*cdf0e10cSrcweir if (!recursion) 120*cdf0e10cSrcweir gobble(filep, file, file_red, symbols); 121*cdf0e10cSrcweir case ENDIF: 122*cdf0e10cSrcweir if (recursion) 123*cdf0e10cSrcweir return(type); 124*cdf0e10cSrcweir case DEFINE: 125*cdf0e10cSrcweir define(line, &symbols); 126*cdf0e10cSrcweir break; 127*cdf0e10cSrcweir case UNDEF: 128*cdf0e10cSrcweir if (!*line) { 129*cdf0e10cSrcweir warning("%s, line %d: incomplete undef == \"%s\"\n", 130*cdf0e10cSrcweir file_red->i_file, filep->f_line, line); 131*cdf0e10cSrcweir break; 132*cdf0e10cSrcweir } 133*cdf0e10cSrcweir hash_undefine(line, symbols); 134*cdf0e10cSrcweir break; 135*cdf0e10cSrcweir case INCLUDE: 136*cdf0e10cSrcweir add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols); 137*cdf0e10cSrcweir break; 138*cdf0e10cSrcweir case INCLUDEDOT: 139*cdf0e10cSrcweir add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols); 140*cdf0e10cSrcweir break; 141*cdf0e10cSrcweir case ERROR: 142*cdf0e10cSrcweir warning("%s: %d: %s\n", file_red->i_file, 143*cdf0e10cSrcweir filep->f_line, line); 144*cdf0e10cSrcweir break; 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir case PRAGMA: 147*cdf0e10cSrcweir case IDENT: 148*cdf0e10cSrcweir case SCCS: 149*cdf0e10cSrcweir case EJECT: 150*cdf0e10cSrcweir break; 151*cdf0e10cSrcweir case -1: 152*cdf0e10cSrcweir warning("%s", file_red->i_file); 153*cdf0e10cSrcweir if (file_red != file) 154*cdf0e10cSrcweir warning1(" (reading %s)", file->i_file); 155*cdf0e10cSrcweir warning1(", line %d: unknown directive == \"%s\"\n", 156*cdf0e10cSrcweir filep->f_line, line); 157*cdf0e10cSrcweir break; 158*cdf0e10cSrcweir case -2: 159*cdf0e10cSrcweir warning("%s", file_red->i_file); 160*cdf0e10cSrcweir if (file_red != file) 161*cdf0e10cSrcweir warning1(" (reading %s)", file->i_file); 162*cdf0e10cSrcweir warning1(", line %d: incomplete include == \"%s\"\n", 163*cdf0e10cSrcweir filep->f_line, line); 164*cdf0e10cSrcweir break; 165*cdf0e10cSrcweir } 166*cdf0e10cSrcweir } 167*cdf0e10cSrcweir return(-1); 168*cdf0e10cSrcweir } 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir int gobble(filep, file, file_red, symbols) 171*cdf0e10cSrcweir register struct filepointer *filep; 172*cdf0e10cSrcweir struct inclist *file, *file_red; 173*cdf0e10cSrcweir struct symhash *symbols; 174*cdf0e10cSrcweir { 175*cdf0e10cSrcweir register char *line; 176*cdf0e10cSrcweir register int type; 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir while ((line = get_line(filep))) { 179*cdf0e10cSrcweir switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) { 180*cdf0e10cSrcweir case IF: 181*cdf0e10cSrcweir case IFFALSE: 182*cdf0e10cSrcweir case IFGUESSFALSE: 183*cdf0e10cSrcweir case IFDEF: 184*cdf0e10cSrcweir case IFNDEF: 185*cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols); 186*cdf0e10cSrcweir while ((type == ELIF) || (type == ELIFFALSE) || 187*cdf0e10cSrcweir (type == ELIFGUESSFALSE)) 188*cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols); 189*cdf0e10cSrcweir if (type == ELSE) 190*cdf0e10cSrcweir (void)gobble(filep, file, file_red, symbols); 191*cdf0e10cSrcweir break; 192*cdf0e10cSrcweir case ELSE: 193*cdf0e10cSrcweir case ENDIF: 194*cdf0e10cSrcweir debug(0,("%s, line %d: #%s\n", 195*cdf0e10cSrcweir file->i_file, filep->f_line, 196*cdf0e10cSrcweir directives[type])); 197*cdf0e10cSrcweir return(type); 198*cdf0e10cSrcweir case DEFINE: 199*cdf0e10cSrcweir case UNDEF: 200*cdf0e10cSrcweir case INCLUDE: 201*cdf0e10cSrcweir case INCLUDEDOT: 202*cdf0e10cSrcweir case PRAGMA: 203*cdf0e10cSrcweir case ERROR: 204*cdf0e10cSrcweir case IDENT: 205*cdf0e10cSrcweir case SCCS: 206*cdf0e10cSrcweir case EJECT: 207*cdf0e10cSrcweir break; 208*cdf0e10cSrcweir case ELIF: 209*cdf0e10cSrcweir case ELIFFALSE: 210*cdf0e10cSrcweir case ELIFGUESSFALSE: 211*cdf0e10cSrcweir return(type); 212*cdf0e10cSrcweir case -1: 213*cdf0e10cSrcweir warning("%s, line %d: unknown directive == \"%s\"\n", 214*cdf0e10cSrcweir file_red->i_file, filep->f_line, line); 215*cdf0e10cSrcweir break; 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir return(-1); 219*cdf0e10cSrcweir } 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir /* 222*cdf0e10cSrcweir * Decide what type of # directive this line is. 223*cdf0e10cSrcweir */ 224*cdf0e10cSrcweir int deftype (line, filep, file_red, file, parse_it, symbols) 225*cdf0e10cSrcweir register char *line; 226*cdf0e10cSrcweir register struct filepointer *filep; 227*cdf0e10cSrcweir register struct inclist *file_red, *file; 228*cdf0e10cSrcweir int parse_it; 229*cdf0e10cSrcweir struct symhash *symbols; 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir register char *p; 232*cdf0e10cSrcweir char *directive, savechar; 233*cdf0e10cSrcweir register int ret; 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir /* 236*cdf0e10cSrcweir * Parse the directive... 237*cdf0e10cSrcweir */ 238*cdf0e10cSrcweir directive=line+1; 239*cdf0e10cSrcweir while (*directive == ' ' || *directive == '\t') 240*cdf0e10cSrcweir directive++; 241*cdf0e10cSrcweir 242*cdf0e10cSrcweir p = directive; 243*cdf0e10cSrcweir while (*p >= 'a' && *p <= 'z') 244*cdf0e10cSrcweir p++; 245*cdf0e10cSrcweir savechar = *p; 246*cdf0e10cSrcweir *p = '\0'; 247*cdf0e10cSrcweir ret = match(directive, directives); 248*cdf0e10cSrcweir *p = savechar; 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir /* If we don't recognize this compiler directive or we happen to just 251*cdf0e10cSrcweir * be gobbling up text while waiting for an #endif or #elif or #else 252*cdf0e10cSrcweir * in the case of an #elif we must check the zero_value and return an 253*cdf0e10cSrcweir * ELIF or an ELIFFALSE. 254*cdf0e10cSrcweir */ 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir if (ret == ELIF && !parse_it) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir while (*p == ' ' || *p == '\t') 259*cdf0e10cSrcweir p++; 260*cdf0e10cSrcweir /* 261*cdf0e10cSrcweir * parse an expression. 262*cdf0e10cSrcweir */ 263*cdf0e10cSrcweir debug(0,("%s, line %d: #elif %s ", 264*cdf0e10cSrcweir file->i_file, filep->f_line, p)); 265*cdf0e10cSrcweir ret = zero_value(p, filep, file_red, symbols); 266*cdf0e10cSrcweir if (ret != IF) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir debug(0,("false...\n")); 269*cdf0e10cSrcweir if (ret == IFFALSE) 270*cdf0e10cSrcweir return(ELIFFALSE); 271*cdf0e10cSrcweir else 272*cdf0e10cSrcweir return(ELIFGUESSFALSE); 273*cdf0e10cSrcweir } 274*cdf0e10cSrcweir else 275*cdf0e10cSrcweir { 276*cdf0e10cSrcweir debug(0,("true...\n")); 277*cdf0e10cSrcweir return(ELIF); 278*cdf0e10cSrcweir } 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir if (ret < 0 || ! parse_it) 282*cdf0e10cSrcweir return(ret); 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir /* 285*cdf0e10cSrcweir * now decide how to parse the directive, and do it. 286*cdf0e10cSrcweir */ 287*cdf0e10cSrcweir while (*p == ' ' || *p == '\t') 288*cdf0e10cSrcweir p++; 289*cdf0e10cSrcweir switch (ret) { 290*cdf0e10cSrcweir case IF: 291*cdf0e10cSrcweir /* 292*cdf0e10cSrcweir * parse an expression. 293*cdf0e10cSrcweir */ 294*cdf0e10cSrcweir ret = zero_value(p, filep, file_red, symbols); 295*cdf0e10cSrcweir debug(0,("%s, line %d: %s #if %s\n", 296*cdf0e10cSrcweir file->i_file, filep->f_line, ret?"false":"true", p)); 297*cdf0e10cSrcweir break; 298*cdf0e10cSrcweir case IFDEF: 299*cdf0e10cSrcweir case IFNDEF: 300*cdf0e10cSrcweir debug(0,("%s, line %d: #%s %s\n", 301*cdf0e10cSrcweir file->i_file, filep->f_line, directives[ret], p)); 302*cdf0e10cSrcweir case UNDEF: 303*cdf0e10cSrcweir /* 304*cdf0e10cSrcweir * separate the name of a single symbol. 305*cdf0e10cSrcweir */ 306*cdf0e10cSrcweir while (isalnum(*p) || *p == '_') 307*cdf0e10cSrcweir *line++ = *p++; 308*cdf0e10cSrcweir *line = '\0'; 309*cdf0e10cSrcweir break; 310*cdf0e10cSrcweir case INCLUDE: 311*cdf0e10cSrcweir debug(2,("%s, line %d: #include %s\n", 312*cdf0e10cSrcweir file->i_file, filep->f_line, p)); 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir /* Support ANSI macro substitution */ 315*cdf0e10cSrcweir { 316*cdf0e10cSrcweir char *sym = hash_lookup(p, symbols); 317*cdf0e10cSrcweir while (sym) 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir p = sym; 320*cdf0e10cSrcweir debug(3,("%s : #includes SYMBOL %s\n", 321*cdf0e10cSrcweir file->i_incstring, 322*cdf0e10cSrcweir sym)); 323*cdf0e10cSrcweir /* mark file as having included a 'soft include' */ 324*cdf0e10cSrcweir file->i_included_sym = TRUE; 325*cdf0e10cSrcweir sym = hash_lookup(p, symbols); 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir } 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir /* 330*cdf0e10cSrcweir * Separate the name of the include file. 331*cdf0e10cSrcweir */ 332*cdf0e10cSrcweir while (*p && *p != '"' && *p != '<') 333*cdf0e10cSrcweir p++; 334*cdf0e10cSrcweir if (! *p) 335*cdf0e10cSrcweir return(-2); 336*cdf0e10cSrcweir if (*p++ == '"') { 337*cdf0e10cSrcweir ret = INCLUDEDOT; 338*cdf0e10cSrcweir while (*p && *p != '"') 339*cdf0e10cSrcweir *line++ = *p++; 340*cdf0e10cSrcweir } else 341*cdf0e10cSrcweir while (*p && *p != '>') 342*cdf0e10cSrcweir *line++ = *p++; 343*cdf0e10cSrcweir *line = '\0'; 344*cdf0e10cSrcweir break; 345*cdf0e10cSrcweir case DEFINE: 346*cdf0e10cSrcweir /* 347*cdf0e10cSrcweir * copy the definition back to the beginning of the line. 348*cdf0e10cSrcweir */ 349*cdf0e10cSrcweir strcpy (line, p); 350*cdf0e10cSrcweir break; 351*cdf0e10cSrcweir case ELSE: 352*cdf0e10cSrcweir case ENDIF: 353*cdf0e10cSrcweir case ELIF: 354*cdf0e10cSrcweir case PRAGMA: 355*cdf0e10cSrcweir case ERROR: 356*cdf0e10cSrcweir case IDENT: 357*cdf0e10cSrcweir case SCCS: 358*cdf0e10cSrcweir case EJECT: 359*cdf0e10cSrcweir debug(0,("%s, line %d: #%s\n", 360*cdf0e10cSrcweir file->i_file, filep->f_line, directives[ret])); 361*cdf0e10cSrcweir /* 362*cdf0e10cSrcweir * nothing to do. 363*cdf0e10cSrcweir */ 364*cdf0e10cSrcweir break; 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir return(ret); 367*cdf0e10cSrcweir } 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir /* 370*cdf0e10cSrcweir * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c 371*cdf0e10cSrcweir * function... It's safe, functions from cppsetup.c don't return here. 372*cdf0e10cSrcweir */ 373*cdf0e10cSrcweir struct symhash *global_symbols = NULL; 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir char * isdefined( symbol ) 376*cdf0e10cSrcweir register char *symbol; 377*cdf0e10cSrcweir { 378*cdf0e10cSrcweir return hash_lookup( symbol, global_symbols ); 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir /* 382*cdf0e10cSrcweir * Return type based on if the #if expression evaluates to 0 383*cdf0e10cSrcweir */ 384*cdf0e10cSrcweir int zero_value(exp, filep, file_red, symbols) 385*cdf0e10cSrcweir register char *exp; 386*cdf0e10cSrcweir register struct filepointer *filep; 387*cdf0e10cSrcweir register struct inclist *file_red; 388*cdf0e10cSrcweir register struct symhash *symbols; 389*cdf0e10cSrcweir { 390*cdf0e10cSrcweir global_symbols = symbols; /* HACK! see above */ 391*cdf0e10cSrcweir if (cppsetup(exp, filep, file_red)) 392*cdf0e10cSrcweir return(IFFALSE); 393*cdf0e10cSrcweir else 394*cdf0e10cSrcweir return(IF); 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir void define( def, symbols ) 398*cdf0e10cSrcweir char *def; 399*cdf0e10cSrcweir struct symhash **symbols; 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir char *val; 402*cdf0e10cSrcweir 403*cdf0e10cSrcweir /* Separate symbol name and its value */ 404*cdf0e10cSrcweir val = def; 405*cdf0e10cSrcweir while (isalnum(*val) || *val == '_') 406*cdf0e10cSrcweir val++; 407*cdf0e10cSrcweir if (*val) 408*cdf0e10cSrcweir *val++ = '\0'; 409*cdf0e10cSrcweir while (*val == ' ' || *val == '\t') 410*cdf0e10cSrcweir val++; 411*cdf0e10cSrcweir 412*cdf0e10cSrcweir if (!*val) 413*cdf0e10cSrcweir val = "1"; 414*cdf0e10cSrcweir hash_define( def, val, symbols ); 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir static int hash( str ) 418*cdf0e10cSrcweir register char *str; 419*cdf0e10cSrcweir { 420*cdf0e10cSrcweir /* Hash (Kernighan and Ritchie) */ 421*cdf0e10cSrcweir register unsigned int hashval = 0; 422*cdf0e10cSrcweir //char *s = str; 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir for ( ; *str; str++ ) 425*cdf0e10cSrcweir { 426*cdf0e10cSrcweir hashval = ( hashval * SYMHASHSEED ) + ( *str ); 427*cdf0e10cSrcweir } 428*cdf0e10cSrcweir 429*cdf0e10cSrcweir //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) ); 430*cdf0e10cSrcweir return hashval & ( SYMHASHMEMBERS - 1 ); 431*cdf0e10cSrcweir } 432*cdf0e10cSrcweir 433*cdf0e10cSrcweir struct symhash *hash_copy( symbols ) 434*cdf0e10cSrcweir struct symhash *symbols; 435*cdf0e10cSrcweir { 436*cdf0e10cSrcweir int i; 437*cdf0e10cSrcweir struct symhash *newsym; 438*cdf0e10cSrcweir if ( !symbols ) 439*cdf0e10cSrcweir return NULL; 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir newsym = (struct symhash *) malloc( sizeof( struct symhash ) ); 442*cdf0e10cSrcweir 443*cdf0e10cSrcweir for ( i = 0; i < SYMHASHMEMBERS; ++i ) 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir if ( !symbols->s_pairs[ i ] ) 446*cdf0e10cSrcweir newsym->s_pairs[ i ] = NULL; 447*cdf0e10cSrcweir else 448*cdf0e10cSrcweir { 449*cdf0e10cSrcweir struct pair *it = symbols->s_pairs[ i ]; 450*cdf0e10cSrcweir struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) ); 451*cdf0e10cSrcweir nw->p_name = it->p_name; 452*cdf0e10cSrcweir nw->p_value = it->p_value; 453*cdf0e10cSrcweir nw->p_next = NULL; 454*cdf0e10cSrcweir 455*cdf0e10cSrcweir while ( it->p_next ) 456*cdf0e10cSrcweir { 457*cdf0e10cSrcweir nw->p_next = (struct pair*) malloc( sizeof( struct pair ) ); 458*cdf0e10cSrcweir it = it->p_next; 459*cdf0e10cSrcweir nw = nw->p_next; 460*cdf0e10cSrcweir nw->p_name = it->p_name; 461*cdf0e10cSrcweir nw->p_value = it->p_value; 462*cdf0e10cSrcweir nw->p_next = NULL; 463*cdf0e10cSrcweir } 464*cdf0e10cSrcweir } 465*cdf0e10cSrcweir } 466*cdf0e10cSrcweir return newsym; 467*cdf0e10cSrcweir } 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir void hash_free( symbols ) 470*cdf0e10cSrcweir struct symhash *symbols; 471*cdf0e10cSrcweir { 472*cdf0e10cSrcweir int i; 473*cdf0e10cSrcweir 474*cdf0e10cSrcweir if ( !symbols ) 475*cdf0e10cSrcweir return; 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir for ( i = 0; i < SYMHASHMEMBERS; ++i ) 478*cdf0e10cSrcweir { 479*cdf0e10cSrcweir struct pair *it = symbols->s_pairs[ i ]; 480*cdf0e10cSrcweir struct pair *next; 481*cdf0e10cSrcweir while ( it ) 482*cdf0e10cSrcweir { 483*cdf0e10cSrcweir next = it->p_next; 484*cdf0e10cSrcweir free( it ); 485*cdf0e10cSrcweir it = next; 486*cdf0e10cSrcweir } 487*cdf0e10cSrcweir } 488*cdf0e10cSrcweir free( symbols->s_pairs ); 489*cdf0e10cSrcweir } 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir void hash_define( name, val, symbols ) 492*cdf0e10cSrcweir char *name, *val; 493*cdf0e10cSrcweir struct symhash **symbols; 494*cdf0e10cSrcweir { 495*cdf0e10cSrcweir int hashval; 496*cdf0e10cSrcweir struct pair *it; 497*cdf0e10cSrcweir 498*cdf0e10cSrcweir if ( !symbols ) 499*cdf0e10cSrcweir return; 500*cdf0e10cSrcweir 501*cdf0e10cSrcweir /* Make space if it's needed */ 502*cdf0e10cSrcweir if ( *symbols == NULL ) 503*cdf0e10cSrcweir { 504*cdf0e10cSrcweir int i; 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir *symbols = (struct symhash *) malloc( sizeof( struct symhash ) ); 507*cdf0e10cSrcweir if ( *symbols == NULL ) 508*cdf0e10cSrcweir fatalerr( "malloc()/realloc() failure in insert_defn()\n" ); 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir for ( i = 0; i < SYMHASHMEMBERS; ++i ) 511*cdf0e10cSrcweir (*symbols)->s_pairs[i] = NULL; 512*cdf0e10cSrcweir } 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir hashval = hash( name ); 515*cdf0e10cSrcweir it = (*symbols)->s_pairs[ hashval ]; 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir /* Replace/insert the symbol */ 518*cdf0e10cSrcweir if ( it == NULL ) 519*cdf0e10cSrcweir { 520*cdf0e10cSrcweir it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) ); 521*cdf0e10cSrcweir it->p_name = copy( name ); 522*cdf0e10cSrcweir it->p_value = copy( val ); 523*cdf0e10cSrcweir it->p_next = NULL; 524*cdf0e10cSrcweir } 525*cdf0e10cSrcweir else if ( strcmp( it->p_name, name ) == 0 ) 526*cdf0e10cSrcweir { 527*cdf0e10cSrcweir it->p_value = copy( val ); 528*cdf0e10cSrcweir } 529*cdf0e10cSrcweir else 530*cdf0e10cSrcweir { 531*cdf0e10cSrcweir while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) ) 532*cdf0e10cSrcweir { 533*cdf0e10cSrcweir it = it->p_next; 534*cdf0e10cSrcweir } 535*cdf0e10cSrcweir if ( it->p_next ) 536*cdf0e10cSrcweir it->p_next->p_name = copy( name ); 537*cdf0e10cSrcweir else 538*cdf0e10cSrcweir { 539*cdf0e10cSrcweir it->p_next = (struct pair*) malloc( sizeof( struct pair ) ); 540*cdf0e10cSrcweir it->p_next->p_name = copy( name ); 541*cdf0e10cSrcweir it->p_next->p_value = copy( val ); 542*cdf0e10cSrcweir it->p_next->p_next = NULL; 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir } 545*cdf0e10cSrcweir } 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir char *hash_lookup( symbol, symbols ) 548*cdf0e10cSrcweir char *symbol; 549*cdf0e10cSrcweir struct symhash *symbols; 550*cdf0e10cSrcweir { 551*cdf0e10cSrcweir struct pair *it; 552*cdf0e10cSrcweir 553*cdf0e10cSrcweir if ( !symbols ) 554*cdf0e10cSrcweir return NULL; 555*cdf0e10cSrcweir 556*cdf0e10cSrcweir it = symbols->s_pairs[ hash( symbol ) ]; 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir while ( it && ( strcmp( it->p_name, symbol ) != 0 ) ) 559*cdf0e10cSrcweir { 560*cdf0e10cSrcweir it = it->p_next; 561*cdf0e10cSrcweir } 562*cdf0e10cSrcweir if ( it ) 563*cdf0e10cSrcweir return it->p_value; 564*cdf0e10cSrcweir 565*cdf0e10cSrcweir return NULL; 566*cdf0e10cSrcweir } 567*cdf0e10cSrcweir 568*cdf0e10cSrcweir void hash_undefine( symbol, symbols ) 569*cdf0e10cSrcweir char *symbol; 570*cdf0e10cSrcweir struct symhash *symbols; 571*cdf0e10cSrcweir { 572*cdf0e10cSrcweir int hashval; 573*cdf0e10cSrcweir struct pair *it; 574*cdf0e10cSrcweir 575*cdf0e10cSrcweir if ( !symbols ) 576*cdf0e10cSrcweir return; 577*cdf0e10cSrcweir 578*cdf0e10cSrcweir hashval = hash( symbol ); 579*cdf0e10cSrcweir it = symbols->s_pairs[ hashval ]; 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir /* Replace/insert the symbol */ 582*cdf0e10cSrcweir if ( it == NULL ) 583*cdf0e10cSrcweir return; 584*cdf0e10cSrcweir else if ( strcmp( it->p_name, symbol ) == 0 ) 585*cdf0e10cSrcweir { 586*cdf0e10cSrcweir if ( it->p_next ) 587*cdf0e10cSrcweir { 588*cdf0e10cSrcweir struct pair *tmp; 589*cdf0e10cSrcweir it->p_name = it->p_next->p_name; 590*cdf0e10cSrcweir it->p_value = it->p_next->p_value; 591*cdf0e10cSrcweir tmp = it->p_next->p_next; 592*cdf0e10cSrcweir free( it->p_next ); 593*cdf0e10cSrcweir it->p_next = tmp; 594*cdf0e10cSrcweir } 595*cdf0e10cSrcweir else 596*cdf0e10cSrcweir { 597*cdf0e10cSrcweir free( it ); 598*cdf0e10cSrcweir symbols->s_pairs[ hashval ] = NULL; 599*cdf0e10cSrcweir } 600*cdf0e10cSrcweir } 601*cdf0e10cSrcweir else 602*cdf0e10cSrcweir { 603*cdf0e10cSrcweir while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) ) 604*cdf0e10cSrcweir { 605*cdf0e10cSrcweir it = it->p_next; 606*cdf0e10cSrcweir } 607*cdf0e10cSrcweir if ( it->p_next ) 608*cdf0e10cSrcweir { 609*cdf0e10cSrcweir struct pair *tmp = it->p_next; 610*cdf0e10cSrcweir it->p_next = it->p_next->p_next; 611*cdf0e10cSrcweir free( tmp ); 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir } 614*cdf0e10cSrcweir } 615