Blame | Last modification | View Log | RSS feed
/*CPP V5 -- macro symbol table routines.source: mst.cstarted: September 22, 1985version: May 26, 1988Written by Edward K. Ream.This software is in the public domain.See the read.me file for disclaimer and other information.*/#include "cpp.h"/* Declare local routines. */static int mst_hash (unsigned char *);/* Define the hash table used to access macro table nodes. */#define MAC_PRIME 101typedef struct mst_node mactab;static struct mst_node {mactab * mst_next; /* Pointer to next bucket. */int mst_nargs; /* Number of args in text. */char * mst_name; /* Pointer to name. */char * mst_text; /* Pointer to replacement text. */};static mactab mst_ht [MAC_PRIME];/*Define the "initial undef list" forarguments undefined on the command line.*/typedef struct u_node unode;static struct u_node {unode * u_next;char * u_name;};unode undef_list; /* list header. *//*Remove ALL instances of a symbol from the symbol table.This ensures that an #undef will expose any non-macro versionof a routine.*/voidmst_delete (symbol)register char * symbol;{register mactab *bp1, *bp2;int hash;TRACEP("mst_delete",printf("entry: symbol=<%s>\n", symbol));hash = mst_hash(symbol);bp1 = & mst_ht [hash];bp2 = bp1 -> mst_next;while(bp2 != NULL) {if(str_eq(symbol, bp2 -> mst_name)) {TRACEP("mst_delete", printf("deletes\n"));bp1 -> mst_next = bp2 -> mst_next;m_free(bp2);bp2 = bp1 -> mst_next;}else {bp1 = bp2;bp2 = bp2 -> mst_next;}}}/*Place a macro in the symbol table along with the number of argumentsto the macro and a pointer to the macro's replacement text.Multiple entries for a symbol can exist in which case the last entrydefined is active.This code conforms to the new standard. It rejects duplicatedefinitions of a macro unless the new definition is exactly thesame as the old.This code also checks the "initial undef list" to see if the firstdefinition of a macro should be ignored. If the macro name isfound on the list, it is removed from the list and no entry is madein the macro symbol table.*/voidmst_enter (symbol, txt, nargs)register char *symbol;register char *txt;register int nargs;{register mactab *bp, *bp2;int hash;unode *up1, *up2;TRACEP("mst_enter", printf("(%s, <%s>, %d)\n",symbol, pr_str(txt), nargs));/*Search the global "initial undef list" (created by command line-u arguments) to see if the initial definition of name shouldbe rejected. If the name appears on the list, remove it fromthe list and do not enter the name in the macro table.*/if (undef_list . u_next != NULL) {up1 = &undef_list;up2 = up1 -> u_next;while (up2 != NULL) {if (str_eq(symbol, up2 -> u_name)) {/* Remove the entry from the list. */up1 -> u_next = up2 -> u_next;return;}else {up1 = up2;up2 = up2 -> u_next;}}}/* Search down the list of mst_nodes. */hash = mst_hash(symbol);bp = & mst_ht [hash];for (bp = bp -> mst_next; bp; bp = bp -> mst_next) {/* Reject redefinitions of a macro unless identical. */if (str_eq (symbol, bp -> mst_name)) {if (nargs == bp -> mst_nargs) {if (str_eq(txt, bp -> mst_text)) {return;}}err3( "Non-identical redefinition of ", symbol," ignored.");return;}}/* Dynamically allocate space for node. */bp2 = m_alloc(sizeof(mactab));/* Hang node from hash table. */bp = & mst_ht [hash];bp2 -> mst_next = bp -> mst_next;bp -> mst_next = bp2;/* Fill in the name and text fields. */bp2 -> mst_name = str_alloc(symbol);bp2 -> mst_text = str_alloc(txt);bp2 -> mst_nargs = nargs;}/*Return the hash value for symbol.*/static intmst_hash (symbol)register unsigned char * symbol;{register int hash;STAT("mst_hash");for (hash = 0; *symbol; ) {hash *= 3;hash += (int) *symbol++;hash %= MAC_PRIME;}return hash;}/*Initialize the macro module.This must be done BEFORE command line arguments are processed.*/voidmst_init(){register int i;TICK("mst_init");/* Clear the hash table. */for (i = 0; i < MAC_PRIME; i++) {mst_ht [i] . mst_next = NULL;mst_ht [i] . mst_name = "<NAME>";mst_ht [i] . mst_text = "<TEXT>";mst_ht [i] . mst_nargs = 0;}/* Clear the "initial undef list." */undef_list . u_next = NULL;}/*Enter the predefined macros into the table.Do nothing if the initial definitions have beensuppressed with -u options.This must be done AFTER command line options have been processed.*/voidmst2_init(){mst_enter("__LINE__", "", -3);mst_enter("__FILE__", "", -3);mst_enter("__STDC__", "", -3);mst_enter("__TIME__", "", -3);mst_enter("__DATE__", "", -3);}/*Look up a symbol in the macro table.Return TRUE if found, and set text and nargs.*/boolmst_lookup(symbol, text, nargs)register char * symbol;char ** text;int *nargs;{register mactab *bp;char buffer [100];int hash;TRACEP("mst_lookup", printf("(%s)\n", symbol));/* Calculate the hash value of the symbol. */hash = mst_hash(symbol);bp = & mst_ht [hash];/* Search down the list of mst_nodes. */for (bp = bp -> mst_next; bp; bp = bp -> mst_next) {if (str_eq(symbol, bp -> mst_name)) {/* Special case for __line__ and __file__. */if (bp -> mst_nargs == -3) {if (str_eq(bp -> mst_name, "__LINE__")) {/* Set current line number. */conv2s(t_line, buffer);bp -> mst_text = str_alloc(buffer);}else if (str_eq(bp -> mst_name, "__FILE__")) {/* Set current file name. */strcpy(buffer, "\"");strcat(buffer, t_file);strcat(buffer, "\"");bp -> mst_text = str_alloc(buffer);}else if (str_eq(bp -> mst_name, "__TIME__")) {/* Set current file name. */bp -> mst_text = systime();}else if (str_eq(bp -> mst_name, "__DATE__")) {bp -> mst_text = sysdate();}else if (str_eq(bp -> mst_name, "__STDC__")) {bp -> mst_text = "1";}}/* Return success. */*nargs = max(-1, bp -> mst_nargs);*text = bp -> mst_text;TRACEP("mst_lookup", printf("found:\n"));return TRUE;}}TRACEP("mst_lookup", printf("not found\n"));/* Return failure. */return FALSE;}/*Add an argument to the "initial undef list."*/voidmst_unarg(arg)char * arg;{unode * p;TICK("mst_unarg");p = m_alloc(sizeof(unode));p -> u_name = arg;p -> u_next = undef_list . u_next;undef_list . u_next = p;}