home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 355_02 / slk2.exe / SPP / MST.C < prev    next >
C/C++ Source or Header  |  1991-06-09  |  8KB  |  323 lines

  1. /*
  2.     New Sherlock Preprocessor -- macro symbol table routines.
  3.  
  4.     source:  mst.c
  5.     started: September 22, 1985
  6.     version:
  7.         July 15, 1988
  8.         February 17, 1989 delete period from error message.
  9.  
  10.  
  11.     PUBLIC DOMAIN SOFTWARE
  12.  
  13.     Sherlock, including the SPP, SDEL and SDIF programs, was placed in
  14.     the public domain on June 15, 1991, by its author,
  15.  
  16.         Edward K. Ream
  17.         166 North Prospect Ave.
  18.         Madison, WI 53705.
  19.         (608) 257-0802
  20.  
  21.     Sherlock may be used for any commercial or non-commercial purpose.
  22.  
  23.  
  24.     DISCLAIMER OF WARRANTIES
  25.  
  26.     Edward K. Ream (Ream) specifically disclaims all warranties,
  27.     expressed or implied, with respect to this computer software,
  28.     including but not limited to implied warranties of merchantability
  29.     and fitness for a particular purpose.  In no event shall Ream be
  30.     liable for any loss of profit or any commercial damage, including
  31.     but not limited to special, incidental consequential or other damages.
  32. */
  33.  
  34. #include "spp.h"
  35.  
  36. /* Declare local routines. */
  37. static int mst_hash    (unsigned char *);
  38.  
  39. /* Define the hash table used to access macro table nodes. */
  40.  
  41. #define MAC_PRIME 101
  42. typedef struct mst_node mactab;
  43. static struct mst_node {
  44.     mactab * mst_next;     /* Pointer to next bucket.    */
  45.     int     mst_nargs;    /* Number of args in text.    */
  46.     char *     mst_name;        /* Pointer to name.        */
  47.     char *     mst_text;        /* Pointer to replacement text. */
  48. };
  49. static mactab mst_ht [MAC_PRIME];
  50.  
  51. /*
  52.     Define the "initial undef list" for
  53.     arguments undefined on the command line.
  54. */
  55. typedef struct u_node unode;
  56. static struct u_node {
  57.     unode *    u_next;
  58.     char *        u_name;
  59. };
  60. unode undef_list;    /* list header. */
  61.  
  62. /*
  63.     Remove ALL instances of a symbol from the symbol table.
  64.     This ensures that an #undef will expose any non-macro version
  65.     of a routine.
  66. */
  67. void
  68. mst_delete (symbol)
  69. register char * symbol;
  70. {
  71.     register mactab *bp1, *bp2;
  72.     int hash;
  73.  
  74.     TRACEP("mst_delete",printf("entry: symbol=<%s>\n", symbol));
  75.     
  76.     hash = mst_hash(symbol);
  77.     bp1 = & mst_ht [hash];
  78.     bp2 = bp1 -> mst_next;
  79.  
  80.     while(bp2 != NULL) {
  81.  
  82.         if(str_eq(symbol, bp2 -> mst_name)) {
  83.  
  84.             TRACEP("mst_delete", printf("deletes\n"));
  85.             bp1 -> mst_next = bp2 -> mst_next;
  86.             m_free(bp2);
  87.             bp2 = bp1 -> mst_next;
  88.         }
  89.         else {
  90.             bp1 = bp2;
  91.             bp2 = bp2 -> mst_next;
  92.         }
  93.     }
  94. }
  95.  
  96. /*
  97.     Place a macro in the symbol table along with the number of arguments
  98.     to the macro and a pointer to the macro's replacement text.
  99.  
  100.     Multiple entries for a symbol can exist in which case the last entry
  101.     defined is active.
  102.  
  103.     This code conforms to the new standard.  It rejects duplicate 
  104.     definitions of a macro unless the new definition is exactly the
  105.     same as the old.  
  106.  
  107.     This code also checks the "initial undef list" to see if the first
  108.     definition of a macro should be ignored.  If the macro name is
  109.     found on the list, it is removed from the list and no entry is made
  110.     in the macro symbol table.
  111. */
  112. void
  113. mst_enter (symbol, txt, nargs)
  114. register char *symbol;
  115. register char *txt;
  116. register int nargs;
  117. {
  118.     register mactab *bp, *bp2;
  119.     int hash;
  120.     unode *up1, *up2;
  121.  
  122.     TRACEP("mst_enter", printf("(%s, <%s>, %d)\n",
  123.         symbol, pr_str(txt), nargs));
  124.  
  125.     /*
  126.         Search the global "initial undef list" (created by command line
  127.         -u arguments) to see if the initial definition of name should
  128.         be rejected.  If the name appears on the list, remove it from
  129.         the list and do not enter the name in the macro table.
  130.     */
  131.  
  132.     if (undef_list . u_next != NULL) {
  133.         up1 = &undef_list;
  134.         up2 = up1 -> u_next;
  135.  
  136.         while (up2 != NULL) {
  137.             if (str_eq(symbol, up2 -> u_name)) {
  138.                 /* Remove the entry from the list. */
  139.                 up1 -> u_next = up2 -> u_next;
  140.                 return;
  141.             }
  142.             else {
  143.                 up1 = up2;
  144.                 up2 = up2 -> u_next;
  145.             }
  146.         }
  147.     }
  148.  
  149.     /* Search down the list of mst_nodes. */
  150.     hash = mst_hash(symbol);
  151.     bp   = & mst_ht [hash];
  152.     for (bp = bp -> mst_next; bp; bp = bp -> mst_next) {
  153.  
  154.         /* Reject redefinitions of a macro unless identical. */
  155.         if (str_eq (symbol, bp -> mst_name)) {
  156.             if (nargs == bp -> mst_nargs) {
  157.                 if (str_eq(txt, bp -> mst_text)) {
  158.                     return;
  159.                 }
  160.             }
  161.             err3(    "Non-identical redefinition of ", symbol,
  162.                 " ignored");
  163.             return;
  164.         }
  165.     }
  166.  
  167.     /* Dynamically allocate space for node. */
  168.     bp2 = m_alloc(sizeof(mactab));
  169.     
  170.     /* Hang node from hash table. */
  171.     bp = & mst_ht [hash];
  172.     bp2 -> mst_next = bp -> mst_next;
  173.     bp  -> mst_next = bp2;
  174.  
  175.     /* Fill in the name and text fields. */
  176.     bp2 -> mst_name  = str_alloc(symbol);
  177.     bp2 -> mst_text  = str_alloc(txt);
  178.     bp2 -> mst_nargs = nargs;
  179. }
  180.  
  181. /*
  182.     Return the hash value for symbol.
  183. */
  184. static int
  185. mst_hash (symbol)
  186. register unsigned char * symbol;
  187. {
  188.     register int hash;
  189.  
  190.     STAT("mst_hash");
  191.  
  192.     for (hash = 0; *symbol; ) {
  193.         hash *= 3;
  194.         hash += (int) *symbol++;
  195.         hash %= MAC_PRIME;
  196.     }
  197.     return hash;
  198. }
  199.  
  200. /*
  201.     Initialize the macro module.
  202.     This must be done BEFORE command line arguments are processed.
  203. */
  204. void
  205. mst_init()
  206. {
  207.     register int i;
  208.  
  209.     TICK("mst_init");
  210.  
  211.     /* Clear the hash table. */
  212.     for (i = 0; i < MAC_PRIME; i++) {
  213.         mst_ht [i] . mst_next = NULL;
  214.         mst_ht [i] . mst_name = "<NAME>";
  215.         mst_ht [i] . mst_text = "<TEXT>";
  216.         mst_ht [i] . mst_nargs = 0;
  217.     }
  218.  
  219.     /* Clear the "initial undef list." */
  220.     undef_list . u_next = NULL;
  221. }
  222.  
  223. /*
  224.     Enter the predefined macros into the table.
  225.     Do nothing if the initial definitions have been
  226.     suppressed with -u options.
  227.  
  228.     This must be done AFTER command line options have been processed.
  229. */
  230. void
  231. mst2_init()
  232. {
  233.     mst_enter("__LINE__", "", -3);
  234.     mst_enter("__FILE__", "", -3);
  235.     mst_enter("__STDC__", "", -3);
  236.     mst_enter("__TIME__", "", -3);
  237.     mst_enter("__DATE__", "", -3);
  238. }
  239.  
  240. /*
  241.     Look up a symbol in the macro table.
  242.     Return TRUE if found, and set text and nargs.
  243. */
  244. bool
  245. mst_lookup(symbol, text, nargs)
  246. register char * symbol;
  247. char ** text;
  248. int *nargs;
  249. {
  250.     register mactab *bp;
  251.     char buffer [100];
  252.     int hash;
  253.  
  254.     TRACEP("mst_lookup", printf("(%s)\n", symbol));
  255.  
  256.     /* Calculate the hash value of the symbol. */
  257.     hash = mst_hash(symbol);
  258.     bp = & mst_ht [hash];
  259.  
  260.     /* Search down the list of mst_nodes. */
  261.     for (bp = bp -> mst_next; bp; bp = bp -> mst_next) {
  262.  
  263.         if (str_eq(symbol, bp -> mst_name)) {
  264.  
  265.             /* Special case for __line__ and __file__. */
  266.             if (bp -> mst_nargs == -3) {
  267.                 if (str_eq(bp -> mst_name, "__LINE__")) {
  268.                     /* Set current line number. */
  269.                     conv2s(t_line, buffer);
  270.                     bp -> mst_text = str_alloc(buffer);
  271.                 }
  272.                 else if (str_eq(bp -> mst_name, "__FILE__")) {
  273.  
  274.                     /* Set current file name. */
  275.                     strcpy(buffer, "\"");
  276.                     strcat(buffer, t_file);
  277.                     strcat(buffer, "\"");
  278.                     bp -> mst_text = str_alloc(buffer);
  279.                 }
  280.                 else if (str_eq(bp -> mst_name, "__TIME__")) {
  281.                     /* Set current file name. */
  282.                     bp -> mst_text = systime();
  283.                 }
  284.                 else if (str_eq(bp -> mst_name, "__DATE__")) {
  285.                     bp -> mst_text = sysdate();
  286.                 }
  287.                 else if (str_eq(bp -> mst_name, "__STDC__")) {
  288.                     bp -> mst_text = "1";
  289.                 }
  290.             }
  291.  
  292.             /* Return success. */
  293.             *nargs = max(-1, bp -> mst_nargs);
  294.             *text  = bp -> mst_text;
  295.  
  296.             TRACEP("mst_lookup", printf("found:\n"));
  297.             return TRUE;
  298.         }
  299.     }
  300.  
  301.     TRACEP("mst_lookup", printf("not found\n"));
  302.  
  303.     /* Return failure. */
  304.     return FALSE;
  305. }
  306.  
  307. /*
  308.     Add an argument to the "initial undef list."
  309. */
  310. void
  311. mst_unarg(arg)
  312. char * arg;
  313. {
  314.     unode * p;
  315.  
  316.     TICK("mst_unarg");
  317.  
  318.     p = m_alloc(sizeof(unode));
  319.     p -> u_name        = arg;
  320.     p -> u_next        = undef_list . u_next;
  321.     undef_list . u_next    = p;
  322. }
  323.