Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

symtable.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** symtable.c
00026 **
00027 ** Symbol table abstraction
00028 **
00029 **  AUTHORS:
00030 **
00031 **      Gary Feldman, Technical Languages and Environments, DECspec project
00032 **      Steve Garland,
00033 **         Massachusetts Institute of Technology
00034 **      Joe Wild, Technical Languages and Environments, DECspec project
00035 **      Yang Meng Tan,
00036 **         Massachusetts Institute of Technology
00037 **
00038 **  CREATION DATE:
00039 **
00040 **      20 January 1991
00041 */
00042 
00043 # include "lclintMacros.nf"
00044 # include "llbasic.h"
00045 # include "gram.h"
00046 # include "lclscan.h"
00047 # include "lclsyntable.h"
00048 # include "lslparse.h"
00049 
00050 /*@+ignorequals@*/
00051 
00052 static bool isBlankLine (char *p_line);
00053 static bool inImport = FALSE;
00054 
00055 /*@constant static int MAXBUFFLEN;@*/
00056 # define MAXBUFFLEN 512
00057 /*@constant static int DELTA;@*/
00058 # define DELTA 100
00059 
00060 static void symHashTable_dump (symHashTable * p_t, FILE * p_f, bool p_lco);
00061 
00062 static void tagInfo_free (/*@only@*/ tagInfo p_tag);
00063 static /*@observer@*/ scopeInfo symtable_scopeInfo (symtable p_stable);
00064 
00065 static void symtable_dumpId (symtable p_stable, FILE *p_f, bool p_lco);
00066 static lsymbol nameNode2key (nameNode p_n);
00067 
00068 typedef enum
00069 {
00070   SYMK_FCN, SYMK_SCOPE, SYMK_TYPE, SYMK_VAR
00071 } symKind;
00072 
00073 typedef struct
00074 {
00075   symKind kind;
00076   union
00077   {
00078     /*@only@*/ fctInfo fct;
00079     /*@only@*/ scopeInfo scope;
00080     /*@only@*/ typeInfo type;
00081     /*@only@*/ varInfo var;
00082   } info;
00083 } idTableEntry;
00084 
00085 typedef struct _idTable
00086 {
00087   unsigned int size;
00088   unsigned int allocated;
00089   /*@relnull@*/ idTableEntry *entries;
00090   bool exporting;
00091 } idTable;
00092 
00093 struct _symtableStruct
00094 {
00095   idTable *idTable;             /* data is idTableEntry */
00096   symHashTable *hTable;         /* data is htData */
00097   mapping *type2sort;           /* maps LCL type symbol to LSL sort */
00098 } ;
00099 
00100 static /*@observer@*/ ltoken idTableEntry_getId (idTableEntry *p_x);
00101 static /*@out@*/ /*@exposed@*/ idTableEntry *nextFree (idTable * p_st);
00102 static /*@dependent@*/ /*@null@*/ idTableEntry *symtable_lookup (idTable * p_st, lsymbol p_id);
00103 static /*@dependent@*/ /*@null@*/ idTableEntry *symtable_lookupInScope (idTable * p_st, lsymbol p_id);
00104 
00105 static /*@only@*/ idTable *symtable_newIdTable (void);
00106 static void idTableEntry_free (idTableEntry p_x);
00107 
00108 /* Local implementatio of hash table */
00109 
00110 static bool allowed_redeclaration = FALSE;
00111 static symbolKey htData_key (htData *p_x);
00112 
00113 static void symHashTable_free (/*@only@*/ symHashTable *p_h);
00114 static /*@only@*/ symHashTable *symHashTable_create (unsigned int p_size);
00115 static /*@null@*/ /*@exposed@*/ htData *
00116   symHashTable_get (symHashTable * p_t, symbolKey p_key, infoKind p_kind, 
00117                  /*@null@*/ nameNode p_n);
00118 static bool symHashTable_put (symHashTable *p_t, /*@only@*/ htData *p_data);
00119 static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
00120   symHashTable_forcePut (symHashTable * p_t, /*@only@*/ htData *p_data);
00121 /* static unsigned int symHashTable_count (symHashTable * t); */
00122 
00123 static void idTable_free (/*@only@*/ idTable *p_st);
00124 
00125 void varInfo_free (/*@only@*/ varInfo v)
00126 {
00127   sfree (v);
00128 }
00129 
00130 static /*@only@*/ varInfo varInfo_copy (varInfo v)
00131 {
00132   varInfo ret = (varInfo) dmalloc (sizeof (*ret));
00133 
00134   ret->id = ltoken_copy (v->id);
00135   ret->sort = v->sort;
00136   ret->kind = v->kind;
00137   ret->export = v->export;
00138 
00139   return ret;
00140 }
00141 
00142 void symtable_free (symtable stable)
00143 {
00144   /* symtable_printStats (stable); */
00145 
00146   idTable_free (stable->idTable);
00147   symHashTable_free (stable->hTable);
00148   mapping_free (stable->type2sort);
00149   sfree (stable);
00150 }
00151 
00152 static void idTable_free (idTable *st)
00153 {
00154   unsigned int i;
00155 
00156   for (i = 0; i < st->size; i++)
00157     {
00158       idTableEntry_free (st->entries[i]);
00159     }
00160 
00161   sfree (st->entries);
00162   sfree (st);
00163 }
00164 
00165 static void fctInfo_free (/*@only@*/ fctInfo f)
00166 {
00167   signNode_free (f->signature);
00168   pairNodeList_free (f->globals);
00169   ltoken_free (f->id);
00170   sfree (f);
00171 }
00172 
00173 static void typeInfo_free (/*@only@*/ typeInfo t)
00174 {
00175   sfree (t);
00176 }
00177 
00178 static void scopeInfo_free (/*@only@*/ scopeInfo s)
00179 {
00180   sfree (s);
00181 }
00182 
00183 static void idTableEntry_free (idTableEntry x)
00184 {
00185   switch (x.kind)
00186     {
00187     case SYMK_FCN:
00188       fctInfo_free (x.info.fct);
00189       break;
00190     case SYMK_SCOPE:
00191       scopeInfo_free (x.info.scope);
00192       break;
00193     case SYMK_TYPE:
00194       typeInfo_free (x.info.type);
00195       break;
00196     case SYMK_VAR:
00197       varInfo_free (x.info.var);
00198       break;
00199     }
00200 }
00201 
00202 static /*@observer@*/ ltoken idTableEntry_getId (idTableEntry *x)
00203 {
00204   switch (x->kind)
00205     {
00206     case SYMK_FCN:
00207       return (x->info.fct->id);
00208     case SYMK_SCOPE:
00209       return ltoken_undefined;
00210     case SYMK_TYPE:
00211       return (x->info.type->id);
00212     case SYMK_VAR:
00213       return (x->info.var->id);
00214     }
00215 
00216   BADBRANCH;
00217 }
00218 
00219 /*@only@*/ symtable
00220 symtable_new (void)
00221 {
00222   symtable stable = (symtable) dmalloc (sizeof (*stable));
00223   idTableEntry *e;
00224   
00225   stable->idTable = symtable_newIdTable ();
00226   stable->hTable = symHashTable_create (HT_MAXINDEX);
00227   stable->type2sort = mapping_create ();
00228   
00229   /* add builtin synonym:  Bool -> bool */
00230   
00231   mapping_bind (stable->type2sort, lsymbol_getBool (), lsymbol_getbool ());
00232 
00233   /*
00234   ** done by symtable_newIdTable
00235   ** st->allocated = 0;
00236   ** st->entries = (idTableEntry *) 0;
00237   ** st->exporting = TRUE;
00238   */
00239 
00240   /* this is global scope */
00241   e = nextFree (stable->idTable);
00242   e->kind = SYMK_SCOPE;
00243   (e->info).scope = (scopeInfo) dmalloc (sizeof (*((e->info).scope)));
00244   (e->info).scope->kind = SPE_GLOBAL;
00245   
00246   return stable;
00247 }
00248 
00249 static /*@only@*/ idTable *symtable_newIdTable (void)
00250 {
00251   idTable *st = (idTable *) dmalloc (sizeof (*st));
00252 
00253   st->size = 0;
00254   st->allocated = 0;
00255   st->entries = (idTableEntry *) 0;
00256   st->exporting = TRUE;
00257   
00258   /* this was being done twice!
00259      e = nextFree (st);
00260      e->kind = SYMK_SCOPE;
00261      (e->info).scope.kind = globScope;
00262      */
00263 
00264   return st;
00265 }
00266 
00267 static lsymbol
00268 nameNode2key (nameNode n)
00269 {
00270   unsigned int ret;
00271 
00272   if (n->isOpId)
00273     {
00274       ret =  ltoken_getText (n->content.opid);
00275     }
00276   else
00277     {
00278       /* use opForm's key as its Identifier */
00279       llassert (n->content.opform != NULL);
00280       ret = (n->content.opform)->key;
00281     }
00282 
00283   return ret;
00284 }
00285 
00286 /*
00287 ** requires: nameNode n is already in st.
00288 */
00289 
00290 static bool
00291 htData_insertSignature (htData *d, /*@owned@*/ sigNode oi)
00292 {
00293   sigNodeSet set = d->content.op->signatures;
00294 
00295   
00296   if (oi != (sigNode) 0)
00297     {
00298       return (sigNodeSet_insert (set, oi));
00299     }
00300   return FALSE;
00301 }
00302 
00303 void
00304 symtable_enterOp (symtable st, /*@only@*/ /*@notnull@*/ nameNode n, 
00305                   /*@owned@*/ sigNode oi)
00306 {
00307   /*
00308   ** Operators are overloaded, we allow entering opInfo more than once,
00309   ** even if it's the same signature. 
00310   **
00311   ** Assumes all sorts are already entered into the symbol table 
00312   */
00313 
00314   symHashTable *ht = st->hTable;
00315   htData *d;
00316   lsymbol id;
00317 
00318   
00319   
00320   id = nameNode2key (n);
00321 
00322   d = symHashTable_get (ht, id, IK_OP, n);
00323   
00324   if (d == (htData *) 0)
00325     {                           /* first signature of this operator */
00326       opInfo op = (opInfo) dmalloc (sizeof (*op));
00327       htData *nd = (htData *) dmalloc (sizeof (*nd));
00328 
00329       op->name = n;
00330 
00331       if (oi != (sigNode) 0)
00332         {
00333           op->signatures = sigNodeSet_singleton (oi);
00334           ht->count++;
00335         }
00336       else
00337         {
00338           op->signatures = sigNodeSet_new ();
00339           sigNode_markOwned (oi);
00340         }
00341 
00342       nd->kind = IK_OP;
00343       nd->content.op = op;
00344       (void) symHashTable_put (ht, nd);
00345     }
00346   else
00347     {
00348       
00349       nameNode_free (n);  /*<<<??? */
00350 
00351       if (htData_insertSignature (d, oi))
00352         {
00353           ht->count++;
00354         }
00355     }
00356 }
00357 
00358 bool
00359   symtable_enterTag (symtable st, tagInfo ti)
00360 {
00361   /* put ti only if it is not already in symtable */
00362   symHashTable *ht = st->hTable;
00363   htData *d;
00364   symbolKey key = ltoken_getText (ti->id);
00365 
00366   d = symHashTable_get (ht, key, IK_TAG, (nameNode) 0);
00367   if (d == (htData *) 0)
00368     {
00369       d = (htData *) dmalloc (sizeof (*d));
00370       d->kind = IK_TAG;
00371       d->content.tag = ti;
00372       d->content.tag->imported = context_inImport ();
00373       (void) symHashTable_put (ht, d);
00374       return TRUE;
00375     }
00376   else
00377     {
00378       if (d->content.tag->imported)
00379         {
00380           d->content.tag = ti;
00381           d->content.tag->imported = context_inImport ();
00382           return TRUE;
00383         }
00384       else
00385         {
00386           tagInfo_free (ti);
00387           return FALSE;
00388         }
00389     }
00390 }
00391 
00392 bool
00393 symtable_enterTagForce (symtable st, tagInfo ti)
00394 {
00395  /* put ti, force-put if necessary */
00396   symHashTable *ht = st->hTable;
00397   htData *d;
00398   symbolKey key = ltoken_getText (ti->id);
00399 
00400   d = symHashTable_get (ht, key, IK_TAG, (nameNode) 0);
00401 
00402   if (d == (htData *) 0)
00403     {
00404       d = (htData *) dmalloc (sizeof (*d));
00405       
00406       d->kind = IK_TAG;
00407       d->content.tag = ti;
00408       d->content.tag->imported = context_inImport ();
00409       (void) symHashTable_put (ht, d);
00410       return TRUE;
00411     }
00412   else
00413     {
00414             
00415       d->kind = IK_TAG;
00416       d->content.tag = ti;
00417       d->content.tag->imported = context_inImport ();
00418       /* interpret return data later, htData * */
00419       /*@i@*/ (void) symHashTable_forcePut (ht, d);
00420       return FALSE;
00421     }
00422 }
00423 
00424 /*@null@*/ opInfo
00425 symtable_opInfo (symtable st, /*@notnull@*/ nameNode n)
00426 {
00427   symHashTable *ht = st->hTable;
00428   lsymbol i = nameNode2key (n);
00429 
00430   htData *d;
00431   d = symHashTable_get (ht, i, IK_OP, n);
00432   if (d == (htData *) 0)
00433     {
00434       return (opInfo)NULL;
00435     }
00436 
00437   return (d->content.op);
00438 }
00439 
00440 /*@null@*/ tagInfo
00441 symtable_tagInfo (symtable st, lsymbol i)
00442 {
00443   symHashTable *ht = st->hTable;
00444   htData *d;
00445   d = symHashTable_get (ht, i, IK_TAG, 0);
00446 
00447   if (d == (htData *) 0)
00448     {
00449       return (tagInfo) NULL;
00450     }
00451 
00452   return (d->content.tag);
00453 }
00454 
00455 void
00456   symtable_enterScope (symtable stable, scopeInfo si)
00457 {
00458   idTable *st = stable->idTable;
00459   idTableEntry *e = nextFree (st);
00460   if (si->kind == SPE_GLOBAL)
00461     llbuglit ("symtable_enterScope: SPE_GLOBAL");
00462   e->kind = SYMK_SCOPE;
00463   (e->info).scope = si;
00464 }
00465 
00466 void
00467 symtable_exitScope (symtable stable)
00468 {
00469   idTable *st = stable->idTable;
00470   int n;
00471 
00472   if (st->entries != NULL)
00473     {
00474       for (n = st->size - 1; (st->entries[n]).kind != SYMK_SCOPE; n--)
00475         {
00476           ;
00477         }
00478     }
00479   else
00480     {
00481       llcontbuglit ("symtable_exitScope: no scope to exit");
00482       n = 0;
00483     }
00484 
00485   st->size = n;
00486 }
00487 
00488 bool
00489 symtable_enterFct (symtable stable, fctInfo fi)
00490 {
00491   idTable *st = stable->idTable;
00492   idTableEntry *e;
00493   bool redecl = FALSE;
00494 
00495   if (!allowed_redeclaration &&
00496       symtable_lookup (st, ltoken_getText (fi->id)) != (idTableEntry *) 0)
00497     {
00498       lclRedeclarationError (fi->id);
00499       redecl = TRUE;
00500     }
00501   
00502   e = nextFree (st);
00503   e->kind = SYMK_FCN;
00504   fi->export = st->exporting;   /* && !fi->private; */
00505   (e->info).fct = fi;
00506 
00507   return redecl;
00508 }
00509 
00510 void
00511 symtable_enterType (symtable stable, /*@only@*/ typeInfo ti)
00512 {
00513   idTable *st = stable->idTable;
00514   idTableEntry *e;
00515   bool insertp = TRUE;
00516   scopeKind k = (symtable_scopeInfo (stable))->kind;
00517 
00518   /* symtable_disp (stable); */
00519 
00520   if (k != SPE_GLOBAL && k != SPE_INVALID)      /* fixed for LCLint */
00521     {
00522       llbug (message ("%q: symtable_enterType: expect global scope. (type: %s)",
00523                       ltoken_unparseLoc (ti->id),
00524                       ltoken_getRawString (ti->id)));
00525     }
00526 
00527   if (!allowed_redeclaration &&
00528       symtable_lookup (st, ltoken_getText (ti->id)) != (idTableEntry *) 0)
00529     {
00530      /* ignore if Bool is re-entered */
00531       if (ltoken_getText (ti->id) == lsymbol_getBool () ||
00532           ltoken_getText (ti->id) == lsymbol_getbool ())
00533         {
00534           insertp = FALSE;
00535         }
00536       else
00537         {
00538           lclRedeclarationError (ti->id);
00539         }
00540     }
00541   if (insertp)
00542     {
00543       /* make sure it is a type TYPEDEF_NAME; */
00544       
00545       if (ltoken_getCode (ti->id) != LLT_TYPEDEF_NAME)
00546         {
00547           lclbug (message ("symtable_enterType: gets a simpleId, expect a type: %s",
00548                            ltoken_getRawString (ti->id)));
00549         }
00550       
00551       e = nextFree (st);
00552       e->kind = SYMK_TYPE;
00553       ti->export = st->exporting;/* && !ti->private; */
00554       (e->info).type = ti;
00555       mapping_bind (stable->type2sort, ltoken_getText (ti->id),
00556                     sort_getLsymbol (sort_makeVal (sort_getUnderlying (ti->basedOn))));
00557     }
00558   else
00559     {
00560       typeInfo_free (ti);
00561     }
00562 }
00563 
00564 lsymbol
00565 lsymbol_sortFromType (symtable s, lsymbol typename)
00566 {
00567   lsymbol inter;
00568   lsymbol out;
00569   ltoken tok;
00570  /* check the synonym table first */
00571   if (LCLIsSyn (typename))
00572     {
00573       tok = LCLGetTokenForSyn (typename);
00574       inter = ltoken_getText (tok);
00575      /*    printf ("In lsymbol_sortFromType: %s -> %s\n",
00576                 lsymbol_toChars (typename), lsymbol_toChars (inter)); */
00577     }
00578   else
00579     {
00580       inter = typename;
00581     }
00582 
00583   /* now map LCL type to sort */
00584   out = mapping_find (s->type2sort, inter);
00585   
00586   if (out == lsymbol_undefined)
00587     {
00588       return inter;
00589     }
00590 
00591   return out;
00592 }
00593 
00594 /* really temp! */
00595 
00596 /*
00597 ** returns true is vi is a redeclaration
00598 */
00599 
00600 bool
00601 symtable_enterVar (symtable stable, /*@temp@*/ varInfo vi)
00602 {
00603   idTable *st = stable->idTable;
00604   bool insertp = TRUE;
00605   bool redecl = FALSE;
00606 
00607   
00608   /* symtable_disp (symtab); */
00609   
00610   if (!allowed_redeclaration &&
00611       (symtable_lookupInScope (st, ltoken_getText (vi->id)) != (idTableEntry *) 0))
00612     {
00613       if (ltoken_getText (vi->id) == lsymbol_getTRUE () ||
00614           ltoken_getText (vi->id) == lsymbol_getFALSE ())
00615         {
00616           insertp = FALSE;
00617         }
00618       else
00619         {
00620           if (usymtab_existsEither (ltoken_getRawString (vi->id)))
00621             {
00622                       lclRedeclarationError (vi->id);
00623               redecl = TRUE;
00624             }
00625           else
00626             {
00627               llbuglit ("redeclared somethingerother?!");
00628             }
00629         }
00630     }
00631 
00632   if (insertp)
00633     {
00634       idTableEntry *e = nextFree (st);
00635 
00636       e->kind = SYMK_VAR;
00637       vi->export = st->exporting &&     /* !vi.private && */
00638         (vi->kind == VRK_VAR || vi->kind == VRK_CONST || vi->kind == VRK_ENUM);
00639       (e->info).var = varInfo_copy (vi);
00640     }
00641   
00642     return (redecl);
00643 }
00644 
00645 bool
00646 symtable_exists (symtable stable, lsymbol i)
00647 {
00648   idTable *st = stable->idTable;
00649   return symtable_lookup (st, i) != (idTableEntry *) 0;
00650 }
00651 
00652 /*@null@*/ typeInfo
00653 symtable_typeInfo (symtable stable, lsymbol i)
00654 {
00655   idTable *st;
00656   idTableEntry *e;
00657 
00658   st = stable->idTable;
00659   e = symtable_lookup (st, i);
00660 
00661   if (e == (idTableEntry *) 0 || e->kind != SYMK_TYPE)
00662     {
00663       return (typeInfo) NULL;
00664     }
00665 
00666   return (e->info).type;
00667 }
00668 
00669 /*@null@*/ varInfo
00670 symtable_varInfo (symtable stable, lsymbol i)
00671 {
00672   idTable *st = stable->idTable;
00673   idTableEntry *e;
00674 
00675   e = symtable_lookup (st, i);
00676 
00677   if (e == (idTableEntry *) 0 || e->kind != SYMK_VAR)
00678     {
00679       return (varInfo) NULL;
00680     }
00681 
00682   return (e->info).var;
00683 }
00684 
00685 /*@null@*/ varInfo
00686 symtable_varInfoInScope (symtable stable, lsymbol id)
00687 {
00688   /* if current scope is a SPE_QUANT, can go beyond current scope */
00689   idTable *st = stable->idTable;
00690   idTableEntry *e2 = (idTableEntry *) 0;
00691   int n;
00692   
00693   for (n = st->size - 1; n >= 0; n--)
00694     {
00695       ltoken tok;
00696 
00697       e2 = &(st->entries[n]);
00698       
00699       if (e2->kind == SYMK_SCOPE && e2->info.scope->kind != SPE_QUANT)
00700         {
00701           return (varInfo) NULL;
00702         }
00703 
00704       tok = idTableEntry_getId (e2);
00705 
00706       if (e2->kind == SYMK_VAR && ltoken_getText (tok) == id)
00707         {
00708           return (e2->info).var;
00709         }
00710     }
00711 
00712   return (varInfo) NULL;
00713 }
00714 
00715 scopeInfo
00716 symtable_scopeInfo (symtable stable)
00717 {
00718   idTable *st = stable->idTable;
00719   int n;
00720   idTableEntry *e;
00721 
00722   for (n = st->size - 1; n >= 0; n--)
00723     {
00724       e = &(st->entries[n]);
00725       if (e->kind == SYMK_SCOPE)
00726         return (e->info).scope;
00727     }
00728 
00729   lclfatalbug ("symtable_scopeInfo: not found");
00730   BADEXIT;
00731 }
00732 
00733 void
00734 symtable_export (symtable stable, bool yesNo)
00735 {
00736   idTable *st = stable->idTable;
00737   st->exporting = yesNo;
00738   (void) sort_setExporting (yesNo);
00739 }
00740 
00741 static void
00742 symHashTable_dump (symHashTable * t, FILE * f, bool lco)
00743 {
00744   /* like symHashTable_dump2 but for output to .lcs file */
00745   int i, size;
00746   bucket *b;
00747   htEntry *entry;
00748   htData *d;
00749   ltoken tok;
00750   sigNodeSet sigs;
00751   
00752   for (i = 0; i <= HT_MAXINDEX; i++)
00753     {
00754             b = t->buckets[i];
00755 
00756       for (entry = b; entry != NULL; entry = entry->next)
00757         {
00758           d = entry->data;
00759 
00760           switch (d->kind)
00761             {
00762             case IK_SORT:
00763               /*@switchbreak@*/ break;
00764             case IK_OP:
00765               {
00766                 char *name = cstring_toCharsSafe (nameNode_unparse (d->content.op->name));
00767                 sigs = d->content.op->signatures;
00768                 size = sigNodeSet_size (sigs);
00769 
00770                 
00771                 sigNodeSet_elements (sigs, x)
00772                   {
00773                     cstring s = sigNode_unparse (x);
00774 
00775                     if (lco)
00776                       {
00777                         fprintf (f, "%%LCL");
00778                       }
00779 
00780                     fprintf (f, "op %s %s\n", name, cstring_toCharsSafe (s));
00781                     cstring_free (s);
00782                   } end_sigNodeSet_elements;
00783 
00784                 sfree (name);
00785                 /*@switchbreak@*/ break;
00786               }
00787             case IK_TAG:
00788               tok = d->content.tag->id;
00789               
00790               if (!ltoken_isUndefined (tok))
00791                 {
00792                   cstring s = tagKind_unparse (d->content.tag->kind);
00793 
00794                   if (lco)
00795                     {
00796                       fprintf (f, "%%LCL");
00797                     }
00798 
00799                   fprintf (f, "tag %s %s\n", ltoken_getTextChars (tok), 
00800                            cstring_toCharsSafe (s));
00801                   cstring_free (s);
00802                 }
00803               /*@switchbreak@*/ break;
00804             }
00805         }
00806     }
00807 }
00808 
00809 void
00810 symtable_dump (symtable stable, FILE * f, bool lco)
00811 {
00812   symHashTable *ht = stable->hTable;
00813 
00814 
00815   fprintf (f, "%s\n", BEGINSYMTABLE);
00816    
00817   symHashTable_dump (ht, f, lco);
00818    
00819   symtable_dumpId (stable, f, lco);
00820   
00821   fprintf (f, "%s\n", SYMTABLEEND);
00822   }
00823 
00824 lsymbol
00825 lsymbol_translateSort (mapping * m, lsymbol s)
00826 {
00827   lsymbol res = mapping_find (m, s);
00828   if (res == lsymbol_undefined)
00829     return s;
00830   return res;
00831 }
00832 
00833 static /*@null@*/ lslOp
00834   lslOp_renameSorts (mapping *map,/*@returned@*/ /*@null@*/ lslOp op)
00835 {
00836   sigNode sign;
00837 
00838   if (op != (lslOp) 0)
00839     {
00840       ltokenList domain;
00841       ltoken range;
00842 
00843       sign = op->signature;
00844       range = sign->range;
00845       domain = sign->domain;
00846 
00847       ltokenList_elements (domain, dt)
00848         {
00849           ltoken_setText (dt, 
00850                           lsymbol_translateSort (map, ltoken_getText (dt)));
00851         } end_ltokenList_elements;
00852 
00853       /*@-onlytrans@*/ /* A memory leak... */
00854       op->signature = makesigNode (sign->tok, domain, range);
00855       /*@=onlytrans@*/
00856     }
00857 
00858   return op;
00859 }
00860 
00861 static /*@null@*/ signNode
00862   signNode_fromsigNode (sigNode s)
00863 {
00864   signNode sign;
00865   sortList slist;
00866   
00867   if (s == (sigNode) 0)
00868     {
00869       return (signNode) 0;
00870     }
00871   
00872   sign = (signNode) dmalloc (sizeof (*sign));
00873   slist = sortList_new ();
00874   sign->tok = ltoken_copy (s->tok);
00875   sign->key = s->key;
00876   sign->range = sort_makeSort (ltoken_undefined, ltoken_getText (s->range));
00877 
00878   ltokenList_elements (s->domain, dt)
00879     {
00880       sortList_addh (slist, sort_makeSort (ltoken_undefined, ltoken_getText (dt)));
00881     } end_ltokenList_elements;
00882 
00883   sign->domain = slist;
00884   return sign;
00885 }
00886 
00887 
00892 static /*@only@*/ pairNodeList
00893 parseGlobals (char *line, tsource *srce)
00894 {
00895   pairNodeList plist = pairNodeList_new ();
00896   pairNode p;
00897   int semi_index;
00898   char *lineptr, sostr[MAXBUFFLEN], gstr[MAXBUFFLEN];
00899 
00900   /* line is not all blank */
00901   /* expected format: "sort1 g1; sort2 g2; sort3 g3;" */
00902   lineptr = line;
00903   
00904   while (!isBlankLine (lineptr))
00905     {
00906       if (sscanf (lineptr, "%s %s", &(sostr[0]), gstr) != 2)
00907         {
00908           lclplainerror 
00909             (message 
00910              ("%q: Imported file contains illegal function global declaration.\n"
00911               "Skipping rest of the line: %s (%s)",
00912               fileloc_unparseRaw (cstring_fromChars (tsource_fileName (srce)), 
00913                                   tsource_thisLineNumber (srce)), 
00914               cstring_fromChars (line), 
00915               cstring_fromChars (lineptr)));
00916           return plist;
00917         }
00918       
00919       p = (pairNode) dmalloc (sizeof (*p));
00920       
00921       /* Note: remove the ";" separator at the end of gstr */
00922       semi_index = size_toInt (strlen (gstr));
00923       gstr[semi_index - 1] = '\0';
00924 
00925       p->tok = ltoken_create (NOTTOKEN, lsymbol_fromChars (gstr));
00926       p->sort = sort_makeSort (ltoken_undefined, lsymbol_fromChars (sostr));
00927 
00928       pairNodeList_addh (plist, p);
00929       lineptr = strchr (lineptr, ';');  /* go pass the next; */
00930 
00931       llassert (lineptr != NULL);
00932       lineptr = lineptr + 1;
00933     }
00934 
00935   return plist;
00936 }
00937 
00938 static bool
00939 isBlankLine (char *line)
00940 {
00941   int i;
00942 
00943   if (line == NULL) return TRUE;
00944 
00945   for (i = 0; line[i] != '\0'; i++)
00946     {
00947       if (line[i] == ' ')
00948         continue;
00949       if (line[i] == '\t')
00950         continue;
00951       if (line[i] == '\n')
00952         return TRUE;
00953       return FALSE;
00954     }
00955   return TRUE;
00956 }
00957 
00958 typedef /*@only@*/ fctInfo o_fctInfo;
00959 
00960 static void
00961 parseLine (char *line, tsource *srce, mapping * map)
00962 {
00963   static /*@owned@*/ o_fctInfo *savedFcn = NULL;
00964   char *lineptr, *lineptr2, *cimportfile = tsource_fileName (srce);
00965   cstring importfile = cstring_fromChars (cimportfile);
00966   char namestr[MAXBUFFLEN], kstr[20], sostr[MAXBUFFLEN];
00967   sort bsort, nullSort = sort_makeNoSort ();
00968   int col = 0;
00969   fileloc imploc = fileloc_undefined;
00970 
00971   
00972   if (inImport)
00973     {
00974       imploc = fileloc_createImport (importfile, tsource_thisLineNumber (srce));
00975     }
00976   
00977   if (firstWord (line, "op"))
00978     {
00979       lslOp op;
00980 
00981       lineptr = strchr (line, 'o');     /* remove any leading blanks */
00982       llassert (lineptr != NULL);
00983       lineptr = strchr (lineptr, ' ');  /* go past "op" */
00984       llassert (lineptr != NULL);
00985 
00986       /* add a newline to the end of the line since parseOpLine expects it */
00987       lineptr2 = strchr (lineptr, '\0');
00988 
00989       if (lineptr2 != 0)
00990         {
00991           *lineptr2 = '\n';
00992           *(lineptr2 + 1) = '\0';
00993         }
00994 
00995       llassert (cimportfile != NULL);
00996       op = parseOpLine (cimportfile, lineptr + 1);
00997       
00998       if (op == (lslOp) 0)
00999         {
01000           lclplainerror
01001             (message
01002              ("%q: Imported file contains illegal operator declaration:\n "
01003               "skipping this line: %s",
01004               fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01005               cstring_fromChars (line)));
01006           fileloc_free (imploc);
01007           return;
01008         }
01009 
01010             op = lslOp_renameSorts (map, op);
01011 
01012       llassert (op != NULL);
01013       llassert (op->name != NULL);
01014 
01015       symtable_enterOp (g_symtab, op->name, 
01016                         sigNode_copy (op->signature));
01017           /*@-mustfree@*/ } /*@=mustfree@*/
01018   else if (firstWord (line, "type"))
01019     {
01020       typeInfo ti;
01021 
01022       if (sscanf (line, "type %s %s %s", namestr, sostr, kstr) != 3)
01023         {
01024           lclplainerror 
01025             (message ("%q: illegal type declaration:\n skipping this line: %s",
01026                       fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01027                       cstring_fromChars (line)));
01028           fileloc_free (imploc);
01029           return;
01030         }
01031       
01032       ti = (typeInfo) dmalloc (sizeof (*ti));
01033       ti->id = ltoken_createFull (LLT_TYPEDEF_NAME, lsymbol_fromChars (namestr),
01034                                     importfile, tsource_thisLineNumber (srce), col);
01035 
01036       bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
01037 
01038       if (sort_isNoSort (bsort))
01039         {
01040           lineptr = strchr (line, ' '); /* go past "type" */
01041           llassert (lineptr != NULL);
01042           lineptr = strchr (lineptr + 1, ' ');  /* go past namestr */
01043           llassert (lineptr != NULL);
01044           col = 5 + lineptr - line;     /* 5 for initial "%LCL "*/
01045 
01046           lclbug (message ("%q: Imported files contains unknown base sort",
01047                            fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
01048 
01049           bsort = nullSort;
01050         }
01051       ti->basedOn = bsort;
01052 
01053       if (strcmp (kstr, "exposed") == 0)
01054         {
01055           ti->abstract = FALSE;
01056           ti->modifiable = TRUE;
01057         }
01058       else
01059         {
01060           ti->abstract = TRUE;
01061           if (strcmp (kstr, "mutable") == 0)
01062             ti->modifiable = TRUE;
01063           else
01064             ti->modifiable = FALSE;
01065         }
01066       ti->export = TRUE;
01067       
01068       /* 
01069       ** sort of a hack to get imports to work...
01070       */
01071       
01072       if (inImport)
01073         {
01074           cstring cnamestr = cstring_fromChars (namestr);
01075 
01076           if (!usymtab_existsGlobEither (cnamestr))
01077             {
01078               (void) usymtab_addEntry 
01079                 (uentry_makeDatatype (cnamestr, ctype_unknown,
01080                                       ti->abstract ? ynm_fromBool (ti->modifiable) : MAYBE,
01081                                       ti->abstract ? YES : NO,
01082                                       fileloc_copy (imploc)));
01083             }
01084         }
01085 
01086       symtable_enterType (g_symtab, ti);
01087     }
01088   else if (firstWord (line, "var"))
01089     {
01090       varInfo vi;
01091 
01092       if (sscanf (line, "var %s %s", namestr, sostr) != 2)
01093         {
01094           lclplainerror
01095             (message ("%q: Imported file contains illegal variable declaration.  "
01096                       "Skipping this line.", 
01097                       fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce))));
01098           fileloc_free (imploc);
01099           return;
01100         }
01101 
01102       vi = (varInfo) dmalloc (sizeof (*vi));
01103       bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
01104       lineptr = strchr (line, ' ');     /* go past "var" */
01105       llassert (lineptr != NULL);
01106       lineptr = strchr (lineptr + 1, ' ');      /* go past namestr */
01107       llassert (lineptr != NULL);
01108       col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
01109 
01110       if (sort_isNoSort (bsort))
01111         {
01112           lclplainerror (message ("%q: Imported file contains unknown base sort",
01113                                   fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
01114           bsort = nullSort;
01115         }
01116 
01117       vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
01118                                   importfile, tsource_thisLineNumber (srce), col);
01119       vi->sort = bsort;
01120       vi->kind = VRK_VAR;
01121       vi->export = TRUE;
01122       (void) symtable_enterVar (g_symtab, vi);
01123       varInfo_free (vi);
01124 
01125       if (inImport)
01126         {
01127           cstring cnamestr = cstring_fromChars (namestr);
01128 
01129           if (!usymtab_existsGlobEither (cnamestr))
01130             {
01131               
01132               (void) usymtab_supEntrySref 
01133                 (uentry_makeVariable (cnamestr, ctype_unknown, 
01134                                       fileloc_copy (imploc), 
01135                                       FALSE));
01136             }
01137         }
01138     }
01139   else if (firstWord (line, "const"))
01140     {
01141       varInfo vi;
01142 
01143       if (sscanf (line, "const %s %s", namestr, sostr) != 2)
01144         {
01145           lclbug (message ("%q: Imported file contains illegal constant declaration: %s",
01146                            fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01147                            cstring_fromChars (line)));
01148           fileloc_free (imploc);
01149           return;
01150         }
01151 
01152       vi = (varInfo) dmalloc (sizeof (*vi));
01153       bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
01154       lineptr = strchr (line, ' ');     /* go past "var" */
01155       llassert (lineptr != NULL);
01156       lineptr = strchr (lineptr + 1, ' ');      /* go past namestr */
01157       llassert (lineptr != NULL);
01158       
01159       col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
01160 
01161       if (sort_isNoSort (bsort))
01162         {
01163           lclplainerror (message ("%q: Imported file contains unknown base sort",
01164                                   fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
01165           bsort = nullSort;
01166         }
01167 
01168       vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
01169                                     importfile, tsource_thisLineNumber (srce), col);
01170       vi->sort = bsort;
01171       vi->kind = VRK_CONST;
01172       vi->export = TRUE;
01173       (void) symtable_enterVar (g_symtab, vi);
01174       varInfo_free (vi);
01175       
01176       if (inImport)
01177         {
01178           cstring cnamestr = cstring_fromChars (namestr);
01179           
01180           if (!usymtab_existsGlobEither (cnamestr))
01181             {
01182                       
01183               (void) usymtab_addEntry (uentry_makeConstant (cnamestr,
01184                                                             ctype_unknown,
01185                                                             fileloc_copy (imploc)));
01186             }
01187         }
01188       /* must check for "fcnGlobals" before "fcn" */
01189     }
01190   else if (firstWord (line, "fcnGlobals"))
01191     {
01192       pairNodeList globals;
01193       lineptr = strchr (line, 'f');     /* remove any leading blanks */
01194       llassert (lineptr != NULL);
01195       lineptr = strchr (lineptr, ' ');  /* go past "fcnGlobals" */
01196       llassert (lineptr != NULL);
01197 
01198      /* a quick check for empty fcnGlobals */
01199       if (!isBlankLine (lineptr))
01200         {
01201           globals = parseGlobals (lineptr, srce);
01202           /* should ensure that each global in an imported function
01203              corresponds to some existing global.  Since only
01204              "correctly processed" .lcs files are imported, this is
01205              true as an invariant. */
01206         }
01207       else
01208         {
01209           globals = pairNodeList_new ();
01210         }
01211       
01212       /* check that they exist, store them on fctInfo */
01213 
01214       if (savedFcn != NULL)
01215         {
01216           pairNodeList_free ((*savedFcn)->globals);
01217           (*savedFcn)->globals = globals;  /* evs, moved inside if predicate */
01218 
01219           (void) symtable_enterFct (g_symtab, *savedFcn);
01220           savedFcn = NULL;
01221         }
01222       else
01223         {
01224           lclplainerror 
01225             (message ("%q: Unexpected function globals.  "
01226                       "Skipping this line: \n%s",
01227                       fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01228                       cstring_fromChars (line)));
01229           savedFcn = NULL;
01230           pairNodeList_free (globals);
01231         }
01232     }
01233   else if (firstWord (line, "fcn"))
01234     {
01235       lslOp op;
01236       lslOp op2; 
01237 
01238       if (savedFcn != (fctInfo *) 0)
01239         {
01240           lclplainerror 
01241             (message ("%q: illegal function declaration.  Skipping this line:\n%s",
01242                       fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01243                       cstring_fromChars (line)));
01244           fileloc_free (imploc);
01245           return;
01246         }
01247 
01248       savedFcn = (fctInfo *) dmalloc (sizeof (*savedFcn));
01249 
01250       lineptr = strchr (line, 'f');     /* remove any leading blanks */
01251       llassert (lineptr != NULL);
01252       lineptr = strchr (lineptr, ' ');  /* go past "fcn" */
01253       llassert (lineptr != NULL);
01254 
01255       /* add a newline to the end of the line since parseOpLine expects it */
01256 
01257       lineptr2 = strchr (lineptr, '\0');
01258 
01259       if (lineptr2 != 0)
01260         {
01261           *lineptr2 = '\n';
01262           *(lineptr2 + 1) = '\0';
01263         }
01264 
01265       op = parseOpLine (cimportfile, lineptr + 1);
01266 
01267       if (op == (lslOp) 0)
01268         {
01269           lclplainerror (message ("%q: illegal function declaration: %s",
01270                                   fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01271                                   cstring_fromChars (line)));
01272           fileloc_free (imploc);
01273           return;
01274         }
01275         
01276       op2 = lslOp_renameSorts (map, op);
01277 
01278       llassert (op2 != NULL);
01279 
01280       if ((op->name != NULL) && op->name->isOpId)
01281         {
01282           (*savedFcn) = (fctInfo) dmalloc (sizeof (**savedFcn));
01283           (*savedFcn)->id = op->name->content.opid;
01284           (*savedFcn)->signature = signNode_fromsigNode (op2->signature);
01285           (*savedFcn)->globals = pairNodeList_new ();
01286           (*savedFcn)->export = TRUE;
01287           
01288           if (inImport)
01289             {
01290               /* 27 Jan 1995 --- added this to be undefined namestr bug */
01291               cstring fname = ltoken_unparse ((*savedFcn)->id);
01292               
01293               if (!usymtab_existsGlobEither (fname))
01294                 {
01295                                   (void) usymtab_addEntry (uentry_makeFunction
01296                                            (fname, ctype_unknown, 
01297                                             typeId_invalid, globSet_new (),
01298                                             sRefSet_undefined, 
01299                                             fileloc_copy (imploc)));
01300                 }
01301             }
01302         }
01303       else
01304         {
01305           lclplainerror (message ("%q: unexpected function name: %s",
01306                                   fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01307                                   cstring_fromChars (line)));
01308         }
01309     }
01310   else if (firstWord (line, "enumConst"))
01311     {
01312       varInfo vi;
01313 
01314       if (sscanf (line, "enumConst %s %s", namestr, sostr) != 2)
01315         {
01316           lclplainerror 
01317             (message ("%q: Illegal enum constant declaration.  "
01318                       "Skipping this line:\n%s",
01319                       fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01320                       cstring_fromChars (line)));
01321           fileloc_free (imploc);
01322           return;
01323         }
01324       
01325       vi = (varInfo) dmalloc (sizeof (*vi));
01326       bsort = sort_lookupName (lsymbol_translateSort (map, lsymbol_fromChars (sostr)));
01327       lineptr = strchr (line, ' ');     /* go past "var" */
01328       llassert (lineptr != NULL);
01329       lineptr = strchr (lineptr + 1, ' ');      /* go past namestr */
01330       llassert (lineptr != NULL);
01331 
01332       col = 5 + lineptr - line; /* 5 for initial "%LCL "*/
01333       if (sort_isNoSort (bsort))
01334         {
01335           lclplainerror (message ("%q: unknown base sort\n",
01336                                   fileloc_unparseRawCol (importfile, tsource_thisLineNumber (srce), col)));
01337           bsort = nullSort;
01338         }
01339 
01340       vi->id = ltoken_createFull (simpleId, lsymbol_fromChars (namestr),
01341                                     importfile, tsource_thisLineNumber (srce), col);
01342                         
01343       vi->sort = bsort;
01344       vi->kind = VRK_ENUM;
01345       vi->export = TRUE;
01346       (void) symtable_enterVar (g_symtab, vi);
01347       varInfo_free (vi);
01348 
01349       if (inImport)
01350         {
01351           cstring cnamestr = cstring_fromChars (namestr);
01352           if (!usymtab_existsEither (cnamestr))
01353             {
01354                       (void) usymtab_addEntry (uentry_makeConstant (cnamestr, ctype_unknown,
01355                                                             fileloc_copy (imploc)));
01356             }
01357         }
01358     }
01359   else if (firstWord (line, "tag"))
01360     {
01361      /* do nothing, sort processing already handles this */
01362     }
01363   else
01364     {
01365       lclplainerror 
01366         (message ("%q: Unknown symbol declaration.  Skipping this line:\n%s",
01367                   fileloc_unparseRaw (importfile, tsource_thisLineNumber (srce)), 
01368                   cstring_fromChars (line)));
01369     }
01370 
01371     fileloc_free (imploc);
01372 }
01373 
01374 void
01375 symtable_import (tsource *imported, ltoken tok, mapping * map)
01376 {
01377   char *buf, *importfile;
01378   tsource *lclsource;
01379   int old_lsldebug;
01380   bool old_inImport = inImport;
01381 
01382   buf = tsource_nextLine (imported);
01383   importfile = tsource_fileName (imported);
01384 
01385   llassert (buf != NULL);
01386 
01387   if (!firstWord (buf, "%LCLSymbolTable"))
01388     {
01389       lclsource = LCLScanSource ();
01390       lclfatalerror (tok, 
01391                      message ("Expecting '%%LCLSymbolTable' line in import file %s:\n%s\n",
01392                               cstring_fromChars (importfile), 
01393                               cstring_fromChars (buf)));
01394     }
01395 
01396   old_lsldebug = lsldebug;
01397   lsldebug = 0;
01398   allowed_redeclaration = TRUE;
01399   inImport = TRUE;
01400 
01401   for (;;)
01402     {
01403       buf = tsource_nextLine (imported);
01404       llassert (buf != NULL);
01405 
01406       
01407       if (firstWord (buf, "%LCLSymbolTableEnd"))
01408         {
01409           break;
01410         }
01411       else
01412         {                       /* a good line, remove %LCL from line first */
01413           if (firstWord (buf, "%LCL"))
01414             {
01415               parseLine (buf + 4, imported, map);
01416             }
01417           else
01418             {
01419               lclsource = LCLScanSource ();
01420               lclfatalerror 
01421                 (tok,
01422                  message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
01423                           cstring_fromChars (importfile), 
01424                           cstring_fromChars (buf)));
01425             }
01426         }
01427     }
01428 
01429   /* restore old value */
01430   inImport = old_inImport;
01431   lsldebug = old_lsldebug;
01432   allowed_redeclaration = FALSE;
01433   }
01434 
01435 static void
01436 symtable_dumpId (symtable stable, FILE *f, bool lco)
01437 {
01438   idTable *st = stable->idTable;
01439   unsigned int i;
01440   idTableEntry *se;
01441   fctInfo fi;
01442   typeInfo ti;
01443   varInfo vi;
01444 
01445   for (i = 1; i < st->size; i++)
01446     {
01447       /* 2/22/93 I think there is a off-by-1 error, 0 entry is never used */
01448       se = st->entries + i;
01449       llassert (se != NULL);
01450       
01451       
01452       /*@-loopswitchbreak@*/
01453       switch (se->kind)
01454         {
01455         case SYMK_FCN:
01456           {
01457             cstring tmp;
01458             
01459             fi = (se->info).fct;
01460             
01461             if (lco)
01462               {
01463                 fprintf (f, "%%LCL");
01464               }
01465 
01466             if (!lco && !fi->export)
01467               {
01468                 fprintf (f, "spec ");
01469               }
01470             
01471             tmp = signNode_unparse (fi->signature);
01472             fprintf (f, "fcn %s %s \n", ltoken_getTextChars (fi->id), 
01473                      cstring_toCharsSafe (tmp));
01474             cstring_free (tmp);
01475             
01476             tmp = pairNodeList_unparse (fi->globals);
01477             fprintf (f, "%%LCLfcnGlobals %s\n", cstring_toCharsSafe (tmp));
01478             cstring_free (tmp);
01479             break;
01480           }
01481         case SYMK_SCOPE:
01482           if (lco)
01483             {
01484               break;
01485             }
01486 
01487           /*@-switchswitchbreak@*/
01488           switch ((se->info).scope->kind)
01489             {
01490             case SPE_GLOBAL:
01491               fprintf (f, "Global scope\n");
01492               break;
01493             case SPE_ABSTRACT:
01494               fprintf (f, "Abstract type scope\n");
01495               break;
01496             case SPE_FCN:
01497               fprintf (f, "Function scope\n");
01498               break;
01499              /* a let scope can only occur in a function scope, should not push
01500                 a new scope, so symtable_lookupInScope works properly
01501                    case letScope:
01502                      fprintf (f, "Let scope\n");
01503                      break; */
01504             case SPE_QUANT:
01505               fprintf (f, "Quantifier scope\n");
01506               break;
01507             case SPE_CLAIM:
01508               fprintf (f, "Claim scope\n");
01509               break;
01510             case SPE_INVALID:
01511               break;
01512             }
01513           break;
01514         case SYMK_TYPE:
01515           ti = (se->info).type;
01516           if (lco)
01517             fprintf (f, "%%LCL");
01518           if (!lco && !ti->export)
01519             fprintf (f, "spec ");
01520           fprintf (f, "type %s %s",
01521                    ltoken_getTextChars (ti->id), sort_getName (ti->basedOn));
01522           if (ti->abstract)
01523             {
01524               if (ti->modifiable)
01525                 fprintf (f, " mutable\n");
01526               else
01527                 fprintf (f, " immutable\n");
01528             }
01529           else
01530             fprintf (f, " exposed\n");
01531           break;
01532         case SYMK_VAR:
01533 
01534           vi = (se->info).var;
01535           if (lco)
01536             {
01537               fprintf (f, "%%LCL");
01538             }
01539 
01540           if (!lco && !vi->export)
01541             {
01542               fprintf (f, "spec ");
01543             }
01544           switch (vi->kind)
01545             {
01546             case VRK_CONST:
01547               fprintf (f, "const %s %s\n",
01548                        ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01549               break;
01550             case VRK_VAR:
01551               fprintf (f, "var %s %s\n",
01552                        ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01553               break;
01554             case VRK_ENUM:
01555               fprintf (f, "enumConst %s %s\n",
01556                        ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01557               break;
01558             default:
01559               if (lco)
01560                 {
01561                   switch (vi->kind)
01562                     {
01563                     case VRK_GLOBAL:
01564                       fprintf (f, "global %s %s\n", ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01565                       break;
01566                     case VRK_PRIVATE:   /* for private vars within function */
01567                       fprintf (f, "local %s %s\n",
01568                                ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01569                       break;
01570                     case VRK_LET:
01571                       fprintf (f, "let %s %s\n",
01572                                ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01573                       break;
01574                     case VRK_PARAM:
01575                       fprintf (f, "param %s %s\n",
01576                                ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01577                       break;
01578                     case VRK_QUANT:
01579                       fprintf (f, "quant %s %s\n",
01580                                ltoken_getTextChars (vi->id), sort_getName (vi->sort));
01581                       break;
01582                     BADDEFAULT;
01583                     }
01584                   /*@=loopswitchbreak@*/
01585                   /*@=switchswitchbreak@*/
01586                 }
01587             }
01588         }
01589     }
01590 }
01591 
01592 static /*@exposed@*/ /*@out@*/ idTableEntry *
01593 nextFree (idTable * st)
01594 {
01595   idTableEntry *ret;
01596   unsigned int n = st->size;
01597 
01598   if (n >= st->allocated)
01599     {
01600       /*
01601       ** this loses with the garbage collector
01602       ** (and realloc is notoriously dangerous)
01603       **
01604       ** st->entries = (idTableEntry *) LSLMoreMem (st->entries, (n + DELTA) 
01605       **                                * sizeof (idTableEntry));
01606       **
01607       ** instead, we copy the symtable...
01608       */
01609       
01610       idTableEntry *oldentries = st->entries;
01611       unsigned int i;
01612       
01613       st->entries = dmalloc ((n+DELTA) * sizeof (*st->entries));
01614       
01615       for (i = 0; i < n; i++)
01616         {
01617           st->entries[i] = oldentries[i];
01618         }
01619       
01620       sfree (oldentries);
01621       
01622       st->allocated = n + DELTA;
01623     }
01624   
01625   ret = &(st->entries[st->size]);
01626   st->size++;
01627   return ret;
01628 }
01629 
01630 
01631 static /*@dependent@*/ /*@null@*/ idTableEntry *
01632   symtable_lookup (idTable *st, lsymbol id)
01633 {
01634   int n;
01635   idTableEntry *e;
01636 
01637   for (n = st->size - 1; n >= 0; n--)
01638     {
01639       e = &(st->entries[n]);
01640 
01641       /*@-loopswitchbreak@*/
01642       switch (e->kind)
01643         {
01644         case SYMK_SCOPE: 
01645           break;
01646         case SYMK_FCN:
01647           if (ltoken_getText (e->info.fct->id) == id) return e;
01648           break;
01649         case SYMK_TYPE:
01650           if (ltoken_getText (e->info.type->id) == id) return e;
01651           break;
01652         case SYMK_VAR:
01653           if (ltoken_getText (e->info.var->id) == id) return e;
01654           break;
01655         BADDEFAULT;
01656         }
01657       /*@=loopswitchbreak@*/
01658     }
01659 
01660   return (idTableEntry *) 0;
01661 }
01662 
01663 
01664 static /*@dependent@*/ /*@null@*/ idTableEntry *
01665   symtable_lookupInScope (idTable *st, lsymbol id)
01666 {
01667   int n;
01668   idTableEntry *e;
01669   for (n = st->size - 1; n >= 0; n--)
01670     {
01671       e = &(st->entries[n]);
01672       if (e->kind == SYMK_SCOPE)
01673         break;
01674       if (ltoken_getText (e->info.fct->id) == id)
01675         {
01676           return e;
01677         }
01678     }
01679   return (idTableEntry *) 0;
01680 }
01681 
01682 /* hash table implementation */
01683 
01684 static symbolKey
01685 htData_key (htData * x)
01686 {
01687   /* assume x points to a valid htData struct */
01688   switch (x->kind)
01689     {
01690     case IK_SORT:
01691       return x->content.sort;
01692     case IK_OP:
01693       {                         /* get the textSym of the token */
01694         nameNode n = (x->content.op)->name;
01695 
01696         if (n->isOpId)
01697           {
01698             return ltoken_getText (n->content.opid);
01699           }
01700         else
01701           {
01702             llassert (n->content.opform != NULL);
01703             return (n->content.opform)->key;
01704           }
01705       }
01706     case IK_TAG:
01707       return ltoken_getText ((x->content).tag->id);
01708     }
01709   BADEXIT;
01710 }
01711 
01712 static void htData_free (/*@null@*/ /*@only@*/ htData *d)
01713 {
01714   if (d != NULL)
01715     {
01716       switch (d->kind)
01717         {
01718         case IK_SORT:
01719           break;
01720         case IK_OP:
01721           /* nameNode_free (d->content.op->name);*/
01722           sigNodeSet_free (d->content.op->signatures);
01723           break;
01724         case IK_TAG:
01725           {
01726             switch (d->content.tag->kind)
01727               {
01728               case TAG_STRUCT:
01729               case TAG_UNION:
01730               case TAG_FWDSTRUCT:
01731               case TAG_FWDUNION:
01732                 /*
01733                  ** no: stDeclNodeList_free (d->content.tag->content.decls);
01734                  **     it is dependent!
01735                  */
01736                 /*@switchbreak@*/ break;
01737               case TAG_ENUM:
01738                 
01739                 /* no: ltokenList_free (d->content.tag->content.enums);
01740                  **     it is dependent!
01741                  */
01742                 
01743                 /*@switchbreak@*/ break;
01744               }
01745           }
01746         }
01747       
01748       sfree (d);
01749     }
01750 }
01751 
01752 static void bucket_free (/*@null@*/ /*@only@*/ bucket *b)
01753 {
01754   if (b != NULL)
01755     {
01756       bucket_free (b->next);
01757       htData_free (b->data);
01758       sfree (b);
01759     }
01760 }
01761 
01762 static void symHashTable_free (/*@only@*/ symHashTable *h)
01763 {
01764   unsigned int i;
01765 
01766   for (i = 0; i < h->size; i++)
01767     {
01768       bucket_free (h->buckets[i]);
01769     }
01770 
01771   sfree (h->buckets);
01772   sfree (h);
01773 }      
01774       
01775 static /*@only@*/ symHashTable *
01776 symHashTable_create (unsigned int size)
01777 {
01778   unsigned int i;
01779   symHashTable *t = (symHashTable *) dmalloc (sizeof (*t));
01780   
01781   t->buckets = (bucket **) dmalloc ((size + 1) * sizeof (*t->buckets));
01782   t->count = 0;
01783   t->size = size;
01784 
01785   for (i = 0; i <= size; i++)
01786     {
01787       t->buckets[i] = (bucket *) NULL;
01788     }
01789 
01790   return t;
01791 }
01792 
01793 static /*@null@*/ /*@exposed@*/ htData *
01794 symHashTable_get (symHashTable *t, symbolKey key, infoKind kind, /*@null@*/ nameNode n)
01795 {
01796   bucket *b;
01797   htEntry *entry;
01798   htData *d;
01799 
01800   b = t->buckets[MASH (key, kind)];
01801   if (b == (bucket *) 0)
01802     {
01803       return ((htData *) 0);
01804     }
01805   
01806   for (entry = (htEntry *) b; entry != NULL; entry = entry->next)
01807     {
01808       d = entry->data;
01809 
01810       if (d->kind == kind && htData_key (d) == key)
01811         if (kind != IK_OP || sameNameNode (n, d->content.op->name))
01812           {
01813             return d;
01814           }
01815     }
01816   return ((htData *) 0);
01817 }
01818 
01819 static bool
01820 symHashTable_put (symHashTable *t, /*@only@*/ htData *data)
01821 {
01822   /* if key is already taken, don't insert, return FALSE
01823      else insert it and return TRUE. */
01824   symbolKey key;
01825   htData *oldd;
01826   infoKind kind;
01827   nameNode name;
01828 
01829   key = htData_key (data);
01830   kind = data->kind;
01831 
01832   if (kind == IK_OP && (!data->content.op->name->isOpId))
01833     {
01834       name = data->content.op->name;
01835     }
01836   else
01837     {
01838       name = (nameNode) 0;
01839     }
01840   
01841   oldd = symHashTable_get (t, key, kind, name);
01842 
01843   if (oldd == (htData *) 0)
01844     {
01845       /*@-deparrays@*/
01846       bucket *new_entry = (bucket *) dmalloc (sizeof (*new_entry));
01847       bucket *b = (t->buckets[MASH (key, kind)]);
01848       htEntry *entry = (htEntry *) b;
01849       /*@=deparrays@*/
01850 
01851       new_entry->data = data;
01852       new_entry->next = entry;
01853       t->buckets[MASH (key, kind)] = new_entry;
01854       t->count++;
01855 
01856       return TRUE;
01857     }
01858   else
01859     {
01860       htData_free (data);
01861     }
01862 
01863   return FALSE;
01864 }
01865 
01866 static /*@only@*/ /*@exposed@*/ /*@null@*/ htData *
01867   symHashTable_forcePut (symHashTable *t, /*@only@*/ htData *data)
01868 {
01869   /* Put data in, return old value */
01870   symbolKey key;
01871   bucket *b;
01872   htData *oldd;
01873   htEntry *entry, *new_entry;
01874   infoKind kind;
01875   nameNode name;
01876 
01877   key = htData_key (data);
01878   kind = data->kind;
01879 
01880   if (kind == IK_OP && (!data->content.op->name->isOpId))
01881     {
01882       name = data->content.op->name;
01883     }
01884   else
01885     {
01886       name = (nameNode) 0;
01887     }
01888 
01889   oldd = symHashTable_get (t, key, kind, name);
01890 
01891   if (oldd == (htData *) 0)
01892     {
01893       new_entry = (htEntry *) dmalloc (sizeof (*new_entry));
01894 
01895       /*@-deparrays@*/
01896       b = t->buckets[MASH (key, kind)];
01897       /*@=deparrays@*/
01898 
01899       entry = b;
01900       new_entry->data = data;
01901       new_entry->next = entry;
01902       t->buckets[MASH (key, kind)] = new_entry;
01903       t->count++;
01904 
01905       return NULL;
01906     }
01907   else
01908     {                           /* modify in place */
01909       *oldd = *data;            /* copy new info over to old info */
01910 
01911       /* dangerous: if the data is the same, don't free it */
01912       if (data != oldd)   
01913         {
01914           sfree (data); 
01915         /*@-branchstate@*/ 
01916         } 
01917       /*@=branchstate@*/
01918 
01919       return oldd;
01920     }
01921 }
01922 
01923 #if 0
01924 static unsigned int
01925 symHashTable_count (symHashTable * t)
01926 {
01927   return (t->count);
01928 }
01929 
01930 #endif
01931 
01932 static void
01933 symHashTable_printStats (symHashTable * t)
01934 {
01935   int i, bucketCount, setsize, sortCount, opCount, tagCount;
01936   int sortTotal, opTotal, tagTotal;
01937   bucket *b;
01938   htEntry *entry;
01939   htData *d;
01940 
01941   sortTotal = 0;
01942   opTotal = 0;
01943   tagTotal = 0;
01944   sortCount = 0;
01945   opCount = 0;
01946   tagCount = 0;
01947 
01948   /* for debugging only */
01949   printf ("\n Printing symHashTable stats ... \n");
01950   for (i = 0; i <= HT_MAXINDEX; i++)
01951     {
01952       b = t->buckets[i];
01953       bucketCount = 0;
01954       for (entry = b; entry != NULL; entry = entry->next)
01955         {
01956           d = entry->data;
01957           bucketCount++;
01958           switch (d->kind)
01959             {
01960             case IK_SORT:
01961               sortCount++;
01962               /*@switchbreak@*/ break;
01963             case IK_OP:
01964               {
01965                 cstring name = nameNode_unparse (d->content.op->name);
01966                 cstring sigs = sigNodeSet_unparse (d->content.op->signatures);
01967                 opCount++;
01968                 /* had a tt? */
01969                 setsize = sigNodeSet_size (d->content.op->signatures);
01970                 printf ("       Op (%d): %s %s\n", setsize, 
01971                         cstring_toCharsSafe (name), 
01972                         cstring_toCharsSafe (sigs));
01973                 cstring_free (name);
01974                 cstring_free (sigs);
01975                 /*@switchbreak@*/ break;
01976               }
01977             case IK_TAG:
01978               tagCount++;
01979               /*@switchbreak@*/ break;
01980             }
01981         }
01982       if (bucketCount > 0)
01983         {
01984           printf ("   Bucket %d has count = %d; opCount = %d; sortCount = %d; tagCount = %d\n", i, bucketCount, opCount, sortCount, tagCount);
01985           sortTotal += sortCount;
01986           tagTotal += tagCount;
01987           opTotal += opCount;
01988         }
01989     }
01990   printf ("SymHashTable has total count = %d, opTotal = %d, sortTotal = %d, tagTotal = %d :\n", t->count, opTotal, sortTotal, tagTotal);
01991 
01992 }
01993 
01994 void
01995 symtable_printStats (symtable s)
01996 {
01997   symHashTable_printStats (s->hTable);
01998  /* for debugging only */
01999   printf ("idTable size = %d; allocated = %d\n",
02000           s->idTable->size, s->idTable->allocated);
02001 }
02002 
02003 /*@only@*/ cstring
02004 tagKind_unparse (tagKind k)
02005 {
02006   switch (k)
02007     {
02008     case TAG_STRUCT:
02009     case TAG_FWDSTRUCT:
02010       return cstring_makeLiteral ("struct");
02011     case TAG_UNION:
02012     case TAG_FWDUNION:
02013       return cstring_makeLiteral ("union");
02014     case TAG_ENUM:
02015       return cstring_makeLiteral ("enum");
02016     }
02017   BADEXIT;
02018 }
02019 
02020 static void tagInfo_free (/*@only@*/ tagInfo tag)
02021 {
02022   sfree (tag);
02023 }
02024 
02025 /*@observer@*/ sigNodeSet 
02026   symtable_possibleOps (symtable tab, nameNode n)
02027 {
02028   opInfo oi = symtable_opInfo (tab, n);
02029   
02030   if (opInfo_exists (oi))
02031     {
02032       return (oi->signatures);
02033     }
02034 
02035   return sigNodeSet_undefined;
02036 }
02037 
02038 bool
02039 symtable_opExistsWithArity (symtable tab, nameNode n, int arity)
02040 {
02041   opInfo oi = symtable_opInfo (tab, n);
02042 
02043   if (opInfo_exists (oi))
02044     {
02045       sigNodeSet sigs = oi->signatures;
02046       sigNodeSet_elements (sigs, sig)
02047       {
02048         if (ltokenList_size (sig->domain) == arity)
02049           return TRUE;
02050       } end_sigNodeSet_elements;
02051     }
02052   return FALSE;
02053 }
02054 
02055 static bool
02056 domainMatches (ltokenList domain, sortSetList argSorts)
02057 {
02058   /* expect their length to match */
02059   /* each domain sort in op must be an element of
02060      the corresponding set in argSorts. */
02061   bool matched = TRUE;
02062   sort s;
02063 
02064   sortSetList_reset (argSorts);
02065   ltokenList_elements (domain, dom)
02066     {
02067       s = sort_fromLsymbol (ltoken_getText (dom));
02068       if (!(sortSet_member (sortSetList_current (argSorts), s)))
02069         {
02070           /*      printf ("   mismatched element is: %s in %s\n", ltoken_getTextChars (*dom),
02071                   sortSet_unparse (sortSetList_current (argSorts))); */
02072           matched = FALSE;
02073           break;
02074         }
02075       sortSetList_advance (argSorts);
02076   } end_ltokenList_elements;
02077 
02078   return matched;
02079 }
02080 
02081 /*@only@*/ lslOpSet
02082   symtable_opsWithLegalDomain (symtable tab, /*@temp@*/ /*@null@*/ nameNode n,
02083                                sortSetList argSorts, sort qual)
02084 {
02085  /* handles nil qual */
02086   lslOpSet ops = lslOpSet_new ();
02087   lslOp op;
02088   sort rangeSort;
02089   opInfo oi;
02090 
02091   llassert (n != NULL);
02092   oi = symtable_opInfo (tab, n);
02093 
02094   if (opInfo_exists (oi))
02095     {
02096       sigNodeSet sigs = oi->signatures;
02097 
02098       sigNodeSet_elements (sigs, sig)
02099         {
02100           if (ltokenList_size (sig->domain) == sortSetList_size (argSorts))
02101             {
02102               rangeSort = sigNode_rangeSort (sig);
02103               
02104               if ((qual == 0) || (sort_equal (&rangeSort, &qual)))
02105                 {
02106                   if (domainMatches (sig->domain, argSorts))
02107                     {
02108                       op = (lslOp) dmalloc (sizeof (*op));
02109                       
02110                       /* each domain sort in op must be an element of
02111                          the corresponding set in argSorts. */
02112                       op->signature = sig;
02113                       op->name = nameNode_copy (n);
02114                       (void) lslOpSet_insert (ops, op);
02115                     }
02116                 }
02117             }
02118         } end_sigNodeSet_elements;
02119     }
02120   return ops;
02121 }

Generated at Fri Nov 3 18:57:45 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000