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