home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 357_01 / cstar1.exe / MST.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  8KB  |  352 lines

  1. /*
  2.     C* -- macro symbol table routines.
  3.  
  4.     source:  mst.c
  5.     started: September 22, 1985
  6.     version:
  7.         January 7, 1987
  8.         March 7, 1989
  9.  
  10.     PUBLIC DOMAIN SOFTWARE
  11.  
  12.     The CSTAR program was placed in    the public domain on June 15, 1991,
  13.     by its author and sole owner,
  14.  
  15.         Edward K. Ream
  16.         1617 Monroe Street
  17.         Madison, WI 53711
  18.         (608) 257-0802
  19.  
  20.     CSTAR may be used for any commercial or non-commercial purpose.
  21.  
  22.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  23. */
  24. #include "cstar.h"
  25.  
  26. /*
  27.     Externally visible routines:
  28. */
  29. void        mst_delete    (char * symbol);
  30. struct mst_node * mst_enter    (char * symbol, char * txt, int nargs);
  31. void        mst_init    (void);
  32. void        mst2_init    (void);
  33. struct mst_node * mst_lookup    (char * symbol);
  34.  
  35. /*
  36.     Internal routines:
  37. */
  38. static int    mst_hash    (unsigned char * symbol);
  39.  
  40. /*
  41.     Define the hash table used to access macro table nodes.
  42. */
  43.  
  44. #define MAC_PRIME 101
  45. struct mst_node * mst_ht [MAC_PRIME];
  46.  
  47. #ifdef TESTING
  48.  
  49. /*
  50.     Dump all symbols of a symbol table.
  51.     This function is used for debugging only.
  52. */
  53. void
  54. mst_dump (void)
  55. {
  56.     register int i;
  57.     register struct mst_node * bp;
  58.  
  59.     /* Dump hash table. */
  60.     printf("The hash table is:\n");
  61.     for (i = 0; i < MAC_PRIME; i++) {
  62.         if (bp = mst_ht [i]) {
  63.  
  64.             printf("mst_ht [%3d] = %p\n", i, bp);
  65.  
  66.             do {
  67.                 mst_1dump(bp);
  68.             } while (bp = bp -> mst_next);
  69.         }
  70.     }
  71. }
  72.  
  73. void
  74. mst_1dump(register struct mst_node * bp)
  75. {
  76.     printf("bp= %4lx, next= %4lx, ", bp, bp -> mst_next);
  77.     printf("hash= %d, ",   mst_hash(bp -> mst_name);
  78.     printf("name= <%s> ",  bp -> mst_name);
  79.     printf("nargs= %d, ",  bp -> mst_nargs);
  80.     printf("text= <%s>\n", bp -> mst_text);
  81. }
  82.  
  83. #endif /* TESTING */
  84.  
  85. /*
  86.     Remove ALL instances of a symbol from the symbol table.
  87.     This ensures that an #undef will expose any non-macro version
  88.     of a routine.
  89. */
  90. void
  91. mst_delete(register char * symbol)
  92. {
  93.     register struct mst_node **bp0, *bp1, *bp2;
  94.  
  95.     TRACEPB("mst_delete", printf("(%s)\n", symbol));
  96.  
  97.     /* Point bp0 into hash table. */
  98.     bp0  = &mst_ht[0];
  99.     bp0 += mst_hash(symbol);
  100.  
  101.     /* bp2 is current node pointer. */
  102.     bp2 = *bp0;
  103.  
  104.     /* Special case: delete the first node. */
  105.     while (bp2 != NULL) {
  106.  
  107.         if(str_eq(symbol, bp2 -> mst_name)) {
  108.             *bp0 = bp2 -> mst_next;
  109.             mg_free( (char *) bp2);
  110.             bp2 = *bp0;
  111.         }
  112.     
  113.         else {
  114.             bp2 = bp2 -> mst_next;
  115.             bp1 = *bp0;
  116.             break;
  117.         }
  118.     }
  119.  
  120.     /* bp1 is undefined here only if bp2 == NULL */
  121.  
  122.     /* General case */
  123.     while (bp2 != NULL) {
  124.  
  125.         if(str_eq(symbol, bp2 -> mst_name)) {
  126.             bp1 -> mst_next = bp2 -> mst_next;
  127.             mg_free( (char *) bp2);
  128.             bp2 = bp1 -> mst_next;
  129.         }
  130.         else {
  131.             bp1 = bp2;
  132.             bp2 = bp2 -> mst_next;
  133.         }
  134.     }
  135.     TICKX("mst_delete");
  136. }
  137.  
  138. /*
  139.     Place a macro in the symbol table along with the number of arguments
  140.     to the macro and a pointer to the macro's replacement text.
  141.  
  142.     Multiple entries for a symbol can exist in which case the last entry
  143.     defined is active.
  144.     Return a pointer to the allocated node or NULL.
  145.  
  146.     This code conforms to the new standard.  It rejects duplicate 
  147.     definitions of a macro unless the new definition is exactly the
  148.     same as the old.  
  149.  
  150.     This code also checks the "initial undef list" to see if the first
  151.     definition of a macro should be ignored.  If the macro name is
  152.     found on the list, it is removed from the list and no entry is made
  153.     in the macro symbol table.
  154. */
  155. struct mst_node *
  156. mst_enter(register char * symbol, register char * txt, register int nargs)
  157. {
  158.     register struct mst_node **bp0, *bp1;
  159.     int hash;
  160.     struct mst_node * bp;
  161.     struct u_node *up1, *up2;
  162.     char msg [100];
  163.     extern struct u_node undef_list;
  164.  
  165.     /*
  166.         Search the global "initial undef list" (created by command line
  167.         -u arguments) to see if the initial definition of name should
  168.         be rejected.  If the name appears on the list, remove it from 
  169.         the list and do not enter the name in the macro table.
  170.     */
  171.  
  172.     TRACEPB("mst_enter", printf("(%s, %s, %d)\n", symbol, txt, nargs));
  173.  
  174.     if (undef_list . u_next != NULL) {
  175.         up1 = &undef_list;
  176.         up2 = up1 -> u_next;
  177.  
  178.         while (up2 != NULL) {
  179.             if (str_eq(symbol, up2 -> u_name)) {
  180.                 up1 -> u_next = up2 -> u_next;
  181.                 RETURN_PTR("mst_enter", NULL);
  182.             }
  183.             else {
  184.                 up1 = up2;
  185.                 up2 = up2 -> u_next;
  186.             }
  187.         }
  188.     }
  189.  
  190.     /* Search down the list of mst_nodes. */
  191.     hash = mst_hash(symbol);
  192.     for (bp = mst_ht [hash]; bp; bp = bp -> mst_next) {
  193.  
  194.         /* Reject redefinitions of a macro unless identical. */
  195.         if (str_eq (symbol, bp -> mst_name)) {
  196.             if (nargs == bp -> mst_nargs) {
  197.                 if (str_eq(txt, bp -> mst_text)) {
  198.  
  199.                     /* Benign redefinition. */
  200.                     strcpy(msg, "(Warning) ");
  201.                     strcat(msg, "Duplicate definition of ");
  202.                     strcat(msg, symbol);
  203.                     strcat(msg, ".");
  204.                     t_error(msg);
  205.                     RETURN_PTR("mst_enter", bp);
  206.                 }
  207.             }
  208.             strcpy(msg, "Non-identical redefinition of ");
  209.             strcat(msg, symbol);
  210.             strcat(msg, " ignored.");
  211.             t_error(msg);
  212.             RETURN_PTR("mst_enter", NULL);
  213.         }
  214.     }
  215.  
  216.     /* Dynamically allocate space for node. */
  217.     bp1 = CAST(struct mst_node *) mg_alloc(sizeof(struct mst_node));
  218.     
  219.     /* Hang node from hash table. */
  220.     bp0  = &mst_ht[0];
  221.     bp0 += mst_hash(symbol);
  222.  
  223.     bp1 -> mst_next = *bp0;
  224.     *bp0            = bp1;
  225.  
  226.     /* Fill in the name and text fields. */
  227.     bp1 -> mst_name  = str_galloc(symbol);
  228.     bp1 -> mst_text  = str_galloc(txt);
  229.     bp1 -> mst_nargs = nargs;
  230.  
  231.     RETURN_PTR("mst_enter", bp1);
  232. }
  233.  
  234. /*
  235.     Return the hash value for symbol.
  236. */
  237. static int
  238. mst_hash (register unsigned char * symbol)
  239. {
  240.     register int hash;
  241.  
  242.     SL_DISABLE();
  243.  
  244.     for (hash = 0; *symbol; ) {
  245.         hash *= 3;
  246.         hash += (int) *symbol++;
  247.         hash %= MAC_PRIME;
  248.     }
  249.     return hash;
  250. }
  251.  
  252. /*
  253.     Initialize the macro module.
  254. */
  255. void
  256. mst_init(void)
  257. {
  258.     register int i;
  259.     register struct mst_node ** bp0;
  260.  
  261.     TICK("mst_init");
  262.  
  263.     /* Clear the hash table. */
  264.     for (i = 0, bp0 = &mst_ht[0]; i < MAC_PRIME; i++) {
  265.         *bp0++ = NULL;
  266.     }
  267.  
  268.     /* Clear the "initial undef list." */
  269.     undef_list . u_next = NULL;
  270. }
  271.  
  272. /*
  273.     Enter the predefined macros into the table.
  274.     Do nothing if the initial definitions have been
  275.     suppressed with -u options.
  276. */
  277. void
  278. mst2_init(void)
  279. {
  280.     struct mst_node * bp;
  281.     struct mst_node * mst_enter();
  282.  
  283.     /*
  284.         Define the __line__ macro and allocate enough space for
  285.         all line numbers.
  286.     */
  287.  
  288.     TICKB("mst2_init");
  289.  
  290.     bp = mst_enter("__line__", "", -3);
  291.     if (bp != NULL) {
  292.         bp -> mst_text = mg_alloc(10);
  293.     }
  294.  
  295.     /*
  296.         Define the __file__ macro and allocate enough space
  297.         for the largest possible file name.
  298.     */
  299.     bp = mst_enter("__file__", "", -3);
  300.     if (bp != NULL) {
  301.         bp -> mst_text = mg_alloc(MAX_FILE_NAME);
  302.     }
  303.  
  304.     TICKX("mst2_init");
  305. }
  306.  
  307. /*
  308.     Look up a symbol in the macro table.
  309.     Return a pointer to the node or NULL.
  310. */
  311. struct mst_node *
  312. mst_lookup (register char * symbol)
  313. {
  314.     register struct mst_node ** bp0, *bp1;
  315.     char buffer [100];
  316.  
  317.     /* Calculate the hash value of the symbol. */
  318.  
  319.     TRACEPB("mst_lookup", printf("(%s)\n", symbol));
  320.  
  321.     bp0  = &mst_ht[0];
  322.     bp0 += mst_hash(symbol);
  323.  
  324.     /* Search down the list of mst_nodes. */
  325.     for (bp1 = *bp0; bp1; bp1 = bp1 -> mst_next) {
  326.  
  327.         if (str_eq(symbol, bp1 -> mst_name)) {
  328.  
  329.             /* Special case for __line__ and __file__. */
  330.             if (bp1 -> mst_nargs == -3) {
  331.                 if (str_eq(bp1 -> mst_name, "__line__")) {
  332.                     /* Set current line number. */
  333.                     conv2s(t_line, buffer);
  334.                     str_cpy(bp1 -> mst_text, buffer);
  335.                 }
  336.                 if (str_eq(bp1 -> mst_name, "__file__")) {
  337.                     /* Set current file name. */
  338.                     str_cpy(bp1 -> mst_text, t_file);
  339.                 }
  340.             }
  341.  
  342.             /* Return success. */
  343.  
  344.             RETURN_PTR("mst_lookup", bp1);
  345.         }
  346.     }
  347.  
  348.     /* Return failure. */
  349.  
  350.     RETURN_PTR("mst_lookup", NULL);
  351. }
  352.