home *** CD-ROM | disk | FTP | other *** search
- /*
- C* -- macro symbol table routines.
-
- source: mst.c
- started: September 22, 1985
- version:
- January 7, 1987
- March 7, 1989
-
- PUBLIC DOMAIN SOFTWARE
-
- The CSTAR program was placed in the public domain on June 15, 1991,
- by its author and sole owner,
-
- Edward K. Ream
- 1617 Monroe Street
- Madison, WI 53711
- (608) 257-0802
-
- CSTAR may be used for any commercial or non-commercial purpose.
-
- See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
- */
- #include "cstar.h"
-
- /*
- Externally visible routines:
- */
- void mst_delete (char * symbol);
- struct mst_node * mst_enter (char * symbol, char * txt, int nargs);
- void mst_init (void);
- void mst2_init (void);
- struct mst_node * mst_lookup (char * symbol);
-
- /*
- Internal routines:
- */
- static int mst_hash (unsigned char * symbol);
-
- /*
- Define the hash table used to access macro table nodes.
- */
-
- #define MAC_PRIME 101
- struct mst_node * mst_ht [MAC_PRIME];
-
- #ifdef TESTING
-
- /*
- Dump all symbols of a symbol table.
- This function is used for debugging only.
- */
- void
- mst_dump (void)
- {
- register int i;
- register struct mst_node * bp;
-
- /* Dump hash table. */
- printf("The hash table is:\n");
- for (i = 0; i < MAC_PRIME; i++) {
- if (bp = mst_ht [i]) {
-
- printf("mst_ht [%3d] = %p\n", i, bp);
-
- do {
- mst_1dump(bp);
- } while (bp = bp -> mst_next);
- }
- }
- }
-
- void
- mst_1dump(register struct mst_node * bp)
- {
- printf("bp= %4lx, next= %4lx, ", bp, bp -> mst_next);
- printf("hash= %d, ", mst_hash(bp -> mst_name);
- printf("name= <%s> ", bp -> mst_name);
- printf("nargs= %d, ", bp -> mst_nargs);
- printf("text= <%s>\n", bp -> mst_text);
- }
-
- #endif /* TESTING */
-
- /*
- Remove ALL instances of a symbol from the symbol table.
- This ensures that an #undef will expose any non-macro version
- of a routine.
- */
- void
- mst_delete(register char * symbol)
- {
- register struct mst_node **bp0, *bp1, *bp2;
-
- TRACEPB("mst_delete", printf("(%s)\n", symbol));
-
- /* Point bp0 into hash table. */
- bp0 = &mst_ht[0];
- bp0 += mst_hash(symbol);
-
- /* bp2 is current node pointer. */
- bp2 = *bp0;
-
- /* Special case: delete the first node. */
- while (bp2 != NULL) {
-
- if(str_eq(symbol, bp2 -> mst_name)) {
- *bp0 = bp2 -> mst_next;
- mg_free( (char *) bp2);
- bp2 = *bp0;
- }
-
- else {
- bp2 = bp2 -> mst_next;
- bp1 = *bp0;
- break;
- }
- }
-
- /* bp1 is undefined here only if bp2 == NULL */
-
- /* General case */
- while (bp2 != NULL) {
-
- if(str_eq(symbol, bp2 -> mst_name)) {
- bp1 -> mst_next = bp2 -> mst_next;
- mg_free( (char *) bp2);
- bp2 = bp1 -> mst_next;
- }
- else {
- bp1 = bp2;
- bp2 = bp2 -> mst_next;
- }
- }
- TICKX("mst_delete");
- }
-
- /*
- Place a macro in the symbol table along with the number of arguments
- to the macro and a pointer to the macro's replacement text.
-
- Multiple entries for a symbol can exist in which case the last entry
- defined is active.
- Return a pointer to the allocated node or NULL.
-
- This code conforms to the new standard. It rejects duplicate
- definitions of a macro unless the new definition is exactly the
- same as the old.
-
- This code also checks the "initial undef list" to see if the first
- definition of a macro should be ignored. If the macro name is
- found on the list, it is removed from the list and no entry is made
- in the macro symbol table.
- */
- struct mst_node *
- mst_enter(register char * symbol, register char * txt, register int nargs)
- {
- register struct mst_node **bp0, *bp1;
- int hash;
- struct mst_node * bp;
- struct u_node *up1, *up2;
- char msg [100];
- extern struct u_node undef_list;
-
- /*
- Search the global "initial undef list" (created by command line
- -u arguments) to see if the initial definition of name should
- be rejected. If the name appears on the list, remove it from
- the list and do not enter the name in the macro table.
- */
-
- TRACEPB("mst_enter", printf("(%s, %s, %d)\n", symbol, txt, nargs));
-
- if (undef_list . u_next != NULL) {
- up1 = &undef_list;
- up2 = up1 -> u_next;
-
- while (up2 != NULL) {
- if (str_eq(symbol, up2 -> u_name)) {
- up1 -> u_next = up2 -> u_next;
- RETURN_PTR("mst_enter", NULL);
- }
- else {
- up1 = up2;
- up2 = up2 -> u_next;
- }
- }
- }
-
- /* Search down the list of mst_nodes. */
- hash = mst_hash(symbol);
- for (bp = mst_ht [hash]; 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)) {
-
- /* Benign redefinition. */
- strcpy(msg, "(Warning) ");
- strcat(msg, "Duplicate definition of ");
- strcat(msg, symbol);
- strcat(msg, ".");
- t_error(msg);
- RETURN_PTR("mst_enter", bp);
- }
- }
- strcpy(msg, "Non-identical redefinition of ");
- strcat(msg, symbol);
- strcat(msg, " ignored.");
- t_error(msg);
- RETURN_PTR("mst_enter", NULL);
- }
- }
-
- /* Dynamically allocate space for node. */
- bp1 = CAST(struct mst_node *) mg_alloc(sizeof(struct mst_node));
-
- /* Hang node from hash table. */
- bp0 = &mst_ht[0];
- bp0 += mst_hash(symbol);
-
- bp1 -> mst_next = *bp0;
- *bp0 = bp1;
-
- /* Fill in the name and text fields. */
- bp1 -> mst_name = str_galloc(symbol);
- bp1 -> mst_text = str_galloc(txt);
- bp1 -> mst_nargs = nargs;
-
- RETURN_PTR("mst_enter", bp1);
- }
-
- /*
- Return the hash value for symbol.
- */
- static int
- mst_hash (register unsigned char * symbol)
- {
- register int hash;
-
- SL_DISABLE();
-
- for (hash = 0; *symbol; ) {
- hash *= 3;
- hash += (int) *symbol++;
- hash %= MAC_PRIME;
- }
- return hash;
- }
-
- /*
- Initialize the macro module.
- */
- void
- mst_init(void)
- {
- register int i;
- register struct mst_node ** bp0;
-
- TICK("mst_init");
-
- /* Clear the hash table. */
- for (i = 0, bp0 = &mst_ht[0]; i < MAC_PRIME; i++) {
- *bp0++ = NULL;
- }
-
- /* Clear the "initial undef list." */
- undef_list . u_next = NULL;
- }
-
- /*
- Enter the predefined macros into the table.
- Do nothing if the initial definitions have been
- suppressed with -u options.
- */
- void
- mst2_init(void)
- {
- struct mst_node * bp;
- struct mst_node * mst_enter();
-
- /*
- Define the __line__ macro and allocate enough space for
- all line numbers.
- */
-
- TICKB("mst2_init");
-
- bp = mst_enter("__line__", "", -3);
- if (bp != NULL) {
- bp -> mst_text = mg_alloc(10);
- }
-
- /*
- Define the __file__ macro and allocate enough space
- for the largest possible file name.
- */
- bp = mst_enter("__file__", "", -3);
- if (bp != NULL) {
- bp -> mst_text = mg_alloc(MAX_FILE_NAME);
- }
-
- TICKX("mst2_init");
- }
-
- /*
- Look up a symbol in the macro table.
- Return a pointer to the node or NULL.
- */
- struct mst_node *
- mst_lookup (register char * symbol)
- {
- register struct mst_node ** bp0, *bp1;
- char buffer [100];
-
- /* Calculate the hash value of the symbol. */
-
- TRACEPB("mst_lookup", printf("(%s)\n", symbol));
-
- bp0 = &mst_ht[0];
- bp0 += mst_hash(symbol);
-
- /* Search down the list of mst_nodes. */
- for (bp1 = *bp0; bp1; bp1 = bp1 -> mst_next) {
-
- if (str_eq(symbol, bp1 -> mst_name)) {
-
- /* Special case for __line__ and __file__. */
- if (bp1 -> mst_nargs == -3) {
- if (str_eq(bp1 -> mst_name, "__line__")) {
- /* Set current line number. */
- conv2s(t_line, buffer);
- str_cpy(bp1 -> mst_text, buffer);
- }
- if (str_eq(bp1 -> mst_name, "__file__")) {
- /* Set current file name. */
- str_cpy(bp1 -> mst_text, t_file);
- }
- }
-
- /* Return success. */
-
- RETURN_PTR("mst_lookup", bp1);
- }
- }
-
- /* Return failure. */
-
- RETURN_PTR("mst_lookup", NULL);
- }
-