home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / lout2.lzh / LOUT2 / z29.c < prev    next >
Text File  |  1994-01-23  |  24KB  |  591 lines

  1. /*@z29.c:Symbol Table:Declarations, hash()@***********************************/
  2. /*                                                                           */
  3. /*  LOUT: A HIGH-LEVEL LANGUAGE FOR DOCUMENT FORMATTING (VERSION 2.05)       */
  4. /*  COPYRIGHT (C) 1993 Jeffrey H. Kingston                                   */
  5. /*                                                                           */
  6. /*  Jeffrey H. Kingston (jeff@cs.su.oz.au)                                   */
  7. /*  Basser Department of Computer Science                                    */
  8. /*  The University of Sydney 2006                                            */
  9. /*  AUSTRALIA                                                                */
  10. /*                                                                           */
  11. /*  This program is free software; you can redistribute it and/or modify     */
  12. /*  it under the terms of the GNU General Public License as published by     */
  13. /*  the Free Software Foundation; either version 1, or (at your option)      */
  14. /*  any later version.                                                       */
  15. /*                                                                           */
  16. /*  This program is distributed in the hope that it will be useful,          */
  17. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  18. /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  19. /*  GNU General Public License for more details.                             */
  20. /*                                                                           */
  21. /*  You should have received a copy of the GNU General Public License        */
  22. /*  along with this program; if not, write to the Free Software              */
  23. /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
  24. /*                                                                           */
  25. /*  FILE:         z29.c                                                      */
  26. /*  MODULE:       Symbol Table                                               */
  27. /*  EXTERNS:      InitSym(), PushScope(), PopScope(), SuppressVisible(),     */
  28. /*                UnSuppressVisible(), SuppressScope(), UnSuppressScope(),   */
  29. /*                SwitchScope(), UnSwitchScope(), BodyParAllowed(),          */
  30. /*                BodyParNotAllowed(), InsertSym(), SearchSym(),             */
  31. /*                SymName(), FullSymName(), ChildSym(), CheckSymSpread(),    */
  32. /*                DeleteEverySym()                                           */
  33. /*                                                                           */
  34. /*****************************************************************************/
  35. #include "externs"
  36.  
  37. #define    MAX_STACK     40        /* size of scope stack               */
  38. #define    MAX_TAB        1024        /* size of hash table                */
  39. #define    TAB_MASK    0x3FF        /* i & TAB_MASK == i % MAX_TAB       */
  40.  
  41. #define    length(x)    word_font(x)
  42.  
  43. static    OBJECT        scope[MAX_STACK];        /* the scope stack   */
  44. static    BOOLEAN        npars_only[MAX_STACK];        /* look for NPAR exc */
  45. static    BOOLEAN        vis_only[MAX_STACK];        /* look for visibles */
  46. static    BOOLEAN        body_ok[MAX_STACK];        /* look for body par */
  47. static    BOOLEAN        suppress_scope;            /* suppress scoping  */
  48. static    BOOLEAN        suppress_visible;        /* suppress visible  */
  49. static    int        scope_top;            /* scope stack top   */
  50. static    struct { OBJECT f1, f2; } symtab[MAX_TAB];    /* the hash table    */
  51. #if DEBUG_ON
  52. static    int        sym_spread[MAX_TAB] = { 0 };    /* hash table spread */
  53. static    int        sym_count = 0;            /* symbol count      */
  54. #endif
  55.  
  56.  
  57. /*****************************************************************************/
  58. /*                                                                           */
  59. /*  #define hash(str, len, val)                                              */
  60. /*                                                                           */
  61. /*  Set val to the hash value of string str, which has length len.           */
  62. /*  The hash function is just the character sum mod MAX_TAB.                 */
  63. /*  This definition assumes that working variables rlen and x exist.         */
  64. /*                                                                           */
  65. /*****************************************************************************/
  66.  
  67. #define hash(str, len, val)                        \
  68. { rlen = len;                                \
  69.   x    = str;                                \
  70.   val  = *x++;                                \
  71.   while( --rlen )  val += *x++;                        \
  72.   val  &= TAB_MASK;                            \
  73. }
  74.  
  75.  
  76. /*@::InitSym(), PushScope(), PopScope(), SuppressVisible(), etc.@*************/
  77. /*                                                                           */
  78. /*  InitSym()                                                                */
  79. /*                                                                           */
  80. /*  Initialize the symbol table to empty.                                    */
  81. /*                                                                           */
  82. /*****************************************************************************/
  83.  
  84. InitSym()
  85. { int i;
  86.   scope_top = 0;
  87.   suppress_scope = FALSE;
  88.   suppress_visible = FALSE;
  89.   for( i = 0;  i < MAX_TAB;  i++ )
  90.     symtab[i].f1 = symtab[i].f2 = (OBJECT) &symtab[i];
  91. } /* end InitSym */
  92.  
  93.  
  94. /*****************************************************************************/
  95. /*                                                                           */
  96. /*  PushScope(x, npars, vis)                                                 */
  97. /*  PopScope()                                                               */
  98. /*                                                                           */
  99. /*  Add or remove an OBJECT x (which must be in the symbol table) to or from */
  100. /*  the scope stack.  If npars is TRUE, only the named parameters of x are   */
  101. /*  added to scope.  If vis is TRUE, only visible locals and parameters are  */
  102. /*  added.                                                                   */
  103. /*                                                                           */
  104. /*****************************************************************************/
  105.  
  106. PushScope(x, npars, vis)
  107. OBJECT x;  BOOLEAN npars, vis;
  108. { debug2(DST, DD, "[ PushScope( %s, %s )", SymName(x), bool(npars));
  109.   assert( suppress_scope == FALSE, "PushScope: suppress_scope!" );
  110.   if( scope_top >= MAX_STACK )
  111.   { int i;
  112.     for( i = 0; i < scope_top; i++ )
  113.       debug2(DST, D, "  scope[%2d] = %s", i, SymName(scope[i]));
  114.     Error(INTERN, &fpos(x), "scope depth limit exceeded");
  115.   }
  116.   scope[scope_top]      = x;
  117.   npars_only[scope_top] = npars;
  118.   vis_only[scope_top]   = vis;
  119.   body_ok[scope_top]    = FALSE;
  120.   scope_top++;
  121. } /* end PushScope */
  122.  
  123. PopScope()
  124. { debug0(DST, DD, "] PopScope()");
  125.   assert( scope_top > 0, "tried to pop empty scope stack");
  126.   assert( suppress_scope == FALSE, "PopScope: suppress_scope!" );
  127.   scope_top--;
  128. } /* end PopScope */
  129.  
  130.  
  131. /*****************************************************************************/
  132. /*                                                                           */
  133. /*  SuppressVisible()                                                        */
  134. /*  UnSuppressVisible()                                                      */
  135. /*                                                                           */
  136. /*  Suppress all scopes (so that all calls to SearchSym fail); and undo it.  */
  137. /*                                                                           */
  138. /*****************************************************************************/
  139.  
  140. SuppressVisible()
  141. { debug0(DST, DD, "[ SuppressVisible()");
  142.   suppress_visible = TRUE;
  143. } /* end SuppressVisible */
  144.  
  145. UnSuppressVisible()
  146. { debug0(DST, DD, "] UnSuppressVisible()");
  147.   suppress_visible = FALSE;
  148. } /* end UnSuppressVisible */
  149.  
  150.  
  151. /*@::SuppressScope(), UnSuppressScope(), SwitchScope(), UnswitchScope()@******/
  152. /*                                                                           */
  153. /*  SuppressScope()                                                          */
  154. /*  UnSuppressScope()                                                        */
  155. /*                                                                           */
  156. /*  Suppress all scopes (so that all calls to SearchSym fail); and undo it.  */
  157. /*                                                                           */
  158. /*****************************************************************************/
  159.  
  160.  
  161. SuppressScope()
  162. { debug0(DST, DD, "[ SuppressScope()");
  163.   suppress_scope = TRUE;
  164. } /* end SuppressScope */
  165.  
  166. UnSuppressScope()
  167. { debug0(DST, DD, "] UnSuppressScope()");
  168.   suppress_scope = FALSE;
  169. } /* end UnSuppressScope */
  170.  
  171.  
  172. /*****************************************************************************/
  173. /*                                                                           */
  174. /*  SwitchScope(sym)                                                         */
  175. /*  UnSwitchScope(sym)                                                       */
  176. /*                                                                           */
  177. /*  Switch to the scope of sym (if nil, StartSym); and switch back again.    */
  178. /*                                                                           */
  179. /*****************************************************************************/
  180.  
  181. SwitchScope(sym)
  182. OBJECT sym;
  183. { int i;
  184.   OBJECT new_scopes[MAX_STACK];
  185.   if( sym == nil )  PushScope(StartSym, FALSE, FALSE);
  186.   else
  187.   { i = 0;
  188.     while( sym != StartSym )
  189.     { new_scopes[i++] = enclosing(sym);
  190.       sym = enclosing(sym);
  191.     }
  192.     while( i > 0 )  PushScope(new_scopes[--i], FALSE, FALSE);
  193.   }
  194. }
  195.  
  196. UnSwitchScope(sym)
  197. OBJECT sym;
  198. { if( sym == nil )  PopScope();
  199.   else
  200.   { while( sym != StartSym )
  201.     { PopScope();
  202.       sym = enclosing(sym);
  203.     }
  204.   }
  205. }
  206.  
  207.  
  208. /*****************************************************************************/
  209. /*                                                                           */
  210. /*  BodyParAllowed()                                                         */
  211. /*  BodyParNotAllowed()                                                      */
  212. /*                                                                           */
  213. /*  Allow or disallow invokations of the body parameter of the current tos.  */
  214. /*                                                                           */
  215. /*****************************************************************************/
  216.  
  217. BodyParAllowed()
  218. { debug0(DST, DD, "BodyParAllowed()");
  219.   body_ok[scope_top-1] = TRUE;
  220. } /* end BodyParAllowed */
  221.  
  222. BodyParNotAllowed()
  223. { debug0(DST, DD, "BodyParNotAllowed()");
  224.   body_ok[scope_top-1] = FALSE;
  225. } /* end BodyParNotAllowed */
  226.  
  227.  
  228. /*@::InsertSym()@*************************************************************/
  229. /*                                                                           */
  230. /*  OBJECT InsertSym(str, xtype, xfpos, xprecedence, indefinite, xrecursive, */
  231. /*                                         xpredefined, xenclosing, xbody)   */
  232. /*                                                                           */
  233. /*  Insert a new symbol into the table.  Its string value is str.            */
  234. /*  Initialise the symbol as the parameters indicate.                        */
  235. /*  Return a pointer to the new symbol.                                      */
  236. /*  If str is not a valid symbol name, InsertSym prints an error             */
  237. /*  message and does not insert the symbol.                                  */
  238. /*                                                                           */
  239. /*****************************************************************************/
  240.  
  241. OBJECT InsertSym(str, xtype, xfpos, xprecedence, xindefinite, xrecursive,
  242.                          xpredefined, xenclosing, xbody)
  243. FULL_CHAR *str;  unsigned char xtype;
  244. FILE_POS *xfpos; unsigned char xprecedence;
  245. BOOLEAN xindefinite, xrecursive;  unsigned xpredefined;
  246. OBJECT xenclosing, xbody;
  247. { register int sum, rlen;
  248.   register unsigned char *x;
  249.   OBJECT p, q, s, link, entry, plink;  int len;
  250.  
  251.   debug3(DST, DD, "InsertSym( %s, %s, in %s )",
  252.     Image(xtype), str, SymName(xenclosing));
  253.   if( !LexLegalName(str) ) Error(WARN, xfpos, "invalid symbol name %s", str);
  254.  
  255.   s = New(xtype);
  256.   FposCopy(fpos(s), *xfpos);
  257.   has_body(s)    = FALSE;
  258.   right_assoc(s) = TRUE;
  259.   precedence(s)  = xprecedence;
  260.   indefinite(s)  = xindefinite;
  261.   recursive(s)   = xrecursive;
  262.   predefined(s)  = xpredefined;
  263.   enclosing(s)   = xenclosing;
  264.   sym_body(s)    = xbody;
  265.   base_uses(s)   = nil;
  266.   uses(s)        = nil;
  267.   marker(s)      = nil;
  268.   cross_sym(s)   = nil;
  269.   is_extern_target(s) = FALSE;
  270.   uses_extern_target(s) = FALSE;
  271.   visible(s)     = FALSE;
  272.   uses_galley(s) = FALSE;
  273.  
  274.   uses_count(s)  = 0;
  275.   dirty(s)       = FALSE;
  276.   if( enclosing(s) != nil && type(enclosing(s)) == NPAR )
  277.     dirty(enclosing(s)) = TRUE;
  278.  
  279.   has_par(s)     = FALSE;
  280.   has_lpar(s)    = FALSE;
  281.   has_rpar(s)    = FALSE;
  282.   if( is_par(type(s)) )  has_par(enclosing(s))  = TRUE;
  283.   if( type(s) == LPAR )  has_lpar(enclosing(s)) = TRUE;
  284.   if( type(s) == RPAR )  has_rpar(enclosing(s)) = TRUE;
  285.  
  286.   has_target(s)  = FALSE;
  287.   force_target(s) = FALSE;
  288.   if( !StringEqual(str, KW_TARGET) ) is_target(s) = FALSE;
  289.   else
  290.   { is_target(s) = has_target(enclosing(s)) = TRUE;
  291.     if( has_key(enclosing(s)) && xbody != nil && type(xbody) == CROSS )
  292.     { if( LastDown(xbody) != Down(xbody) )
  293.       { OBJECT sym;
  294.     Child(sym, Down(xbody));
  295.     if( type(sym) == CLOSURE )
  296.     { is_extern_target(actual(sym)) = TRUE;
  297.       uses_extern_target(actual(sym)) = TRUE;
  298.     }
  299.       }
  300.     }
  301.   }
  302.  
  303.   has_tag(s)  = FALSE;
  304.   if( !StringEqual(str, KW_TAG) ) is_tag(s) = FALSE;
  305.   else is_tag(s) = has_tag(enclosing(s)) = dirty(enclosing(s)) = TRUE;
  306.  
  307.   has_key(s)  = FALSE;
  308.   if( !StringEqual(str, KW_KEY) ) is_key(s) = FALSE;
  309.   else is_key(s) = has_key(enclosing(s)) = TRUE;
  310.  
  311.   if( type(s) == RPAR && has_body(enclosing(s)) && (is_tag(s) || is_key(s)) )
  312.     Error(WARN, &fpos(s), "a body parameter may not be named %s", str);
  313.  
  314.   if( type(s) == RPAR && has_target(enclosing(s)) && (is_tag(s) || is_key(s)) )
  315.     Error(WARN,&fpos(s), "the right parameter of a galley may not be %s", str);
  316.  
  317.   len = StringLength(str);
  318.   hash(str, len, sum);
  319.  
  320.   ifdebug(DST, D, sym_spread[sum]++;  sym_count++);
  321.   entry = (OBJECT) &symtab[sum];
  322.   for( plink = Down(entry);  plink != entry;  plink = NextDown(plink) )
  323.   { Child(p, plink);
  324.     if( length(p) == len && StringEqual(str, string(p)) )
  325.     { for( link = Down(p);  link != p;  link = NextDown(link) )
  326.       {    Child(q, link);
  327.     if( enclosing(s) == enclosing(q) )
  328.     { Error(WARN, &fpos(s), "symbol %s previously defined at%s",
  329.         str, EchoFilePos(&fpos(q)) );
  330.       break;
  331.     }
  332.       }
  333.       goto wrapup;
  334.     }
  335.   }
  336.  
  337.   /* need a new OBJECT as well as s */
  338.   p = NewWord(WORD, len, xfpos);
  339.   length(p) = len;
  340.   StringCopy(string(p), str);
  341.   Link(entry, p);
  342.  
  343.  wrapup:
  344.   Link(p, s);
  345.   if( enclosing(s) != nil ) Link(enclosing(s), s);
  346.   debug2(DST, DD, "InsertSym Link(%s, %s) and returning.",
  347.         SymName(enclosing(s)), SymName(s));
  348.   return s;
  349. } /* end InsertSym */
  350.  
  351.  
  352. /*@::SearchSym(), SymName()@**************************************************/
  353. /*                                                                           */
  354. /*  OBJECT SearchSym(str, len)                                               */
  355. /*                                                                           */
  356. /*  Search the symbol table for str, with length len, and return an          */
  357. /*  OBJECT referencing the entry if found.  Otherwise return nil.            */
  358. /*                                                                           */
  359. /*****************************************************************************/
  360.  
  361. OBJECT SearchSym(str, len)
  362. FULL_CHAR *str;  int len;
  363. { register int rlen, sum;
  364.   register FULL_CHAR *x, *y;
  365.   OBJECT p, q, link, plink, entry;
  366.   int s;
  367.  
  368.   debug2(DST, DDD, "SearchSym( %c..., %d )", str[0], len);
  369.  
  370.   hash(str, len, sum);
  371.   rlen = len;
  372.   entry = (OBJECT) &symtab[sum];
  373.   for( plink = Down(entry);  plink != entry;  plink = NextDown(plink) )
  374.   { Child(p, plink);
  375.     if( rlen == length(p) )
  376.     { x = str;  y = string(p);
  377.       do; while( *x++ == *y++ && --rlen );
  378.       if( rlen == 0 )
  379.       {    s = scope_top;
  380.     do
  381.     { s--;
  382.       for( link = Down(p);  link != p;  link = NextDown(link) )
  383.       { Child(q, link);
  384.         if( enclosing(q) == scope[s]
  385.           && (!npars_only[s] || type(q) == NPAR)
  386.           && (!vis_only[s] || visible(q) || suppress_visible )
  387.           && (body_ok[s] || type(q)!=RPAR || !has_body(enclosing(q)) )
  388.           && !suppress_scope )
  389.         {    debug1(DST, DDD, "SearchSym returning %s", Image(type(q)));
  390.         return q;
  391.         }
  392.       }
  393.     } while( scope[s] != StartSym );
  394.       }
  395.     }
  396.     rlen = len;
  397.   }
  398.   debug0(DST, DDD, "SearchSym returning <nil>");
  399.   return nil;
  400. } /* end SearchSym */
  401.  
  402.  
  403. /*****************************************************************************/
  404. /*                                                                           */
  405. /*  FULL_CHAR *SymName(s)                                                    */
  406. /*                                                                           */
  407. /*  Return the string value of the name of symbol s.                         */
  408. /*                                                                           */
  409. /*****************************************************************************/
  410.  
  411. FULL_CHAR *SymName(s)
  412. OBJECT s;
  413. { OBJECT p;
  414.   if( s == nil )  return AsciiToFull("<nil>");
  415.   Parent(p, Up(s));
  416.   assert( is_word(type(p)), "SymName: !is_word(type(p))!" );
  417.   return string(p);
  418. } /* end SymName */
  419.     
  420.  
  421. /*@::FullSymName(), ChildSym()@***********************************************/
  422. /*                                                                           */
  423. /*  FULL_CHAR *FullSymName(x, str)                                           */
  424. /*                                                                           */
  425. /*  Return the path name of symbol x. with str separating each entry.        */
  426. /*                                                                           */
  427. /*****************************************************************************/
  428.  
  429. FULL_CHAR *FullSymName(x, str)
  430. OBJECT x;  FULL_CHAR *str;
  431. { OBJECT stack[20];  int i;
  432.   static FULL_CHAR buff[MAX_LINE], *sname;
  433.   if( x == nil )  return AsciiToFull("<nil>");
  434.   assert( enclosing(x) != nil, "FullSymName: enclosing(x) == nil!" );
  435.   for( i = 0;  enclosing(x) != nil && i < 20;  i++ )
  436.   { stack[i] = x;
  437.     x = enclosing(x);
  438.   }
  439.   StringCopy(buff, STR_EMPTY);
  440.   for( i--;  i > 0;  i-- )
  441.   { sname = SymName(stack[i]);
  442.     if( StringLength(sname)+StringLength(str)+StringLength(buff) >= MAX_LINE )
  443.       Error(FATAL, &fpos(x), "full name of symbol is too long");
  444.     StringCat(buff, sname);
  445.     StringCat(buff, str);
  446.   }
  447.   sname = SymName(stack[0]);
  448.   if( StringLength(sname) + StringLength(buff) >= MAX_LINE )
  449.     Error(FATAL, &fpos(x), "full name of symbol is too long");
  450.   StringCat(buff, sname);
  451.   return buff;
  452. } /* end FullSymName */
  453.  
  454.  
  455. /*****************************************************************************/
  456. /*                                                                           */
  457. /*  OBJECT ChildSym(s, typ)                                                  */
  458. /*                                                                           */
  459. /*  Find the child of symbol s of type typ, either LPAR or RPAR.             */
  460. /*                                                                           */
  461. /*****************************************************************************/
  462.  
  463. OBJECT ChildSym(s, typ)
  464. OBJECT s;  unsigned typ;
  465. { OBJECT link, y;
  466.   for( link = Down(s);  link != s;  link = NextDown(link) )
  467.   { Child(y, link);
  468.     if( type(y) == typ && enclosing(y) == s )  return y;
  469.   }
  470.   Error(INTERN, &fpos(s), "Symbol %s has missing %s", SymName(s), Image(typ));
  471.   return nil;
  472. } /* end ChildSym */
  473.  
  474.  
  475. /*@::CheckSymSpread(), DeleteSymBody()@***************************************/
  476. /*                                                                           */
  477. /*  CheckSymSpread()                                                         */
  478. /*                                                                           */
  479. /*  Check the spread of symbols through the hash table.                      */
  480. /*                                                                           */
  481. /*****************************************************************************/
  482. #if DEBUG_ON
  483.  
  484. CheckSymSpread()
  485. { int i, j, sum, usum;  OBJECT entry, plink;
  486.   debug2(DST, D, "Symbol table spread (table size = %d, symbols = %d):",
  487.     MAX_TAB, sym_count);
  488.   usum = sum = 0;
  489.   for( i = 0;  i < MAX_TAB;  i++ )
  490.   { fprintf(stderr, "%4d: ", i);
  491.     for( j = 1;  j <= sym_spread[i];  j++ )
  492.     { fprintf(stderr, ".");
  493.       sum += j;
  494.     }
  495.     entry = (OBJECT) &symtab[i];
  496.     for( plink=Down(entry), j=1;  plink != entry;  plink=NextDown(plink), j++ )
  497.     { fprintf(stderr, "+");
  498.       usum += j;
  499.     }
  500.     fprintf(stderr, "\n");
  501.   }
  502.   fprintf(stderr, "average length counting duplicate names = %.1f\n",
  503.     (float) sum / sym_count);
  504.   fprintf(stderr, "average length not counting duplicate names = %.1f\n",
  505.     (float) usum / sym_count);
  506. } /* end CheckSymSpread */
  507.  
  508.  
  509. /*****************************************************************************/
  510. /*                                                                           */
  511. /*  static DeleteSymBody(s)                                                  */
  512. /*                                                                           */
  513. /*  Delete the body of symbol s.                                             */
  514. /*                                                                           */
  515. /*****************************************************************************/
  516.  
  517. static DeleteSymBody(s)
  518. OBJECT s;
  519. { debug1(DST, DDD, "DeleteSymBody( %s )", SymName(s));
  520.   switch( type(s) )
  521.   {
  522.     case MACRO:    while( sym_body(s) != nil )
  523.           sym_body(s) = DeleteAndDispose(sym_body(s), PARENT);
  524.         break;
  525.     
  526.     case LPAR:
  527.     case NPAR:
  528.     case RPAR:
  529.     case LOCAL:    if( sym_body(s) != nil ) DisposeObject(sym_body(s));
  530.         break;
  531.  
  532.     default:    Error(INTERN,no_fpos, "unknown symbol type %s",Image(type(s)));
  533.         break;
  534.   }
  535.   debug0(DST, DDD, "DeleteSymBody returning.");
  536. } /* end DeleteSymBody */
  537.  
  538.  
  539. /*@::DeleteEverySym()@********************************************************/
  540. /*                                                                           */
  541. /*  DeleteEverySym()                                                         */
  542. /*                                                                           */
  543. /*  Delete every symbol in the symbol table.                                 */
  544. /*  Note that we first delete all bodies, then the symbols themselves.       */
  545. /*  This is so that the closures within the bodies have well-defined         */
  546. /*  actual() pointers, even while the symbol table is being disposed.        */
  547. /*  If this is not done, debug output during the disposal gets confused.     */
  548. /*                                                                           */
  549. /*****************************************************************************/
  550.  
  551. DeleteEverySym()
  552. { int i, j, load, cost;  OBJECT p, plink, link, x, entry;
  553.   debug0(DST, D, "DeleteEverySym()");
  554.  
  555.   /* dispose the bodies of all symbols */
  556.   for( i = 0;  i < MAX_TAB;  i++ )
  557.   { entry = (OBJECT) &symtab[i];
  558.     for( plink = Down(entry);  plink != entry;  plink = NextDown(plink) )
  559.     { Child(p, plink);
  560.       for( link = Down(p);  link != p;  link = NextDown(link) )
  561.       {    Child(x, link);  DeleteSymBody(x);
  562.     /* *** will not work now
  563.     while( base_uses(x) != nil )
  564.     { tmp = base_uses(x);  base_uses(x) = next(tmp);
  565.       PutMem(tmp, USES_SIZE);
  566.     }
  567.     while( uses(x) != nil )
  568.     { tmp = uses(x);  uses(x) = next(tmp);
  569.       PutMem(tmp, USES_SIZE);
  570.     }
  571.     *** */
  572.       }
  573.     }
  574.   }
  575.  
  576.   /* dispose the symbol name strings, gather statistics, and print them */
  577.   load = cost = 0;
  578.   for( i = 0;  i < MAX_TAB;  i++ )
  579.   { j = 1; entry = (OBJECT) &symtab[i];
  580.     while( Down(entry) != entry )
  581.     { load += 1;  cost += j;  j += 1;
  582.       DisposeChild(Down(entry));
  583.     }
  584.   }
  585.   if( load > 0 ) debug4(DST, D, "size = %d, items = %d (%d%%), probes = %.1f",
  586.     MAX_TAB, load, (100*load)/MAX_TAB, (float) cost/load);
  587.   else debug1(DST, D, "table size = %d, no entries in table", MAX_TAB);
  588.   debug0(DST, D, "DeleteEverySym returning.");
  589. } /* end DeleteEverySym */
  590. #endif
  591.