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

sort.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 ** sort.c
00026 **
00027 ** sort abstraction
00028 **
00029 **      NOTE: The structure of this module follows a similar one
00030 **            used in the previous LCL checker.  However, all other
00031 **            details are quite different.
00032 **
00033 **  AUTHOR:
00034 **      Yang Meng Tan,
00035 **         Massachusetts Institute of Technology
00036 */
00037 
00038 # include "lclintMacros.nf"
00039 # include "llbasic.h"
00040 # include "llgrammar.h"
00041 # include "lclscan.h"
00042 
00043 /*@+ignorequals@*/
00044 
00045 static lsymbol newStructTag (void) /*@*/ ;
00046 static lsymbol newEnumTag (void) /*@*/ ;
00047 static lsymbol newUnionTag (void) /*@*/ ;
00048 
00049 /*@constant static int MAXBUFFLEN; @*/
00050 # define MAXBUFFLEN 1024
00051 
00052 /*@constant static int DELTA; @*/
00053 # define DELTA 100
00054 
00055 /*@constant static int NOSORTHANDLE; @*/
00056 # define NOSORTHANDLE 0
00057 
00058 /*@constant static int HOFSORTHANDLE; @*/
00059 # define HOFSORTHANDLE 1
00060 
00061 /* local routines */
00062 
00063 static void sort_addTupleMembers (sort p_tupleSort, sort p_strSort)  
00064    /*@modifies internalState@*/ ;
00065 
00066 static bool sort_isNewEntry (sortNode p_s) /*@*/ ;  
00067 
00068 static sort sort_enterNew (/*@special@*/ sortNode p_s) 
00069    /*@uses p_s.kind, p_s.name, p_s.members@*/
00070    /*@releases p_s.members@*/
00071    /*@modifies internalState@*/ ;
00072 
00073 static sort sort_enterGlobal (sortNode p_s) /*@modifies internalState@*/ ;
00074 
00075 static sort sort_enterNewForce (/*@special@*/ sortNode p_s) 
00076    /*@uses p_s.kind, p_s.name, p_s.members@*/
00077    /*@releases p_s.members@*/
00078    /*@modifies internalState@*/ ;
00079 
00080 static void genPtrOps (sort p_baseSort, sort p_ptrSort, sort p_arraySort);
00081 static void genArrOps (sort p_baseSort, sort p_arraySort, int p_dim,
00082                        sort p_vecSort);
00083 static void genVecOps (sort p_baseSort, sort p_vecSort, int p_dim);
00084 static void genTupleOps (sort p_tupleSort);
00085 static void genUnionOps (sort p_tupleSort);
00086 static void genStrOps (sort p_strSort, sort p_tupleSort);
00087 static void genEnumOps (sort p_enumSort);
00088 
00089 static void overloadPtrFcns (sort p_ptrSort);
00090 static void overloadIsSub (sort p_s, int p_dim);
00091 static void overloadSizeof (sort p_domainSort);
00092 
00093 /*@observer@*/ static cstring sort_unparseKind (sortKind p_k) /*@*/ ;
00094 
00095 static /*@observer@*/ cstring
00096   sort_unparseKindName (sortNode p_s) /*@*/ ;
00097 
00098 static lsymbol
00099   sortTag_toSymbol (char *p_kind, ltoken p_tagid, /*@out@*/ bool *p_isNew);
00100 
00101 static void 
00102   overloadUnaryTok (/*@only@*/ nameNode p_nn, 
00103                     sort p_domainSort, /*@only@*/ ltoken p_range);
00104 static void 
00105   overloadUnary (/*@only@*/ nameNode p_nn, 
00106                  sort p_domainSort, sort p_rangeSort);
00107 static void 
00108   overloadBinary (/*@only@*/ nameNode p_nn, 
00109                   sort p_s, /*@only@*/ ltoken p_dTok, sort p_rs);
00110 static /*@only@*/ nameNode makeFieldOp (lsymbol p_field);
00111 static /*@only@*/ nameNode makeArrowFieldOp (lsymbol p_field);
00112 
00113 # undef sp
00114 static lsymbol sp (lsymbol p_s1, lsymbol p_s2);
00115 static void sortError (ltoken p_t, sort p_oldsort, sortNode p_newnode);
00116 
00117 /*@-namechecks@*/
00118 sort sort_bool;
00119 sort sort_capBool;
00120 sort sort_int;
00121 sort sort_char;
00122 sort sort_float;
00123 sort sort_double;
00124 sort sort_cstring;
00125 /*@=namechecks@*/
00126 
00127 static sort sort_void;
00128 static sort char_obj_ptrSort;
00129 static sort char_obj_ArrSort;
00130 
00131 /* This is used to uniqueize sort names, for anonymous C types */
00132 static int sortUID = 1;
00133 
00134 static /*@only@*/ /*@null@*/ sortNode *sortTable = (sortNode *) 0;
00135 static int sortTableSize = 0;
00136 static int sortTableAlloc = 0;
00137 
00138 /* Important to keep sorts in some order because importing routines
00139 for sorts rely on this order to ensure that when we encounter a sort
00140 S1 that is based on sort S2, S2 is before S1 in the imported file. */
00141 
00142 static bool exporting = TRUE;
00143 
00144 static lsymbol underscoreSymbol;
00145 static /*@only@*/ ltoken intToken;
00146 
00147 static /*@owned@*/ nameNode arrayRefNameNode;
00148 static /*@owned@*/ nameNode ptr2arrayNameNode;
00149 static /*@owned@*/ nameNode deRefNameNode;
00150 static /*@owned@*/ nameNode nilNameNode;
00151 static /*@owned@*/ nameNode plusNameNode;
00152 static /*@owned@*/ nameNode minusNameNode;
00153 static /*@owned@*/ nameNode condNameNode;
00154 static /*@owned@*/ nameNode eqNameNode;
00155 static /*@owned@*/ nameNode neqNameNode;
00156 
00157 static sortNode noSort;
00158 
00159 static sortNode HOFSort =
00160 { 
00161   SRT_HOF, 
00162   HOFSORTHANDLE,
00163   lsymbol_undefined,
00164   lsymbol_undefined,
00165   FALSE, /* was lsymbolNULL */
00166   NOSORTHANDLE,
00167   NOSORTHANDLE,
00168   smemberInfo_undefined,
00169   FALSE,
00170   FALSE,
00171   FALSE, 
00172   FALSE
00173 };
00174 
00175 static ob_mstring sortKindName[] =
00176 {
00177   "FIRSTSORT", "NOSORT", "HOFSORT",
00178   "PRIMITIVE", "SYNONYM", "POINTER", "OBJ", "ARRAY", "VECTOR",
00179   "STRUCT", "TUPLE", "UNION", "UNIONVAL", "ENUM", "LASTSORT"
00180 } ;
00181 
00182 static void smemberInfo_free (/*@null@*/ /*@only@*/ smemberInfo *mem)
00183 {
00184   sfree (mem);
00185 }
00186 
00187 static void sortNode_free (/*@special@*/ sortNode sn)
00188    /*@uses sn.members@*/
00189    /*@releases sn.members@*/
00190 {
00191   smemberInfo_free (sn.members);
00192 }
00193 
00194 void
00195 sort_destroyMod (void)
00196    /*@globals killed sortTable, killed arrayRefNameNode,
00197               killed ptr2arrayNameNode,killed deRefNameNode,
00198               killed nilNameNode, killed plusNameNode,
00199               killed minusNameNode, killed condNameNode,
00200               killed eqNameNode, killed neqNameNode @*/
00201 {
00202   if (sortTable != NULL)  
00203     {
00204       int i;
00205 
00206       for (i = 0; i < sortTableSize; i++)
00207         {
00208           sortNode_free (sortTable[i]);
00209         }
00210 
00211       nameNode_free (arrayRefNameNode);
00212       nameNode_free (ptr2arrayNameNode);
00213       nameNode_free (deRefNameNode);
00214       nameNode_free (nilNameNode);
00215       nameNode_free (plusNameNode);
00216       nameNode_free (minusNameNode);
00217       nameNode_free (condNameNode);
00218       nameNode_free (eqNameNode);
00219       nameNode_free (neqNameNode);
00220 
00221       sfree (sortTable);
00222       /*@-branchstate@*/
00223     }
00224 } /*@=branchstate@*/
00225 
00226 sort
00227 sort_makeNoSort (void)
00228 {
00229   return NOSORTHANDLE;
00230 }
00231 
00232 sort
00233 sort_makeHOFSort (sort base)
00234 {
00235   sortNode outSort;
00236   sort handle;
00237 
00238   outSort.kind = SRT_HOF;
00239   outSort.name = cstring_toSymbol (message ("_HOF_sort_%d", sortTableSize));
00240   outSort.tag = lsymbol_undefined;
00241   outSort.baseSort = base;
00242   outSort.objSort = NOSORTHANDLE;
00243   outSort.members = smemberInfo_undefined;
00244   outSort.export = exporting;
00245   outSort.imported = context_inImport ();
00246   outSort.mutable = FALSE;
00247   outSort.abstract = FALSE;
00248 
00249   llassert (sortTable != NULL);
00250 
00251   outSort.handle = handle = sortTableSize;
00252   sortTable[handle] = outSort;
00253 
00254   sortTableSize++;
00255   return handle;
00256 }
00257 
00258 static sort
00259 sort_construct (lsymbol name, sortKind kind, sort baseSort,
00260                 lsymbol tagName,
00261                 bool mut, sort objSort, /*@null@*/ smemberInfo *members)
00262 {
00263   sortNode outSort;
00264   sort handle;
00265 
00266   handle = sort_lookupName (name);
00267 
00268   outSort.kind = kind;
00269   outSort.name = name;
00270   outSort.tag = tagName;
00271   outSort.realtag = TRUE; 
00272   outSort.baseSort = baseSort;
00273   outSort.objSort = objSort;
00274   outSort.members = members;
00275   outSort.mutable = mut;
00276   outSort.export = exporting;
00277   outSort.imported = context_inImport ();
00278   outSort.abstract = FALSE;
00279   outSort.handle = handle;
00280 
00281   if (handle == NOSORTHANDLE)
00282     {
00283       outSort.handle = handle = sort_enterNew (outSort);
00284       return handle;
00285     }
00286   else
00287     {
00288       llassert (sortTable != NULL);
00289 
00290       if (sortTable[handle].kind != kind)
00291         {
00292           sortError (ltoken_undefined, handle, outSort);
00293           smemberInfo_free (outSort.members);
00294 
00295           return handle;
00296         }
00297       else
00298         {
00299           /* evs --- added 11 Mar 1994
00300           ** the new entry should supercede the old one, since
00301           ** it could be a forward reference to a struct, etc.
00302           */
00303 
00304           sortTable[handle] = outSort;
00305           return handle;
00306         }
00307     }
00308 }
00309 
00310 static sort
00311   sort_constructAbstract (lsymbol name, bool mut, sort baseSort)
00312 {
00313   sortNode outSort;
00314   sortKind kind;
00315   sort handle;
00316 
00317   if (mut)
00318     kind = SRT_OBJ;
00319   else
00320     kind = SRT_PRIM;
00321 
00322   handle = sort_lookupName (name);
00323   outSort.kind = kind;
00324   outSort.name = name;
00325   outSort.tag = lsymbol_undefined;
00326   outSort.baseSort = baseSort;
00327   outSort.objSort = NOSORTHANDLE;
00328   outSort.members = smemberInfo_undefined;
00329   outSort.mutable = mut;
00330   outSort.export = exporting;
00331   outSort.imported = context_inImport ();
00332   outSort.abstract = TRUE;
00333   outSort.handle = handle;
00334 
00335   if (handle == NOSORTHANDLE)
00336     {
00337       outSort.handle = handle = sort_enterNew (outSort);
00338       /* do not make sort operators. */
00339     }
00340   else
00341     {
00342       llassert (sortTable != NULL);
00343 
00344       if (sortTable[handle].kind != kind)
00345         {
00346           sortError (ltoken_undefined, handle, outSort);
00347         }
00348 
00349       smemberInfo_free (outSort.members);
00350     }
00351 
00352   return handle;
00353 }
00354 
00355 sort
00356 sort_makeSort (/*@unused@*/ ltoken t, lsymbol n)
00357 {
00358   /*
00359   ** Expects n to be a new sort.
00360   ** Generate a sort with the given name.  Useful for LSL sorts. 
00361   */
00362 
00363   sort handle = sort_lookupName (n);
00364 
00365   if (handle == NOSORTHANDLE)
00366     {
00367       sortNode outSort;
00368 
00369       outSort.handle = handle;      
00370       outSort.kind = SRT_PRIM;
00371       outSort.name = n;
00372       outSort.tag = lsymbol_undefined;
00373       outSort.baseSort = NOSORTHANDLE;
00374       outSort.objSort = NOSORTHANDLE;
00375       outSort.members = smemberInfo_undefined;
00376       outSort.export = exporting;
00377       outSort.mutable = FALSE;
00378       outSort.imported = context_inImport ();
00379       outSort.abstract = FALSE;
00380 
00381       /* Put into sort table, sort_enter checks for duplicates. */
00382       outSort.handle = handle = sort_enterNew (outSort);
00383     }
00384   else
00385     {
00386       /* don't override old info */
00387      ;
00388     }
00389 
00390   return handle;
00391 }
00392 
00393 static sort
00394 sort_makeSortNoOps (/*@unused@*/ ltoken t, lsymbol n) /*@modifies internalState@*/ 
00395 {
00396   sort handle;
00397   
00398   handle = sort_lookupName (n);
00399 
00400   if (handle == NOSORTHANDLE)
00401     {
00402       sortNode outSort;
00403 
00404       outSort.handle = handle;
00405       outSort.kind = SRT_PRIM;
00406       outSort.name = n;
00407       outSort.tag = lsymbol_undefined;
00408       outSort.baseSort = NOSORTHANDLE;
00409       outSort.objSort = NOSORTHANDLE;
00410       outSort.members = smemberInfo_undefined;
00411       outSort.export = exporting;
00412       outSort.mutable = FALSE;
00413       outSort.imported = context_inImport ();
00414       outSort.abstract = FALSE;
00415       /* Put into sort table, sort_enter checks for duplicates. */
00416       outSort.handle = handle = sort_enterNew (outSort);
00417     }                           /* don't override old info */
00418 
00419   return handle;
00420 }
00421 
00422 static sort
00423 sort_makeLiteralSort (ltoken t, lsymbol n) 
00424    /*@modifies internalState@*/
00425 {
00426   /*
00427   ** Like sort_makeSort, in addition, generate sizeof operator 
00428   ** t not currently used, may be useful for generating error msgs later 
00429   ** Also useful for abstract types, need sizeof operator.
00430   */
00431 
00432   sort handle = sort_makeSort (t, n);
00433 
00434   overloadSizeof (handle);
00435   return handle;
00436 }
00437 
00438 sort
00439 sort_makeSyn (ltoken t, sort s, lsymbol n)
00440 {
00441   /* make a synonym sort with name n that is == to sort s */
00442   /* expect n to be a new sort name */
00443   sortNode outSort;
00444   sort handle;
00445   /* must not clash with any LSL sorts */
00446   lsymbol newname = sp (underscoreSymbol, n);
00447   
00448   if (n == lsymbol_undefined)
00449     {
00450       llbuglit ("sort_makeSyn: synonym must have name");
00451     }
00452 
00453   handle = sort_lookupName (newname);
00454 
00455   outSort.kind = SRT_SYN;
00456   outSort.name = newname;
00457   outSort.baseSort = s;
00458   outSort.objSort = NOSORTHANDLE;
00459   /* info is not duplicated */
00460   outSort.tag = lsymbol_undefined;
00461   outSort.members = smemberInfo_undefined;
00462   outSort.export = exporting;
00463   outSort.mutable = FALSE;
00464   outSort.imported = context_inImport ();
00465   outSort.abstract = FALSE;
00466   outSort.handle = handle;
00467 
00468   if (handle == NOSORTHANDLE)
00469     {
00470       outSort.handle = handle = sort_enterNew (outSort);
00471       /* No operators to generate for synonyms */
00472     }
00473   else
00474     {
00475       llassert (sortTable != NULL);
00476       
00477       if (sortTable[handle].kind != SRT_SYN)
00478         {
00479           sortError (t, handle, outSort);
00480         }
00481 
00482       smemberInfo_free (outSort.members);
00483     }
00484 
00485   return handle;
00486 }
00487 
00488 sort
00489 sort_makeFormal (sort insort)
00490 {
00491   sortNode s;
00492   sort sor, handle;
00493 
00494   sor = sort_getUnderlying (insort);
00495   handle = sor;
00496   s = sort_lookup (sor);
00497 
00498   switch (s.kind)
00499     {
00500     case SRT_STRUCT:
00501       handle = sort_makeTuple (ltoken_undefined, sor);
00502       break;
00503     case SRT_UNION:
00504       handle = sort_makeUnionVal (ltoken_undefined, sor);
00505       break;
00506     default:
00507       break;
00508     }
00509 
00510   return handle;
00511 }
00512 
00513 sort
00514 sort_makeGlobal (sort insort)
00515 {
00516   /* Make a Obj if not an array or a struct */
00517   sortNode s;
00518   sort sor, handle;
00519   sor = sort_getUnderlying (insort);
00520   handle = sor;
00521   s = sort_lookup (sor);
00522 
00523   switch (s.kind)
00524     {
00525     case SRT_ARRAY:
00526     case SRT_STRUCT:
00527     case SRT_UNION:
00528     case SRT_HOF:
00529     case SRT_NONE:
00530       break;
00531     case SRT_VECTOR:
00532     case SRT_TUPLE:
00533     case SRT_UNIONVAL:
00534       llcontbuglit ("sort_makeGlobal: can't make vectors, tuples, or unionvals global");
00535       break;
00536     default:
00537       handle = sort_makeObj (sor);
00538       break;
00539     }
00540   return handle;
00541 }
00542 
00543 sort
00544 sort_makeObj (sort sor)
00545 {
00546   sortNode baseSortNode, outSort;
00547   sort baseSort, handle;
00548   lsymbol name;
00549 
00550  /* skip the synonym sort */
00551   baseSort = sort_getUnderlying (sor);
00552   baseSortNode = sort_quietLookup (baseSort);
00553   switch (baseSortNode.kind)
00554     {
00555     case SRT_HOF:
00556     case SRT_NONE:
00557       return baseSort;
00558     case SRT_VECTOR:
00559       if (baseSortNode.objSort != 0)
00560         return baseSortNode.objSort;
00561       else                      /* must have well-defined objSort field */
00562         {
00563           llcontbuglit ("sort_makeObj: Inconsistent vector reps:invalid objSort field");
00564           return baseSort;
00565         }
00566     case SRT_TUPLE:
00567     case SRT_UNIONVAL:
00568      /* need to map *_Struct_Tuple to *_Struct and *_Union_UnionVal to
00569       *_Union, according to sort naming conventions */
00570       if (baseSortNode.baseSort != NOSORTHANDLE)
00571        /* for tuples and unionvals, baseSort field keeps the map from
00572           value sort to obj sort. */
00573         return baseSortNode.baseSort;
00574       else                      /* valid tuples and unionvals must have baseSort fields */
00575         {
00576           llcontbuglit ("sort_makeObj: Inconsistent tuples or unionvals reps: invalid baseSort field");
00577           return baseSort;
00578         }
00579     default:
00580       name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
00581                  lsymbol_fromChars ("_Obj"));
00582       handle = sort_lookupName (name);
00583 
00584       outSort.kind = SRT_OBJ;
00585       /* must not clash with any LSL sorts */
00586       outSort.name = name;
00587       outSort.tag = lsymbol_undefined;
00588       outSort.baseSort = baseSort;
00589       outSort.objSort = NOSORTHANDLE;
00590       outSort.members = smemberInfo_undefined;
00591       outSort.mutable = TRUE;
00592       outSort.export = exporting;
00593       outSort.abstract = FALSE;
00594       outSort.handle = handle;
00595       outSort.imported = TRUE;
00596 
00597       if (handle == NOSORTHANDLE)
00598         {
00599           if (sort_isNewEntry (outSort))
00600             {
00601               outSort.handle = handle = sort_enterNew (outSort);
00602             }
00603           else
00604             {
00605               outSort.handle = handle = sort_enterNew (outSort);
00606             }
00607         }
00608       else
00609         {
00610           llassert (sortTable != NULL);
00611 
00612           if (sortTable[handle].kind != SRT_OBJ)
00613             {
00614               sortError (ltoken_undefined, handle, outSort);
00615             }
00616 
00617           smemberInfo_free (outSort.members);
00618         }
00619 
00620       return handle;
00621     }
00622 }
00623 
00624 sort
00625 sort_makePtr (ltoken t, sort baseSort)
00626 {
00627   sortNode s, outSort;
00628   sort handle, arrayHandle;
00629   lsymbol name;
00630 
00631   s = sort_lookup (baseSort);
00632 
00633   if (s.kind == SRT_HOF)
00634     {
00635       return baseSort;
00636     }
00637   if (s.kind == SRT_NONE)
00638     {
00639       return baseSort;
00640     }
00641 
00642   if (s.kind != SRT_ARRAY && s.kind != SRT_STRUCT &&
00643       s.kind != SRT_UNION)
00644     /* && s.kind != SRT_OBJ) */
00645     /* base is not an SRT_ARRAY, struct or union.  Need to insert a obj. */
00646     baseSort = sort_makeObj (baseSort);
00647   
00648   name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
00649              lsymbol_fromChars ("_Ptr"));
00650   handle = sort_lookupName (name);
00651   
00652   outSort.kind = SRT_PTR;
00653   outSort.name = name;
00654   outSort.tag = lsymbol_undefined;
00655   outSort.baseSort = baseSort;
00656   outSort.objSort = NOSORTHANDLE;
00657   outSort.members = smemberInfo_undefined;
00658   outSort.mutable = FALSE;
00659   outSort.export = exporting;
00660   outSort.imported = context_inImport ();
00661   outSort.abstract = FALSE;
00662   outSort.handle = handle;
00663   
00664   if (handle == NOSORTHANDLE)
00665     {
00666       if (sort_isNewEntry (outSort))
00667         {
00668           outSort.handle = handle = sort_enterNew (outSort);
00669           arrayHandle = sort_makeArr (t, baseSort);
00670           genPtrOps (baseSort, handle, arrayHandle);
00671         }
00672       else
00673         {
00674           outSort.handle = handle = sort_enterNew (outSort);
00675         }
00676     }
00677   else
00678     {
00679       llassert (sortTable != NULL);
00680 
00681       if (sortTable[handle].kind != SRT_PTR)
00682         {
00683           sortError (t, handle, outSort);
00684         }
00685       smemberInfo_free (outSort.members);
00686     }
00687   return handle;
00688 }
00689 
00690 sort
00691 sort_makePtrN (sort s, int pointers)
00692 {
00693   llassert (pointers >= 0);
00694 
00695   if (pointers == 0)
00696     {
00697       return s;
00698     }
00699   else
00700     {
00701       return sort_makePtrN (sort_makePtr (ltoken_undefined, s), 
00702                             pointers - 1);
00703     }
00704 }
00705 
00706 sort
00707 sort_makeArr (ltoken t, sort baseSort)
00708 {
00709   sortNode s, outSort, old;
00710   sort handle, vecHandle;
00711   int dim;
00712   lsymbol name;
00713 
00714   s = sort_lookup (baseSort);
00715 
00716   if (s.kind == SRT_HOF)
00717     return baseSort;
00718   if (s.kind == SRT_NONE)
00719     return baseSort;
00720 
00721   if (s.kind != SRT_ARRAY && s.kind != SRT_STRUCT &&
00722       s.kind != SRT_UNION && s.kind != SRT_OBJ)
00723    /* base is not an array, struct or obj.  Need to insert a Obj. */
00724     baseSort = sort_makeObj (baseSort);
00725 
00726   name = sp (sp (underscoreSymbol, sort_getLsymbol (baseSort)),
00727              lsymbol_fromChars ("_Arr"));
00728   handle = sort_lookupName (name);
00729 
00730  /* must not clash with any LSL sorts */
00731   outSort.name = name;
00732   outSort.kind = SRT_ARRAY;
00733   outSort.baseSort = baseSort;
00734   outSort.objSort = NOSORTHANDLE;
00735   outSort.members = smemberInfo_undefined;
00736   outSort.mutable = TRUE;
00737   outSort.export = exporting;
00738   outSort.imported = context_inImport ();
00739   outSort.abstract = FALSE;
00740   outSort.handle = handle;
00741   
00742   if (handle == NOSORTHANDLE)
00743     {
00744       if (sort_isNewEntry (outSort))
00745         {
00746           outSort.handle = handle = sort_enterNew (outSort);
00747 
00748           for (old = outSort, dim = 0;
00749                old.kind == SRT_ARRAY;
00750                dim++, old = sort_lookup (old.baseSort))
00751             {
00752               ;
00753             }
00754 
00755           vecHandle = sort_makeVec (t, handle);
00756           genArrOps (baseSort, handle, dim, vecHandle);
00757         }
00758       else
00759         {
00760           outSort.handle = handle = sort_enterNew (outSort);
00761         }
00762     }
00763   else
00764     {
00765       llassert (sortTable != NULL);
00766 
00767       if (sortTable[handle].kind != SRT_ARRAY)
00768         {
00769           sortError (t, handle, outSort);
00770         }
00771 
00772       smemberInfo_free (outSort.members);
00773     }
00774 
00775   return handle;
00776 }
00777 
00778 sort
00779 sort_makeVec (ltoken t, sort arraySort)
00780 {
00781   sortNode s, outSort, old;
00782   sort baseSort, handle, elementSort;
00783   int dim;                      /* array dimension count. */
00784   lsymbol name;
00785 
00786   s = sort_lookup (arraySort);
00787 
00788   if (s.kind == SRT_HOF)
00789     return arraySort;
00790   if (s.kind == SRT_NONE)
00791     return arraySort;
00792 
00793   if (s.kind != SRT_ARRAY)
00794     {
00795       llbug (message ("sort_makeVec: only arrays can become vectors: given sort is %s",
00796                       sort_unparseKind (s.kind)));
00797     }
00798 
00799   if (s.baseSort == NOSORTHANDLE)
00800     llbuglit ("sort_makeVec: arrays must have base (element) sort");
00801 
00802  /* Vectors return "values", so make array elements values. */
00803 
00804   baseSort = s.baseSort;
00805   elementSort = sort_makeVal (baseSort);
00806 
00807   name = sp (sp (underscoreSymbol, sort_getLsymbol (elementSort)),
00808              lsymbol_fromChars ("_Vec"));
00809   handle = sort_lookupName (name);
00810 
00811   outSort.baseSort = elementSort;
00812   outSort.name = name;
00813   outSort.objSort = arraySort;
00814   outSort.kind = SRT_VECTOR;
00815   outSort.members = smemberInfo_undefined;
00816   outSort.mutable = FALSE;
00817   outSort.export = exporting;
00818   outSort.imported = context_inImport ();
00819   outSort.abstract = FALSE;
00820   outSort.handle = handle;
00821 
00822   if (handle == NOSORTHANDLE)
00823     {
00824       if (sort_isNewEntry (outSort))
00825         {
00826           outSort.handle = handle = sort_enterNew (outSort);
00827 
00828           for (old = outSort, dim = 0;
00829                old.kind == SRT_VECTOR;
00830                dim++, old = sort_lookup (old.baseSort))
00831             {
00832               ;
00833             }
00834 
00835           genVecOps (elementSort, handle, dim);
00836         }
00837       else
00838         {
00839           outSort.handle = handle = sort_enterNew (outSort);
00840         }
00841     }
00842   else
00843     {
00844       llassert (sortTable != NULL);
00845 
00846       if (sortTable[handle].kind != SRT_VECTOR)
00847         {
00848           sortError (t, handle, outSort);
00849         }
00850 
00851       smemberInfo_free (outSort.members);
00852     }
00853 
00854   return handle;
00855 }
00856 
00857 sort
00858 sort_makeVal (sort sor)
00859 {
00860   sort retSort = sor;
00861   sortNode rsn, s;
00862 
00863   llassert (sortTable != NULL);
00864   s = sort_quietLookup (sor);
00865 
00866   switch (s.kind)
00867     {
00868     case SRT_PRIM:
00869     case SRT_ENUM:
00870     case SRT_PTR:
00871     case SRT_TUPLE:
00872     case SRT_UNIONVAL:
00873     case SRT_VECTOR:
00874     case SRT_HOF:
00875     case SRT_NONE:
00876      /* Do nothing for basic types and pointers. */
00877       retSort = sor;
00878       break;
00879     case SRT_SYN:
00880       return sort_makeVal (sortTable[sor].baseSort);
00881     case SRT_OBJ:
00882      /* Strip out the last Obj's */
00883       if (s.baseSort == NOSORTHANDLE)
00884         {
00885           llbuglit ("sort_makeVal: expecting a base sort for Obj");
00886         }
00887       retSort = s.baseSort;
00888       break;
00889     case SRT_ARRAY:
00890       retSort = sort_makeVec (ltoken_undefined, sor);
00891       break;
00892     case SRT_STRUCT:
00893       retSort = sort_makeTuple (ltoken_undefined, sor);
00894       break;
00895     case SRT_UNION:
00896       retSort = sort_makeUnionVal (ltoken_undefined, sor);
00897       break;
00898     default:
00899       llbuglit ("sort_makeVal: invalid sort kind");
00900     }
00901   rsn = sort_quietLookup (retSort);
00902   if (rsn.kind == SRT_NONE)
00903     {
00904       llfatalbug (message ("sort_makeVal: invalid return sort kind: %d", (int)rsn.kind));
00905     }
00906   return retSort;
00907 }
00908 
00909 sort
00910 sort_makeImmutable (ltoken t, lsymbol name)
00911 {
00912   sortNode outSort;
00913   sort handle;
00914 
00915   handle = sort_lookupName (name);
00916 
00917   outSort.kind = SRT_PRIM;
00918   outSort.name = name;
00919   outSort.baseSort = NOSORTHANDLE;
00920   outSort.objSort = NOSORTHANDLE;
00921   outSort.members = smemberInfo_undefined;
00922   outSort.export = exporting;
00923   outSort.mutable = FALSE;
00924   outSort.imported = context_inImport ();
00925   outSort.abstract = TRUE;
00926   outSort.handle = handle;
00927 
00928   if (handle == NOSORTHANDLE)
00929     {
00930       outSort.handle = handle = sort_enterNew (outSort);
00931       overloadSizeof (handle);
00932     }
00933   else
00934     {                           /* complain */
00935       llassert (sortTable != NULL);
00936 
00937       if ((sortTable[handle].kind != SRT_PRIM) &&
00938           (sortTable[handle].abstract) &&
00939           (!sortTable[handle].mutable))
00940         {
00941           sortError (t, handle, outSort);
00942         }
00943 
00944       smemberInfo_free (outSort.members);
00945     }
00946 
00947   return handle;
00948 }
00949 
00950 sort
00951 sort_makeMutable (ltoken t, lsymbol name)
00952 {
00953   sort immutable_old, handle, baseSort;
00954   lsymbol objName;
00955 
00956   immutable_old = sort_lookupName (name);
00957 
00958  /* First generate the value sort */
00959   baseSort = sort_makeImmutable (t, name);
00960 
00961   llassert (sortTable != NULL);
00962 
00963   /* to prevent duplicate error messages */
00964   if (immutable_old != NOSORTHANDLE &&
00965       (sortTable[baseSort].kind != SRT_PRIM) &&
00966       (sortTable[baseSort].abstract) &&
00967       (!sortTable[baseSort].mutable))
00968     {
00969      /* already complained */
00970       handle = NOSORTHANDLE;
00971     }
00972   else
00973     {                           /* sort_makeImmutable must have succeeded */
00974       sortNode outSort;
00975 
00976      /* must not clash with any LSL sorts */
00977       objName = sp (sp (underscoreSymbol, name),
00978                     lsymbol_fromChars ("_Obj"));
00979       handle = sort_lookupName (objName);
00980 
00981       outSort.kind = SRT_OBJ;
00982       outSort.name = objName;
00983       outSort.tag = lsymbol_undefined;
00984       outSort.baseSort = baseSort;
00985       outSort.objSort = NOSORTHANDLE;
00986       outSort.members = smemberInfo_undefined;
00987       outSort.mutable = TRUE;
00988       outSort.export = exporting;
00989       outSort.imported = context_inImport ();
00990       outSort.abstract = TRUE;
00991       outSort.handle = handle;
00992 
00993       if (handle == NOSORTHANDLE)
00994         {
00995           if (sort_isNewEntry (outSort))
00996             {
00997               outSort.handle = handle = sort_enterNew (outSort);
00998             }
00999           else
01000             {
01001               handle = sort_enterNew (outSort);
01002             }
01003         }
01004       else 
01005         {
01006           llassert (sortTable != NULL);
01007 
01008           if ((sortTable[handle].kind != SRT_OBJ) 
01009               && sortTable[handle].abstract
01010               && sortTable[handle].mutable)
01011             {
01012               sortError (t, handle, outSort);
01013             }
01014 
01015           smemberInfo_free (outSort.members);
01016         }
01017     }
01018   return handle;
01019 }
01020 
01021 sort
01022 sort_makeStr (ltoken opttagid)
01023 {
01024   sortNode outSort;
01025   sort handle;
01026   bool isNewTag;
01027   lsymbol name;
01028 
01029   /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
01030   /* isNewTag true means that the name generated is new */
01031 
01032   if (ltoken_isUndefined (opttagid))
01033     {
01034       opttagid = ltoken_create (simpleId, newStructTag ());
01035 
01036       outSort.realtag = FALSE;
01037     }
01038   else
01039     {
01040       outSort.realtag = TRUE;
01041     }
01042   
01043   name = sortTag_toSymbol ("Struct", opttagid, &isNewTag);
01044   
01045   llassert (sortTable != NULL);
01046   handle = sort_lookupName (name);
01047   outSort.name = name;
01048   outSort.kind = SRT_STRUCT;
01049   outSort.tag = ltoken_getText (opttagid);
01050   outSort.baseSort = NOSORTHANDLE;
01051   outSort.objSort = NOSORTHANDLE;
01052   outSort.members = smemberInfo_undefined;
01053   outSort.export = exporting;
01054   outSort.mutable = TRUE;
01055   outSort.imported = context_inImport ();
01056   outSort.abstract = FALSE;
01057   outSort.handle = handle;
01058 
01059   if (handle == NOSORTHANDLE)
01060     {
01061       if (sort_isNewEntry (outSort))
01062         {
01063           outSort.handle = handle = sort_enterNew (outSort);
01064         }
01065       else
01066         {
01067           outSort.handle = handle = sort_enterNewForce (outSort);
01068         }
01069     }
01070   else 
01071     {
01072       if (sortTable[handle].kind != SRT_STRUCT)
01073         {
01074           sortError (opttagid, handle, outSort);
01075         }
01076 
01077       smemberInfo_free (outSort.members);
01078     }
01079 
01080   return handle;
01081 }
01082 
01083 bool
01084 sort_updateStr (sort strSort, /*@only@*/ smemberInfo *info)
01085 {
01086   /* expect strSort to be in sort table but not yet filled in */
01087   /* return TRUE if it is "new" */
01088   sort tupleSort;
01089   sortNode sn;
01090   
01091   llassert (sortTable != NULL);
01092   sn = sort_lookup (strSort);
01093 
01094   if (sn.members == (smemberInfo *) 0)
01095     {
01096       sortTable[strSort].members = info;
01097       tupleSort = sort_makeTuple (ltoken_undefined, strSort);
01098       genStrOps (strSort, tupleSort);
01099       return TRUE;
01100     }
01101   else
01102     {
01103       smemberInfo_free (info);
01104       return FALSE;
01105     }
01106 }
01107 
01108 sort
01109 sort_makeTuple (ltoken t, sort strSort)
01110 {
01111   sort handle;
01112   sortNode outSort, s = sort_lookup (strSort);
01113   lsymbol name;
01114 
01115   if (s.kind != SRT_STRUCT)
01116     {
01117       llfatalbug (message ("sort_makeTuple: Only structs can become tuples: given sort is %s",
01118                            sort_unparseKind (s.kind)));
01119     }
01120 
01121   name = sp (s.name, lsymbol_fromChars ("_Tuple"));
01122   llassert (sortTable != NULL);
01123   handle = sort_lookupName (name);
01124 
01125   outSort.kind = SRT_TUPLE;
01126   outSort.name = name;
01127   outSort.tag = s.tag;
01128   outSort.realtag = s.realtag;
01129   outSort.baseSort = strSort;
01130   outSort.objSort = NOSORTHANDLE;
01131   outSort.members = smemberInfo_undefined;
01132   outSort.export = exporting;
01133   outSort.abstract = FALSE;
01134   outSort.imported = context_inImport ();
01135   outSort.mutable = FALSE;
01136   outSort.handle = handle;
01137 
01138   if (handle == NOSORTHANDLE)
01139     {
01140       if (sort_isNewEntry (outSort))
01141         {
01142           outSort.handle = handle = sort_enterNew (outSort);
01143 
01144           sort_addTupleMembers (handle, strSort);
01145           genTupleOps (handle);
01146         }
01147       else
01148         {
01149           outSort.handle = handle = sort_enterNew (outSort);
01150         }
01151     }
01152   else 
01153     {
01154       if (sortTable[handle].kind != SRT_TUPLE)
01155         {
01156           sortError (t, handle, outSort);
01157         }
01158 
01159       smemberInfo_free (outSort.members);
01160     }
01161 
01162   return handle;
01163 }
01164 
01165 static void
01166 sort_addTupleMembers (sort tupleSort, sort strSort)
01167 {
01168   smemberInfo *mem, *tail = smemberInfo_undefined;
01169   smemberInfo *top = smemberInfo_undefined;
01170   smemberInfo *newinfo;
01171   
01172   /* make sure it works for empty smemberInfo */
01173   
01174   llassert (sortTable != NULL);
01175  
01176  for (mem = sortTable[strSort].members;
01177        mem != smemberInfo_undefined; mem = mem->next)
01178     {
01179       newinfo = (smemberInfo *) dmalloc (sizeof (*newinfo));
01180       newinfo->name = mem->name;
01181       newinfo->sort = sort_makeVal (mem->sort);
01182       newinfo->next = smemberInfo_undefined;
01183 
01184       if (top == smemberInfo_undefined)
01185         {                       /* start of iteration */
01186           top = newinfo;
01187           tail = newinfo;
01188         }
01189       else
01190         {
01191           llassert (tail != smemberInfo_undefined);
01192 
01193           tail->next = newinfo;
01194           tail = newinfo;
01195           /*@-branchstate@*/ /* tail is dependent */
01196         } 
01197       /*@=branchstate@*/
01198     }
01199 
01200   sortTable[tupleSort].members = top;
01201 }
01202 
01203 static 
01204 void genTupleOps (sort tupleSort)
01205 {
01206   ltoken range, dom;
01207   sort fieldsort;
01208   smemberInfo *m;
01209   unsigned int memCount;
01210   ltokenList domain = ltokenList_new ();
01211   sigNode signature;
01212   opFormUnion u;
01213   opFormNode opform;
01214   nameNode nn;
01215 
01216   memCount = 0;
01217   range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (tupleSort));
01218 
01219   llassert (sortTable != NULL);
01220   for (m = sortTable[tupleSort].members;
01221        m != smemberInfo_undefined; m = m->next)
01222     {
01223       fieldsort = sort_makeVal (m->sort);
01224       overloadUnary (makeFieldOp (m->name), tupleSort, fieldsort);
01225 
01226       dom = ltoken_createType (simpleId, SID_SORT,
01227                                sort_getLsymbol (fieldsort));
01228       ltokenList_addh (domain, dom);
01229       memCount++;
01230     }
01231 
01232   /* For tuples only: [__, ...]: memSorts, ... -> tupleSort */
01233   signature = makesigNode (ltoken_undefined, domain, range);
01234   u.middle = memCount;
01235 
01236   opform = makeOpFormNode (ltoken_copy (ltoken_lbracked),
01237                            OPF_BMIDDLE, u, ltoken_copy (ltoken_rbracket));
01238 
01239   nn = makeNameNodeForm (opform);
01240   symtable_enterOp (g_symtab, nn, signature);
01241   
01242   /*
01243   ** should not be able to take sizeof (struct^) ...
01244   */
01245 }
01246 
01247 static 
01248 void genUnionOps (sort tupleSort)
01249 {
01250  /* like genTupleOps but no constructor [ ...]: -> unionSort */
01251   smemberInfo *m;
01252   sort sort;
01253 
01254   llassert (sortTable != NULL);
01255   for (m = sortTable[tupleSort].members;
01256        m != smemberInfo_undefined; m = m->next)
01257     {
01258      /* Generate __.memName: strSort ->memSortObj */
01259       overloadUnary (makeFieldOp (m->name), tupleSort, m->sort);
01260      /*    printf ("making __.%s: %s -> %s\n", lsymbol_toChars (m->name),
01261                 sort_getName (tupleSort), sort_getName (m->sort)); */
01262      /* __->memName : Union_Ptr -> memSortObj */
01263       sort = sort_makePtr (ltoken_undefined, tupleSort);
01264       overloadUnary (makeArrowFieldOp (m->name), sort, m->sort);
01265      /*    printf ("making __->%s: %s -> %s\n", lsymbol_toChars (m->name),
01266                 sort_getName (sort), sort_getName (m->sort)); */
01267     }
01268 }
01269 
01270 static 
01271 void genStrOps (sort strSort, /*@unused@*/ sort tupleSort)
01272 {
01273   smemberInfo *m;
01274   sort sort;
01275   
01276   llassert (sortTable != NULL);
01277   for (m = sortTable[strSort].members;
01278        m != smemberInfo_undefined; m = m->next)
01279     {
01280      /* Generate __.memName: strSort ->memSortObj */
01281       overloadUnary (makeFieldOp (m->name), strSort, m->sort);
01282       /*    printf ("making __.%s: %s -> %s\n", lsymbol_toChars (m->name),
01283             sort_getName (strSort), sort_getName (m->sort)); */
01284       /* __->memName : Struct_Ptr -> memSortObj */
01285       sort = sort_makePtr (ltoken_undefined, strSort);
01286       overloadUnary (makeArrowFieldOp (m->name), sort, m->sort);
01287       /*    printf ("making __->%s: %s -> %s\n", lsymbol_toChars (m->name),
01288             sort_getName (sort), sort_getName (m->sort)); */
01289     }
01290   /* Generate fresh, trashed, modifies, unchanged: struct/union -> bool */
01291   /* Generate __any, __pre, __post: nStruct -> nTuple */
01292   /* Generate sizeof: strSort -> int */
01293   /* overloadStateFcns (strSort, tupleSort); */
01294 }
01295 
01296 sort
01297 sort_makeUnion (ltoken opttagid)
01298 {
01299   sortNode outSort;
01300   sort handle;
01301   bool isNewTag; 
01302   lsymbol name;
01303 
01304   /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
01305   /* isNewTag true means that the name generated is new */
01306 
01307   if (ltoken_isUndefined (opttagid))
01308     {
01309       opttagid = ltoken_create (simpleId, newUnionTag ());
01310       outSort.realtag = FALSE;
01311     }
01312   else
01313     outSort.realtag = TRUE;
01314 
01315   llassert (sortTable != NULL);
01316   name = sortTag_toSymbol ("Union", opttagid, &isNewTag);
01317   handle = sort_lookupName (name);
01318   outSort.name = name;
01319   outSort.kind = SRT_UNION;
01320   outSort.tag = ltoken_getText (opttagid);
01321   outSort.baseSort = NOSORTHANDLE;
01322   outSort.objSort = NOSORTHANDLE;
01323   outSort.members = smemberInfo_undefined;
01324   outSort.export = exporting;
01325   outSort.mutable = TRUE;
01326   outSort.imported = context_inImport ();
01327   outSort.abstract = FALSE;
01328   outSort.handle = handle;
01329   
01330   if (handle == NOSORTHANDLE)
01331     {
01332       if (sort_isNewEntry (outSort))
01333         {
01334           outSort.handle = handle = sort_enterNew (outSort);
01335         }
01336       else
01337         {
01338           outSort.handle = handle = sort_enterNewForce (outSort);
01339         }
01340     }
01341   else 
01342     {
01343       if (sortTable[handle].kind != SRT_UNION)
01344         {
01345           sortError (opttagid, handle, outSort);
01346         }
01347 
01348       smemberInfo_free (outSort.members);
01349     }
01350 
01351   return handle;
01352 }
01353 
01354 bool
01355 sort_updateUnion (sort unionSort, /*@only@*/ smemberInfo *info)
01356 {
01357  /* expect unionSort to be in sort table but not yet filled in */
01358  /* return TRUE if it is "new" */
01359   sort uValSort;
01360   sortNode sn;
01361 
01362   llassert (sortTable != NULL);
01363 
01364   sn = sort_lookup (unionSort);
01365 
01366   if (sn.members == (smemberInfo *) 0)
01367     {
01368       sortTable[unionSort].members = info;
01369       uValSort = sort_makeUnionVal (ltoken_undefined, unionSort);
01370       /* same as struct operations */
01371       genStrOps (unionSort, uValSort);
01372       return TRUE;
01373     }
01374   else
01375     {
01376       smemberInfo_free (info);
01377       return FALSE;
01378     }
01379 }
01380 
01381 sort
01382 sort_makeUnionVal (ltoken t, sort unionSort)
01383 {
01384   sort handle;
01385   sortNode outSort, s = sort_lookup (unionSort);
01386   lsymbol name;
01387 
01388   if (s.kind != SRT_UNION)
01389     {
01390       llfatalbug (message ("sort_makeUnion: only unions can become unionVals: given sort is: %s",
01391                            sort_unparseKind (s.kind)));
01392     }
01393 
01394   llassert (sortTable != NULL);
01395 
01396   name = sp (s.name, lsymbol_fromChars ("_UnionVal"));
01397   handle = sort_lookupName (name);
01398 
01399   outSort.kind = SRT_UNIONVAL;
01400   outSort.name = name;
01401   outSort.tag = s.tag;
01402   outSort.realtag = s.realtag;
01403   outSort.baseSort = unionSort;
01404   outSort.objSort = NOSORTHANDLE;
01405   outSort.members = smemberInfo_undefined;
01406   outSort.export = exporting;
01407   outSort.abstract = FALSE;
01408   outSort.imported = context_inImport ();
01409   outSort.mutable = FALSE;
01410   outSort.handle = handle;
01411 
01412   if (handle == NOSORTHANDLE)
01413     {
01414       if (sort_isNewEntry (outSort))
01415         {
01416           outSort.handle = handle = sort_enterNew (outSort);
01417 
01418           /* Add members to the unionVal's. */
01419           /* same as structs and tuples */
01420 
01421           sort_addTupleMembers (handle, unionSort);
01422           genUnionOps (handle);
01423         }
01424       else
01425         {
01426           outSort.handle = handle = sort_enterNew (outSort);
01427         }
01428     }
01429   else 
01430     {
01431       if (sortTable[handle].kind != SRT_UNIONVAL)
01432         {
01433           sortError (t, handle, outSort);
01434         }
01435 
01436       smemberInfo_free (outSort.members);
01437     }
01438 
01439   return handle;
01440 }
01441 
01442 static lsymbol
01443 newEnumTag ()
01444 {
01445   static int ecount = 0;
01446 
01447   return (cstring_toSymbol (message ("e%s%de", context_moduleName (), ecount++)));
01448 }
01449 
01450 static lsymbol
01451 newStructTag ()
01452 {
01453   static int ecount = 0;
01454 
01455   return (cstring_toSymbol (message ("s%s%ds", context_moduleName (), ecount++)));
01456 }
01457 
01458 static lsymbol
01459 newUnionTag ()
01460 {
01461   static int ecount = 0;
01462 
01463   return (cstring_toSymbol (message ("u%s%du", context_moduleName (), ecount++)));
01464 }
01465 
01466 sort
01467 sort_makeEnum (ltoken opttagid)
01468 {
01469   sortNode outSort;
01470   sort handle;
01471   bool isNew;
01472   lsymbol name;
01473 
01474   llassert (sortTable != NULL);
01475 
01476   if (ltoken_isUndefined (opttagid))
01477     {
01478       opttagid = ltoken_create (simpleId, newEnumTag ());
01479       outSort.realtag = FALSE;
01480     }
01481   else
01482     outSort.realtag = TRUE;
01483   
01484   /* must not clash with any LSL sorts, tag2sortname adds "_" prefix */
01485 
01486   name = sortTag_toSymbol ("Enum", opttagid, &isNew);
01487   handle = sort_lookupName (name);
01488   outSort.name = name;
01489   outSort.kind = SRT_ENUM;
01490   outSort.tag = ltoken_getText (opttagid);
01491   outSort.baseSort = NOSORTHANDLE;
01492   outSort.objSort = NOSORTHANDLE;
01493   outSort.members = smemberInfo_undefined;
01494   outSort.export = exporting;
01495   outSort.mutable = FALSE;
01496   outSort.imported = context_inImport ();
01497   outSort.abstract = FALSE;
01498   outSort.handle = handle;
01499 
01500   if (handle == NOSORTHANDLE)
01501     {
01502       if (sort_isNewEntry (outSort))
01503         {
01504           outSort.handle = handle = sort_enterNew (outSort);
01505         }
01506       else
01507         {
01508           outSort.handle = handle = sort_enterNewForce (outSort);
01509         }
01510     }
01511   else 
01512     {
01513       if (sortTable[handle].kind != SRT_ENUM)
01514         {
01515           sortError (opttagid, handle, outSort);
01516         }
01517 
01518       smemberInfo_free (outSort.members);
01519     }
01520 
01521   return handle;
01522 }
01523 
01524 bool
01525 sort_updateEnum (sort enumSort, /*@only@*/ smemberInfo *info)
01526 {
01527   /*
01528   ** Expect enumSort to be in sort table but not yet filled in.
01529   ** Return TRUE if it is "new" 
01530   */
01531 
01532   sortNode sn;
01533 
01534   llassert (sortTable != NULL);
01535 
01536   sn = sort_lookup (enumSort);
01537   if (sn.members == (smemberInfo *) 0)
01538     {
01539       sortTable[enumSort].members = info;
01540       genEnumOps (enumSort);
01541       return TRUE;
01542     }
01543   else
01544     {
01545       smemberInfo_free (info);
01546       return FALSE;
01547     }
01548 }
01549 
01550 static 
01551 void genEnumOps (sort enumSort)
01552 {
01553   smemberInfo *ei;
01554   ltokenList domain = ltokenList_new ();
01555   ltoken range, mem;
01556   nameNode nn;
01557   sigNode signature;
01558 
01559   range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (enumSort));
01560   signature = makesigNode (ltoken_undefined, domain, range);
01561 
01562   llassert (sortTable != NULL);
01563 
01564   for (ei = sortTable[enumSort].members;
01565        ei != (smemberInfo *) 0; ei = ei->next)
01566     {
01567       mem = ltoken_createType (simpleId, SID_OP, ei->name);
01568       nn = makeNameNodeId (mem);
01569       symtable_enterOp (g_symtab, nn, sigNode_copy (signature));
01570     }
01571 
01572   sigNode_free (signature);
01573   overloadSizeof (enumSort);
01574 }
01575 
01576 static void
01577 genPtrOps (/*@unused@*/ sort baseSort, sort ptrSort, sort arraySort)
01578 {
01579   /* Generate *__: xPtr -> x */
01580 
01581   /* overloadUnary (deRefNameNode, ptrSort, baseSort); */
01582 
01583   /* Generate maxIndex, minIndex: xPtr -> int */
01584   /* overloadUnaryTok (maxIndexNameNode, ptrSort, intToken); */
01585   /* overloadUnaryTok (minIndexNameNode, ptrSort, intToken); */
01586 
01587   /* Generate __[]: pointer -> array  */
01588   overloadUnary (nameNode_copySafe (ptr2arrayNameNode), ptrSort, arraySort);
01589 
01590   /* Generate __+__, __-__: pointer, int -> pointer  */
01591   overloadBinary (nameNode_copySafe (plusNameNode), ptrSort, 
01592                   ltoken_copy (intToken), ptrSort);
01593 
01594   overloadBinary (nameNode_copySafe (minusNameNode), ptrSort, 
01595                   ltoken_copy (intToken), ptrSort);
01596 
01597   /* Generate NIL: -> xPtr */
01598   /* Generate __+__: int, pointer -> pointer  */
01599   /* Generate __-__: pointer, pointer -> int  */
01600   overloadPtrFcns (ptrSort);
01601 }
01602 
01603 static void
01604 genArrOps (sort baseSort, sort arraySort, int dim, /*@unused@*/ sort vecSort)
01605 {
01606   /* Generate __[__]: nArr, int -> n */
01607   overloadBinary (nameNode_copySafe (arrayRefNameNode), arraySort, 
01608                   ltoken_copy (intToken), baseSort);
01609   
01610   /* Generate maxIndex, minIndex: sort -> int */
01611   /* overloadUnaryTok (maxIndexNameNode, arraySort, intToken); */
01612   /* overloadUnaryTok (minIndexNameNode, arraySort, intToken); */
01613   
01614   /* Generate isSub: arraySort, int, ... -> bool */
01615   overloadIsSub (arraySort, dim); 
01616   
01617   /* Generate fresh, trashed, modifies, unchanged: array -> bool  */
01618   /* Generate any, pre, post: array -> vector */
01619   
01620   /* overloadStateFcns (arraySort, vecSort); */
01621   /* overloadObjFcns (arraySort); */
01622 }
01623 
01624 /*
01625 ** overloadPtrFcns:
01626 **   generate NIL: -> ptrSort
01627 **            __+__: int, ptrSort -> ptrSort  
01628 **            __-__: ptrSort, ptrSort -> int  
01629 */
01630 static void
01631 overloadPtrFcns (sort ptrSort)
01632 {
01633   ltokenList domain = ltokenList_new ();
01634   ltoken range;
01635   sigNode signature;
01636   
01637   /* NIL: -> ptrSort */
01638   
01639   range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (ptrSort));
01640   signature = makesigNode (ltoken_undefined, ltokenList_new (), ltoken_copy (range));
01641   symtable_enterOp (g_symtab, nameNode_copySafe (nilNameNode), signature);
01642   
01643   /* __+__: int, ptrSort -> ptrSort  */
01644   
01645   ltokenList_addh (domain, ltoken_copy (intToken));
01646   ltokenList_addh (domain, ltoken_copy (range));
01647 
01648   signature = makesigNode (ltoken_undefined, domain, ltoken_copy (range));
01649   symtable_enterOp (g_symtab, nameNode_copySafe (plusNameNode), signature);
01650   
01651   /* __-__: ptrSort, ptrSort -> int  */
01652 
01653   domain = ltokenList_new ();
01654   ltokenList_addh (domain, ltoken_copy (range));
01655   ltokenList_addh (domain, range);
01656   range = ltoken_copy (intToken);
01657   signature = makesigNode (ltoken_undefined, domain, range);
01658   symtable_enterOp (g_symtab, nameNode_copySafe (minusNameNode), signature);
01659 }
01660 
01661 static void
01662 genVecOps (sort baseSort, sort vecSort, int dim)
01663 {
01664   /* Generate __[__]: vecSort, int -> baseSort */
01665 
01666   overloadBinary (nameNode_copySafe (arrayRefNameNode), vecSort, 
01667                   ltoken_copy (intToken), baseSort);
01668 
01669   /*          sizeof: vecSort -> int */
01670   /* Generate isSub: vecSort, int, ... -> bool */
01671 
01672   overloadIsSub (vecSort, dim);
01673 }
01674 
01675 static void
01676 overloadIsSub (sort s, int dim)
01677 {
01678   /* Generate isSub: s, int, ... -> bool */
01679   int j, i;
01680   ltoken dom, nulltok = ltoken_undefined;
01681   ltokenList domain;
01682   sigNode signature;
01683 
01684   for (j = 1; j <= dim; j++)
01685     {
01686       nameNode isSubNameNode = (nameNode) dmalloc (sizeof (*isSubNameNode));
01687 
01688       isSubNameNode->isOpId = TRUE;
01689       isSubNameNode->content.opid = ltoken_createType (simpleId, SID_OP, 
01690                                                          lsymbol_fromChars ("isSub"));
01691       dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (s));
01692 
01693       domain = ltokenList_singleton (dom);
01694 
01695       for (i = 1; i <= j; i++)
01696         {
01697           ltokenList_addh (domain, ltoken_copy (intToken));
01698         }
01699 
01700       signature = makesigNode (nulltok, domain, ltoken_copy (ltoken_bool));
01701       symtable_enterOp (g_symtab, isSubNameNode, signature);
01702     }
01703 }
01704 
01705 static void
01706 overloadUnaryTok (/*@only@*/ nameNode nn, sort domainSort, /*@only@*/ ltoken range)
01707 {
01708   /* Generate <nn>: domainSort -> rangeTok */
01709   sigNode signature;
01710   ltoken dom;
01711   ltokenList domain;
01712 
01713   dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (domainSort));
01714   domain = ltokenList_singleton (dom);
01715   signature = makesigNode (ltoken_undefined, domain, range);
01716   symtable_enterOp (g_symtab, nn, signature);
01717 }
01718 
01719 static void
01720 overloadSizeof (sort domainSort)
01721 {
01722   nameNode sizeofNameNode = (nameNode) dmalloc (sizeof (*sizeofNameNode));
01723   
01724   sizeofNameNode->isOpId = TRUE;
01725   sizeofNameNode->content.opid = ltoken_createType (simpleId, SID_OP, 
01726                                                       lsymbol_fromChars ("sizeof"));
01727   
01728   overloadUnaryTok (sizeofNameNode, domainSort, ltoken_copy (intToken));
01729 }
01730 
01731 static void
01732 overloadUnary (/*@only@*/ nameNode nn, sort domainSort, sort rangeSort)
01733 {
01734   ltoken range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (rangeSort));
01735 
01736   overloadUnaryTok (nn, domainSort, range);
01737 }
01738 
01739 static void
01740 overloadBinary (/*@only@*/ nameNode nn, sort s, /*@only@*/ ltoken dTok, sort rs)
01741 {
01742   /* Generate <nn>: s, dTok -> rs */
01743   sigNode signature;
01744   ltoken range, dom;
01745   ltokenList domain = ltokenList_new ();
01746 
01747   range = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (rs));
01748   dom = ltoken_createType (simpleId, SID_SORT, sort_getLsymbol (s));
01749   
01750   ltokenList_addh (domain, dom);
01751   ltokenList_addh (domain, dTok);
01752   
01753   signature = makesigNode (ltoken_undefined, domain, range);
01754       symtable_enterOp (g_symtab, nn, signature);
01755 }
01756 
01757 static /*@only@*/ nameNode
01758 makeFieldOp (lsymbol field)
01759 {
01760  /* operator: __.<field> */
01761   nameNode nn;
01762   opFormUnion u;
01763   opFormNode opform;
01764 
01765   u.id = ltoken_createType (simpleId, SID_OP, field);
01766   opform = makeOpFormNode (ltoken_undefined, OPF_MSELECT, u, ltoken_undefined);
01767   nn = makeNameNodeForm (opform);
01768   return nn;
01769 }
01770 
01771 static /*@only@*/ nameNode
01772 makeArrowFieldOp (lsymbol field)
01773 {
01774  /* operator: __-><field> */
01775   nameNode nn;
01776   opFormUnion u;
01777   opFormNode opform;
01778 
01779   u.id = ltoken_createType (simpleId, SID_OP, field);
01780   opform = makeOpFormNode (ltoken_undefined, OPF_MMAP, u, ltoken_undefined);
01781   nn = makeNameNodeForm (opform);
01782   return nn;
01783 }
01784 
01785 void
01786 sort_init (void) 
01787    /*@globals undef noSort,
01788               undef arrayRefNameNode,
01789               undef ptr2arrayNameNode,
01790               undef deRefNameNode,
01791               undef nilNameNode,
01792               undef plusNameNode,
01793               undef minusNameNode,
01794               undef condNameNode,
01795               undef eqNameNode,
01796               undef neqNameNode,
01797               undef intToken; @*/
01798 {
01799   /* on alpha, declaration does not allocate storage */
01800   opFormNode opform;
01801   opFormUnion u;
01802   underscoreSymbol = lsymbol_fromChars ("_");
01803 
01804   /*
01805   ** commonly used data for generating operators 
01806   */
01807   
01808   lsymbol_setbool (lsymbol_fromChars ("bool"));
01809   intToken = ltoken_createType (simpleId, SID_SORT, lsymbol_fromChars ("int"));
01810   
01811   /*
01812   ** __ \eq __: sort, sort -> bool 
01813   */
01814 
01815   u.anyop = ltoken_copy (ltoken_eq);
01816   opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
01817   eqNameNode = makeNameNodeForm (opform);
01818   
01819   /*
01820   ** __ \neq __: sort, sort -> bool 
01821   */
01822 
01823   u.anyop = ltoken_copy (ltoken_neq);
01824   opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
01825   neqNameNode = makeNameNodeForm (opform);
01826   
01827   /*
01828   **if __ then __ else __: bool, sort, sort -> sort 
01829   */
01830 
01831   opform = makeOpFormNode (ltoken_undefined, OPF_IF, 
01832                            opFormUnion_createMiddle (0), ltoken_undefined);
01833   condNameNode = makeNameNodeForm (opform);
01834   
01835   /* operator: __[__]: arraySort, int -> elementSort_Obj */
01836   u.middle = 1;
01837   opform = makeOpFormNode (ltoken_copy (ltoken_lbracked), OPF_BMMIDDLE, u,
01838                            ltoken_copy (ltoken_rbracket));
01839   arrayRefNameNode = makeNameNodeForm (opform);
01840   
01841   /* operator: __[]: ptrSort -> arraySort */
01842   u.middle = 0;
01843   opform = makeOpFormNode (ltoken_copy (ltoken_lbracked), 
01844                            OPF_BMMIDDLE, u,
01845                            ltoken_copy (ltoken_rbracket));
01846   ptr2arrayNameNode = makeNameNodeForm (opform);
01847   
01848   /* operator: *__ */
01849   u.anyop = ltoken_create (LLT_MULOP, lsymbol_fromChars ("*"));
01850   opform = makeOpFormNode (ltoken_undefined, OPF_ANYOPM, u, ltoken_undefined);
01851   deRefNameNode = makeNameNodeForm (opform);
01852   
01853   /* operator: __ + __ */
01854   u.anyop = ltoken_create (simpleOp, lsymbol_fromChars ("+"));
01855   opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
01856   plusNameNode = makeNameNodeForm (opform);
01857   
01858   /* operator: __ - __ */
01859   u.anyop = ltoken_create (simpleOp, lsymbol_fromChars ("-"));
01860   opform = makeOpFormNode (ltoken_undefined, OPF_MANYOPM, u, ltoken_undefined);
01861   minusNameNode = makeNameNodeForm (opform);
01862   
01863   /* operator: NIL */
01864   nilNameNode = (nameNode) dmalloc (sizeof (*nilNameNode));
01865   nilNameNode->isOpId = TRUE;
01866   nilNameNode->content.opid = ltoken_createType (simpleId, SID_OP, 
01867                                                  lsymbol_fromChars ("NIL"));
01868 
01869   noSort.kind = SRT_NONE;
01870   noSort.name = lsymbol_fromChars ("_unknown");;
01871   noSort.tag = lsymbol_undefined;
01872   noSort.baseSort = NOSORTHANDLE;
01873   noSort.objSort = NOSORTHANDLE;
01874   noSort.members = smemberInfo_undefined;
01875   noSort.export = FALSE;
01876   noSort.mutable = FALSE;
01877   noSort.abstract = FALSE;
01878   noSort.imported = FALSE;
01879   noSort.handle = NOSORTHANDLE;
01880   
01881   /*
01882   ** Store the null sort into table, and in the process initialize the sort table. 
01883   ** Must be the first sort_enter so NOSORTHANDLE is truly = 0. Similarly, 
01884   ** for HOFSORTHANDLE = 1.
01885   */
01886   
01887   noSort.handle = sort_enterGlobal (noSort);
01888   (void) sort_enterGlobal (HOFSort); 
01889   
01890   /* Other builtin sorts */
01891   
01892   sort_bool = sort_makeImmutable (ltoken_undefined, lsymbol_fromChars ("bool"));
01893   sort_capBool = sort_makeSortNoOps (ltoken_undefined, lsymbol_fromChars ("Bool"));
01894   
01895   llassert (sortTable != NULL);
01896 
01897   /* make sort_Bool a synonym for sort_bool */
01898   sortTable[sort_capBool].kind = SRT_SYN;
01899   sortTable[sort_capBool].baseSort = sort_bool;
01900   sortTable[sort_capBool].mutable = FALSE;
01901   sortTable[sort_capBool].abstract = TRUE;
01902   
01903   sort_int = sort_makeLiteralSort (ltoken_undefined, 
01904                                    lsymbol_fromChars ("int"));
01905   sort_char = sort_makeLiteralSort (ltoken_undefined,
01906                                     lsymbol_fromChars ("char"));
01907   sort_void = sort_makeLiteralSort (ltoken_undefined,
01908                                     lsymbol_fromChars ("void"));
01909   
01910   /* sort_cstring is char__Vec, for C strings eg: "xyz" */
01911   char_obj_ptrSort = sort_makePtr (ltoken_undefined, sort_char);
01912   char_obj_ArrSort = sort_makeArr (ltoken_undefined, sort_char);
01913   
01914   sort_cstring = sort_makeVal (char_obj_ArrSort);
01915   sort_float = sort_makeLiteralSort (ltoken_undefined, lsymbol_fromChars ("float"));
01916   sort_double = sort_makeLiteralSort (ltoken_undefined, lsymbol_fromChars ("double"));
01917 }
01918 
01919 sort
01920 sort_lookupName (lsymbol name)
01921 {
01922   long int i;
01923 
01924   if (name == lsymbol_undefined)
01925     {
01926       return NOSORTHANDLE;
01927     }
01928 
01929   llassert (sortTable != NULL);
01930 
01931   for (i = 0; i < sortTableSize; i++)
01932     {
01933       if (sortTable[i].name == name)
01934         {
01935           return i;
01936         }
01937     }
01938 
01939   return NOSORTHANDLE;
01940 }
01941 
01942 static bool
01943 sort_isNewEntry (sortNode s)
01944 {
01945   int i;
01946   
01947   for (i = 0; i < sortTableSize; i++)
01948     {
01949       llassert (sortTable != NULL);
01950 
01951       if (sortTable[i].kind == s.kind && sortTable[i].name == s.name)
01952         {
01953           return FALSE;
01954         }
01955     }
01956   return TRUE;
01957 }
01958 
01959 static sort
01960 sort_enterGlobal (sortNode s)
01961 {
01962   /*@i@*/ return (sort_enterNew (s));
01963 }
01964 
01965 static sort
01966 sort_enterNew (sortNode s)
01967 {
01968   /* This ensures that the argument sortNode is not entered into
01969      the sort table more than once.  isNew flag will tell the
01970      caller this info, and the caller will decide whether to generate
01971      operators for this sort. */
01972   long int i;
01973   
01974   for (i = 0; i < sortTableSize; i++)
01975     {
01976       llassert (sortTable != NULL);
01977 
01978       if (sortTable[i].kind == s.kind && sortTable[i].name == s.name)
01979         {
01980           sortNode_free (s);
01981           return i;
01982         }
01983     }
01984 
01985   if (sortTableSize >= sortTableAlloc)
01986     {
01987       sortNode *oldSortTable = sortTable;
01988 
01989       sortTableAlloc += DELTA;
01990       sortTable = (sortNode *) dmalloc (sortTableAlloc * sizeof (*sortTable));
01991 
01992       if (sortTableSize > 0)
01993         {
01994           llassert (oldSortTable != NULL);      
01995           for (i = 0; i < sortTableSize; i++)
01996             {
01997               sortTable[i] = oldSortTable[i];
01998             }
01999         }
02000 
02001       sfree (oldSortTable);
02002     }
02003 
02004   llassert (sortTable != NULL);
02005 
02006   s.handle = sortTableSize;
02007   sortTable[sortTableSize++] = s;
02008 
02009   /*@-compdef@*/ 
02010   
02011   return s.handle;
02012 } /*=compdef@*/
02013 
02014 static sort sort_enterNewForce (sortNode s)
02015 {
02016   sort sor = sort_enterNew (s); 
02017 
02018   s.handle = sor;
02019   llassert (sortTable != NULL);
02020   sortTable[sor] = s;
02021   
02022   /*@-globstate@*/ return (sor); /*@=globstate@*/
02023 }
02024 
02025 void
02026 sort_printStats (void)
02027 {
02028   /* only for debugging */
02029   printf ("sortTableSize = %d; sortTableAlloc = %d\n", sortTableSize,
02030           sortTableAlloc);
02031 }
02032 
02033 sortNode
02034 sort_lookup (sort sor)
02035 {
02036   /* ymtan: can sor be 0 ? */
02037   /* evs --- yup...0 should return noSort ? */
02038   
02039   if (sor > 0U && sor < (unsigned) sortTableSize)
02040     {
02041       llassert (sortTable != NULL);
02042       return sortTable[sor];
02043     }
02044 
02045   llassert (sor == 0);
02046   return noSort;
02047 }
02048 
02049 sortNode
02050 sort_quietLookup (sort sor)
02051 {
02052   /* ymtan: can sor be 0 ? */
02053   if (sor > 0U && sor < (unsigned) sortTableSize)
02054     {
02055       llassert (sortTable != NULL);
02056       return (sortTable[sor]);
02057     }
02058   else
02059     {
02060       return noSort;
02061     }
02062 }
02063 
02064 static cstring
02065 printEnumMembers (/*@null@*/ smemberInfo *list)
02066 {
02067   cstring out = cstring_undefined;
02068   smemberInfo *m;
02069 
02070   for (m = list; m != (smemberInfo *) 0; m = m->next)
02071     {
02072       out = cstring_concat (out, lsymbol_toString (m->name));
02073 
02074       if (m->next != (smemberInfo *) 0)
02075         {
02076           out = cstring_concatChars (out, ", ");
02077         }
02078     }
02079   return out;
02080 }
02081 
02082 static /*@only@*/ cstring
02083 printStructMembers (/*@null@*/ smemberInfo *list)
02084 {
02085   cstring ret = cstring_undefined;
02086   smemberInfo *m;
02087 
02088   for (m = list; m != (smemberInfo *) 0; m = m->next)
02089     {
02090       ret = message ("%q%q %s; ",
02091                      ret, sort_unparse (m->sort), 
02092                      cstring_fromChars (lsymbol_toChars (m->name)));
02093     }
02094 
02095   return ret;
02096 }
02097 
02098 /*@only@*/ cstring
02099 sort_unparse (sort s)
02100 {
02101  /* printing routine for sorts */
02102   sortNode sn;
02103   lsymbol name;
02104 
02105   sn = sort_quietLookup (s);
02106   name = sn.name;
02107 
02108   switch (sn.kind)
02109     {
02110     case SRT_NONE:
02111       if (name == lsymbol_undefined)
02112         {
02113           return cstring_makeLiteral ("_unknown");
02114         }
02115 
02116       return (cstring_fromCharsNew (lsymbol_toChars (name)));
02117     case SRT_HOF:
02118       return cstring_makeLiteral ("procedural");
02119     case SRT_PRIM:
02120       return (cstring_fromCharsNew (lsymbol_toChars (name)));
02121     case SRT_SYN:
02122       return (cstring_fromCharsNew (lsymbol_toChars (name)));
02123 
02124     case SRT_PTR:
02125       return (message ("%q *", sort_unparse (sort_makeVal (sn.baseSort))));
02126     case SRT_OBJ:
02127       return (message ("obj %q", sort_unparse (sn.baseSort)));
02128     case SRT_ARRAY:
02129       return (message ("array of %q", sort_unparse (sort_makeVal (sn.baseSort))));
02130     case SRT_VECTOR:
02131       return (message ("vector of %q", sort_unparse (sn.baseSort)));
02132     case SRT_TUPLE:
02133       if (sn.tag != lsymbol_undefined && sn.realtag)
02134         {
02135           return (message ("struct %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
02136         }
02137       else
02138         {
02139           return (message ("struct {%q}", printStructMembers (sn.members)));
02140         }
02141     case SRT_UNIONVAL:
02142       if (sn.tag != lsymbol_undefined && sn.realtag)
02143         {
02144           return (message ("union %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
02145         }
02146       else
02147         {
02148           return (message ("union {%q}", printStructMembers (sn.members)));
02149         }
02150     case SRT_ENUM:
02151       if (sn.tag != lsymbol_undefined && sn.realtag)
02152         {
02153           return (message ("enum %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
02154         }
02155       else
02156         {
02157           return (message ("enum {%q}", printEnumMembers (sn.members)));
02158         }
02159     case SRT_STRUCT:
02160       if (sn.tag != lsymbol_undefined && sn.realtag)
02161         {
02162           return (message ("obj struct %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
02163         }
02164       else
02165         {
02166           return (message ("obj struct {%q}", printStructMembers (sn.members)));
02167         }
02168     case SRT_UNION:
02169       if (sn.tag != lsymbol_undefined && sn.realtag)
02170         {
02171           return (message ("obj union %s", cstring_fromChars (lsymbol_toChars (sn.tag))));
02172         }
02173       else
02174         {
02175           return (message ("obj union {%q}", printStructMembers (sn.members)));
02176         }
02177     default:
02178       return (cstring_makeLiteral ("illegal"));
02179     }
02180 }
02181 
02182 static lsymbol
02183 sp (lsymbol s1, lsymbol s2)
02184 {
02185   char buff[MAXBUFFLEN];
02186   char *name1Ptr;
02187   char *name2Ptr;
02188   int temp_length;
02189 
02190   name1Ptr = lsymbol_toCharsSafe (s1);
02191   name2Ptr = lsymbol_toCharsSafe (s2);
02192 
02193   if (strlen (name1Ptr) + strlen (name2Ptr) + 1 > MAXBUFFLEN)
02194     {
02195       temp_length = strlen (name1Ptr) + strlen (name2Ptr) + 1;
02196       llfatalbug (message ("sp: name too long: %s%s", 
02197                            cstring_fromChars (name1Ptr), 
02198                            cstring_fromChars (name2Ptr)));
02199     }
02200 
02201   strcpy (&buff[0], name1Ptr);
02202   strcat (&buff[0], name2Ptr);
02203 
02204   return lsymbol_fromChars (&buff[0]);
02205 }
02206 
02207 static lsymbol
02208 sortTag_toSymbol (char *kind, ltoken tagid, /*@out@*/ bool *isNew)
02209 {
02210   /* 
02211   ** kind could be struct, union or enum.  Create a unique sort
02212   ** name based on the given info. But first check that tagid
02213   ** has not been defined already. (ok if it is a forward decl) 
02214   **/
02215 
02216   tagInfo to;
02217 
02218   if (ltoken_isUndefined (tagid))
02219     {
02220       *isNew = TRUE;
02221       return (cstring_toSymbol (message ("_anon_%s%d", cstring_fromChars (kind), sortUID++)));
02222     }
02223   else
02224     {
02225       to = symtable_tagInfo (g_symtab, ltoken_getText (tagid));
02226 
02227       if (tagInfo_exists (to))
02228         {
02229           *isNew = FALSE;
02230         }
02231       else
02232         {
02233           *isNew = TRUE;
02234         }
02235 
02236       return (cstring_toSymbol (message ("_%s_%s", 
02237                                          ltoken_unparse (tagid), 
02238                                          cstring_fromChars (kind))));
02239     }
02240 }
02241 
02242 /*@constant int MAX_SORT_DEPTH@*/
02243 # define MAX_SORT_DEPTH 10
02244 
02245 static sort
02246 sort_getUnderlyingAux (sort s, int depth)
02247 {
02248   sortNode sn = sort_quietLookup (s);
02249   
02250   if (sn.kind == SRT_SYN)
02251     {
02252       if (depth > MAX_SORT_DEPTH)
02253         {
02254           llcontbug (message ("sort_getUnderlying: depth charge: %d", depth));
02255           return s;
02256         }
02257       
02258       return sort_getUnderlyingAux (sn.baseSort, depth + 1);
02259     }
02260   
02261   return s;
02262 }
02263 
02264 sort
02265 sort_getUnderlying (sort s)
02266 {
02267   return sort_getUnderlyingAux (s, 0);
02268 }
02269 
02270 static lsymbol
02271 underlyingSortName (sortNode sn)
02272 {
02273   if (sn.kind == SRT_SYN)
02274     return underlyingSortName (sort_quietLookup (sn.baseSort));
02275   return sn.name;
02276 }
02277 
02278 static /*@observer@*/ sortNode
02279 underlyingSortNode (sortNode sn)
02280 {
02281   if (sn.kind == SRT_SYN)
02282     {
02283       return underlyingSortNode (sort_quietLookup (sn.baseSort));
02284     }
02285 
02286   return sn;
02287 }
02288 
02289 bool
02290 sort_mutable (sort s)
02291 {
02292  /* if s is not a valid sort, then returns false */
02293   sortNode sn = sort_quietLookup (s);
02294   if (sn.mutable)
02295     return TRUE;
02296   return FALSE;
02297 }
02298 
02299 bool
02300 sort_setExporting (bool flag)
02301 {
02302   bool old;
02303   old = exporting;
02304   exporting = flag;
02305   return old;
02306 }
02307 
02308 /*@observer@*/ static cstring 
02309 sort_unparseKind (sortKind k)
02310 {
02311   if (k > SRT_FIRST && k < SRT_LAST)
02312     return (cstring_fromChars (sortKindName[(int)k]));
02313   else
02314     return (cstring_makeLiteralTemp ("<unknown sort kind>"));
02315 }
02316 
02317 bool
02318 sort_isValidSort (sort s)
02319 {
02320   sortNode sn = sort_quietLookup (s);
02321   sortKind k = sn.kind;
02322   if (k != SRT_NONE && k > SRT_FIRST && k < SRT_LAST)
02323     return TRUE;
02324   else
02325     return FALSE;
02326 }
02327 
02328 void
02329 sort_dump (FILE *f, bool lco)
02330 {
02331   int i;
02332   sortNode s;
02333   smemberInfo *mem;
02334 
02335   fprintf (f, "%s\n", BEGINSORTTABLE);
02336   llassert (sortTable != NULL);
02337 
02338   for (i = 2; i < sortTableSize; i++)
02339     {
02340       /* skips 0 and 1, noSort and HOFSort */
02341       s = sortTable[i];
02342       
02343       /* if (lco && !s.export) continue; */
02344       /* Difficult to keep track of where each op and sort belong to
02345          which LCL type.  Easiest to export them all (even private sorts and
02346          op's) but for checking imported modules, we only use LCL types and
02347          variables to check, i.e., we don't rely on sorts and op's for such
02348          checking. */
02349       
02350       if (s.kind == SRT_NONE)
02351         continue;
02352       
02353       if (lco)
02354         {
02355           fprintf (f, "%%LCL");
02356         }
02357 
02358       if (lsymbol_isDefined (s.name))
02359         {
02360           fprintf (f, "sort %s ", lsymbol_toCharsSafe (s.name));
02361         }
02362       else
02363         {
02364           llcontbug (message ("Invalid sort in sort_dump: sort %d; sortname: %s.  This may result from using .lcs files produced by an old version of LCLint.  Remove the .lcs files, and rerun LCLint.",
02365                               i, lsymbol_toString (s.name)));
02366           fprintf (f, "sort _error_ ");
02367         }
02368       
02369       if (!lco && !s.export)
02370         fprintf (f, "private ");
02371 
02372       /*@-loopswitchbreak@*/
02373       switch (s.kind)
02374         {
02375         case SRT_HOF:
02376           fprintf (f, "hof nil nil\n");
02377           break;
02378         case SRT_PRIM:
02379           if (s.abstract)
02380             fprintf (f, "immutable nil nil\n");
02381           else
02382             fprintf (f, "primitive nil nil\n");
02383           break;
02384         case SRT_OBJ:
02385           if (s.abstract)
02386             fprintf (f, "mutable %s nil\n",
02387                      lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02388           else
02389             fprintf (f, "obj %s nil\n",
02390                      lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02391           break;
02392         case SRT_SYN:
02393           fprintf (f, "synonym %s nil\n",
02394                    lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02395           break;
02396         case SRT_PTR:
02397           fprintf (f, "ptr %s nil\n", lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02398           break;
02399         case SRT_ARRAY:
02400           fprintf (f, "arr %s nil\n",
02401                    lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02402           break;
02403         case SRT_VECTOR:
02404           fprintf (f, "vec %s %s\n",
02405                    lsymbol_toCharsSafe (sortTable[s.baseSort].name),
02406                    lsymbol_toCharsSafe (sortTable[s.objSort].name));
02407           break;
02408         case SRT_STRUCT:
02409           if (s.tag == lsymbol_undefined)
02410             {
02411               /* we need to make up a tag to prevent excessive
02412                  growth of .lcs files when tags are overloaded
02413                  */
02414               llbuglit ("Struct has no tag");
02415             }
02416           else
02417             fprintf (f, "str %s nil\n", lsymbol_toCharsSafe (s.tag));
02418 
02419           for (mem = s.members;
02420                mem != smemberInfo_undefined; mem = mem->next)
02421             {
02422               if (lco)
02423                 fprintf (f, "%%LCL");
02424               fprintf (f, "sort %s strMem %s nil\n", lsymbol_toCharsSafe (mem->name),
02425                        lsymbol_toCharsSafe (sortTable[mem->sort].name));
02426             }
02427           if (lco)
02428             fprintf (f, "%%LCL");
02429           fprintf (f, "sort strEnd nil nil nil\n");
02430           break;
02431         case SRT_UNION:
02432           if (s.tag == lsymbol_undefined)
02433             llbuglit ("Union has no tag");
02434           else
02435             fprintf (f, "union %s nil\n", lsymbol_toCharsSafe (s.tag));
02436           for (mem = s.members;
02437                mem != smemberInfo_undefined; mem = mem->next)
02438             {
02439               if (lco)
02440                 fprintf (f, "%%LCL");
02441               fprintf (f, "sort %s unionMem %s nil\n", lsymbol_toCharsSafe (mem->name),
02442                        lsymbol_toCharsSafe (sortTable[mem->sort].name));
02443             }
02444           if (lco)
02445             fprintf (f, "%%LCL");
02446           fprintf (f, "sort unionEnd nil nil nil\n");
02447           break;
02448         case SRT_ENUM:
02449           if (s.tag == lsymbol_undefined)
02450             {
02451               llbuglit ("Enum has no tag");
02452             }
02453 
02454           fprintf (f, "enum %s nil\n", lsymbol_toCharsSafe (s.tag));
02455 
02456           for (mem = s.members;
02457                mem != smemberInfo_undefined; mem = mem->next)
02458             {
02459               if (lco)
02460                 fprintf (f, "%%LCL");
02461               fprintf (f, "sort %s enumMem nil nil\n", lsymbol_toCharsSafe (mem->name));
02462             }
02463           if (lco)
02464             fprintf (f, "%%LCL");
02465           fprintf (f, "sort enumEnd nil nil nil\n");
02466           break;
02467         case SRT_TUPLE:
02468           fprintf (f, "tup %s nil\n", lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02469           break;
02470         case SRT_UNIONVAL:
02471           fprintf (f, "unionval %s nil\n",
02472                    lsymbol_toCharsSafe (sortTable[s.baseSort].name));
02473           break;
02474         default:
02475           fprintf (f, "sort_dump: unexpected sort: %d", (int)s.kind);
02476         }                       /* switch */
02477       /*@=loopswitchbreak@*/
02478     }
02479 
02480   fprintf (f, "%s\n", SORTTABLEEND);
02481 }
02482 
02483 static void
02484 sort_loadOther (char *kstr, lsymbol sname, sort bsort)
02485 {
02486   if (strcmp (kstr, "synonym") == 0)
02487     {
02488       (void) sort_construct (sname, SRT_SYN, bsort, lsymbol_undefined,
02489                              FALSE, NOSORTHANDLE, smemberInfo_undefined);
02490     }
02491   else if (strcmp (kstr, "mutable") == 0)
02492     {
02493       (void) sort_constructAbstract (sname, TRUE, bsort);
02494     }
02495   else if (strcmp (kstr, "obj") == 0)
02496     {
02497       (void) sort_construct (sname, SRT_OBJ, bsort, lsymbol_undefined,
02498                              TRUE, NOSORTHANDLE, smemberInfo_undefined);
02499     }
02500   else if (strcmp (kstr, "ptr") == 0)
02501     {
02502       (void) sort_construct (sname, SRT_PTR, bsort, lsymbol_undefined,
02503                              FALSE, NOSORTHANDLE, smemberInfo_undefined);
02504     }
02505   else if (strcmp (kstr, "arr") == 0)
02506     {
02507       (void) sort_construct (sname, SRT_ARRAY, bsort, lsymbol_undefined,
02508                              TRUE, NOSORTHANDLE, smemberInfo_undefined);
02509     }
02510   else if (strcmp (kstr, "tup") == 0)
02511     {
02512       (void) sort_construct (sname, SRT_TUPLE, bsort, lsymbol_undefined,
02513                              FALSE, NOSORTHANDLE, smemberInfo_undefined);
02514     }
02515   else if (strcmp (kstr, "unionval") == 0)
02516     {
02517       (void) sort_construct (sname, SRT_UNIONVAL, bsort, lsymbol_undefined,
02518                              FALSE, NOSORTHANDLE, smemberInfo_undefined);
02519     }
02520   else
02521     {
02522       llbug (message ("Unhandled: %s", cstring_fromChars (kstr)));
02523     }
02524 }
02525 
02526 static void
02527 parseSortLine (char *line, ltoken t, tsource * s,
02528                mapping *map, lsymbolList slist)
02529 {
02530   /* caller expects that map and slist are updated */
02531   /* t and importfle are only used for error messages */
02532   static lsymbol strName = lsymbol_undefined;
02533   static smemberInfo *strMemList = NULL;
02534   static lsymbol unionName = lsymbol_undefined;
02535   static smemberInfo *unionMemList = NULL;
02536   static lsymbol enumName = lsymbol_undefined;
02537   static smemberInfo *enumMemList = NULL;
02538   static lsymbol tagName = lsymbol_undefined;
02539   
02540   char *importfile = tsource_fileName (s);
02541   char sostr[MAXBUFFLEN], kstr[10], basedstr[MAXBUFFLEN], objstr[MAXBUFFLEN];
02542   bool tmp;
02543   tagInfo ti;
02544   lsymbol sname, bname, new_name, objName;
02545   sort objSort;
02546   char *lineptr;
02547   int col;                      /* for keeping column number */
02548   ltoken tagid;
02549   
02550   if (sscanf (line, "sort %s %s %s %s", &(sostr[0]), &(kstr[0]),
02551               &(basedstr[0]), &(objstr[0])) != 4)
02552     {           
02553       /* if this fails, can have weird errors */
02554       /* strEnd, unionEnd, enumEnd won't return 4 args */
02555       lclplainerror 
02556         (message ("%q: Imported file contains illegal sort declaration.   "
02557                   "Skipping this line: \n%s\n",
02558                   fileloc_unparseRaw (cstring_fromChars (importfile), 
02559                                       tsource_thisLineNumber (s)), 
02560                   cstring_fromChars (line)));
02561       return;
02562     }
02563   
02564   sname = lsymbol_fromChars (sostr);
02565   if (sname == lsymbol_fromChars ("nil"))
02566     {
02567       /* No given sort name.  Use lsymbol_undefined and generate sort name
02568          in sort building routines. */
02569       sname = lsymbol_undefined;
02570       lclerror (t, message ("Illegal sort declaration in import file: %s:\n%s",
02571                             cstring_fromChars (importfile), 
02572                             cstring_fromChars (line)));
02573     }
02574   
02575   /* Assume that when we encounter a sort S1 that is based on sort
02576      S2, S2 is before S1 in the imported file.  sort table is a
02577      linear list and we create base sorts before other sorts. */
02578   
02579   bname = lsymbol_fromChars (basedstr);
02580   if (strcmp (kstr, "primitive") == 0)
02581     {
02582       new_name = lsymbol_translateSort (map, sname);
02583       (void) sort_construct (new_name, SRT_PRIM, NOSORTHANDLE,
02584                              lsymbol_undefined, FALSE,
02585                              NOSORTHANDLE, smemberInfo_undefined);
02586     }
02587   else if (strcmp (kstr, "strMem") == 0)
02588     {
02589       smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
02590       mem->next = strMemList;
02591       mem->name = sname;
02592       mem->sortname = bname;
02593       mem->sort = NOSORTHANDLE;
02594       strMemList = mem;
02595     }
02596   else if (strcmp (sostr, "strEnd") == 0)
02597     {                           /* now process it */
02598       if (strName != lsymbol_undefined && strMemList != NULL)
02599         {
02600           sort asort = sort_construct (strName, SRT_STRUCT, NOSORTHANDLE, tagName,
02601                                   TRUE, NOSORTHANDLE, strMemList);
02602           
02603           if (tagName != lsymbol_undefined)
02604             {
02605               tagid = ltoken_create (simpleId, tagName);
02606 
02607               ti = (tagInfo) dmalloc (sizeof (*ti));
02608               ti->sort = asort;
02609               ti->kind = TAG_STRUCT;
02610               ti->id = tagid;
02611               ti->imported = FALSE;
02612               
02613               (void) symtable_enterTagForce (g_symtab, ti);
02614             }
02615         }
02616       else
02617         {
02618           if (strName == lsymbol_undefined)
02619             {
02620               lclbug (message ("%q: Imported file contains unexpected null struct sort",
02621                                fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
02622             }
02623           else
02624             {
02625               /*
02626                ** no members -> its a forward struct
02627                */
02628               
02629               if (tagName != lsymbol_undefined)
02630                 {
02631                   tagid = ltoken_create (simpleId, tagName);
02632                   (void) checkAndEnterTag (TAG_FWDSTRUCT, tagid);
02633                 }
02634             }
02635         }
02636       strName = lsymbol_undefined;
02637       strMemList = NULL;
02638       tagName = lsymbol_undefined;
02639     }
02640   else if (strcmp (kstr, "str") == 0)
02641     {
02642       if (strName != lsymbol_undefined || strMemList != NULL)
02643         {
02644           lclbug (message ("%q: unexpected non-null struct sort or "
02645                            "non-empty member list",
02646                            fileloc_unparseRaw (cstring_fromChars (importfile), 
02647                                                tsource_thisLineNumber (s))));
02648         }
02649       /* see if a tag is associated with this sort */
02650       if (strcmp (basedstr, "nil") == 0)
02651         {
02652           llfatalerror (message ("%s: Struct missing tag.  Obsolete .lcs file, remove and rerun lcl.",
02653                                  cstring_fromChars (importfile)));
02654           /*
02655             strName = sortTag_toSymbol ("Struct", nulltok, &tmp);
02656             tagName = lsymbol_undefined;
02657             mapping_bind (map, sname, strName);
02658             */
02659         }
02660       else /* a tag exists */
02661         {  /* create tag in symbol table and add tagged sort in sort table */
02662           tagName = bname;
02663           tagid = ltoken_create (simpleId, bname);
02664 
02665           strName = sortTag_toSymbol ("Struct", tagid, &tmp);
02666           ti = symtable_tagInfo (g_symtab, tagName);
02667 
02668           /*
02669           ** No error for redefining a tag in an import.
02670           */
02671         }
02672       /* to be processed later in sort_import */
02673       lsymbolList_addh (slist, strName);
02674     }
02675   else if (strcmp (kstr, "enumMem") == 0)
02676     {
02677       smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
02678       mem->next = enumMemList;
02679       mem->sortname = enumName;
02680       mem->name = sname;
02681       mem->sort = NOSORTHANDLE;
02682       enumMemList = mem;
02683     }
02684   else if (strcmp (sostr, "enumEnd") == 0)
02685     {
02686       if (enumName != lsymbol_undefined && enumMemList != NULL)
02687         {
02688           sort asort = sort_construct (enumName, SRT_ENUM, NOSORTHANDLE, tagName,
02689                                        FALSE, NOSORTHANDLE, enumMemList);
02690           
02691           if (tagName != lsymbol_undefined)
02692             {
02693               tagid = ltoken_create (simpleId, tagName);
02694 
02695               ti = (tagInfo) dmalloc (sizeof (*ti));
02696               ti->sort = asort;
02697               ti->kind = TAG_ENUM;
02698               ti->id = tagid;
02699               ti->imported = FALSE;
02700 
02701               (void) symtable_enterTagForce (g_symtab, ti);
02702             }
02703         }
02704       else
02705         {
02706           lclbug (message ("%q: unexpected null enum sort or empty member list",
02707                            fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
02708         }
02709       enumName = lsymbol_undefined;
02710       enumMemList = NULL;
02711       tagName = lsymbol_undefined;
02712     }
02713   else if (strcmp (kstr, "enum") == 0)
02714     {
02715       if (enumName != lsymbol_undefined || enumMemList != NULL)
02716         {
02717           lclbug (message ("%q: Unexpected non-null enum sort or "
02718                            "non-empty member list",
02719                            fileloc_unparseRaw (cstring_fromChars (importfile), 
02720                                                tsource_thisLineNumber (s))));
02721         }
02722 
02723       /* see if a tag is associated with this sort */
02724       if (strcmp (basedstr, "nil") == 0)
02725         {
02726           llfatalerror (message ("%s: Enum missing tag.  Obsolete .lcs file, "
02727                                  "remove and rerun lcl.",
02728                                  cstring_fromChars (importfile)));
02729         }
02730       else
02731         {                       /* a tag exists */
02732           tagName = bname;
02733           tagid = ltoken_create (simpleId, bname);
02734           enumName = sortTag_toSymbol ("Enum", tagid, &tmp);
02735           ti = symtable_tagInfo (g_symtab, bname);
02736         }
02737     }
02738   else if (strcmp (kstr, "unionMem") == 0)
02739     {
02740       smemberInfo *mem = (smemberInfo *) dmalloc (sizeof (*mem));
02741       mem->next = unionMemList;
02742       mem->sortname = bname;
02743       mem->name = sname;
02744       mem->sort = NOSORTHANDLE;
02745       unionMemList = mem;
02746     }
02747   else if (strcmp (sostr, "unionEnd") == 0)
02748     {
02749       if (unionName != lsymbol_undefined && unionMemList != NULL)
02750         {
02751           sort asort = sort_construct (unionName, SRT_UNION, NOSORTHANDLE, tagName,
02752                                        FALSE, NOSORTHANDLE, unionMemList);
02753 
02754           if (tagName != lsymbol_undefined)
02755             {
02756               tagid = ltoken_create (simpleId, tagName);
02757 
02758               ti = (tagInfo) dmalloc (sizeof (*ti));
02759               ti->sort = asort;
02760               ti->kind = TAG_UNION;
02761               ti->id = tagid;
02762               ti->imported = FALSE;
02763 
02764               (void) symtable_enterTagForce (g_symtab, ti);
02765             }
02766         }
02767       else
02768         {
02769           if (unionName == lsymbol_undefined)
02770             {
02771               lclbug
02772                 (message ("%q: Imported file contains unexpected null union sort",
02773                           fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
02774             }
02775           else
02776             {
02777               /*
02778                ** no members -> its a forward struct
02779                */
02780               
02781               if (tagName != lsymbol_undefined)
02782                 {
02783                   tagid = ltoken_create (simpleId, tagName);
02784 
02785                   (void) checkAndEnterTag (TAG_FWDUNION, tagid);
02786                 }
02787             }
02788         }
02789 
02790       unionName = lsymbol_undefined;
02791       unionMemList = NULL;
02792       tagName = lsymbol_undefined;
02793     }
02794   else if (strcmp (kstr, "union") == 0)
02795     {
02796       if (unionName != lsymbol_undefined || unionMemList != NULL)
02797         {
02798           lclbug
02799             (message 
02800              ("%q: Unexpected non-null union sort or non-empty "
02801               "member list",
02802               fileloc_unparseRaw (cstring_fromChars (importfile), tsource_thisLineNumber (s))));
02803         }
02804       /* see if a tag is associated with this sort */
02805       if (strcmp (basedstr, "nil") == 0)
02806         {
02807           llfatalerror
02808             (message ("%s: Union missing tag.  Obsolete .lcs file, "
02809                       "remove and rerun lcl.",
02810               cstring_fromChars (importfile)));
02811         }
02812       else
02813         {                       /* a tag exists */
02814           tagName = bname;
02815           tagid = ltoken_create (simpleId, bname);
02816 
02817           unionName = sortTag_toSymbol ("Union", tagid, &tmp);
02818           ti = symtable_tagInfo (g_symtab, bname);
02819         }
02820       lsymbolList_addh (slist, unionName);
02821     }
02822   else if (strcmp (kstr, "immutable") == 0)
02823     {
02824       (void) sort_constructAbstract (sname, FALSE, NOSORTHANDLE);
02825     }
02826   else if (strcmp (kstr, "hof") == 0)
02827     {
02828       (void) sort_construct (sname, SRT_HOF, NOSORTHANDLE, lsymbol_undefined,
02829                              FALSE, NOSORTHANDLE, smemberInfo_undefined);
02830     }
02831   else
02832     {
02833       sort bsort = sort_lookupName (lsymbol_translateSort (map, bname));
02834 
02835       if (sort_isNoSort (bsort))
02836         {
02837           lineptr = strchr (line, ' '); /* go past "sort" */
02838           llassert (lineptr != NULL);
02839           lineptr = strchr (lineptr + 1, ' ');  /* go past sostr */
02840           llassert (lineptr != NULL);
02841           lineptr = strchr (lineptr + 1, ' ');  /* go past kstr */
02842           llassert (lineptr != NULL);
02843           col = 5 + lineptr - line;     /* 5 for initial "%LCL "*/
02844 
02845           llbug 
02846             (message ("%q: Imported file contains unknown base sort: %s",
02847                       fileloc_unparseRawCol (cstring_fromChars (importfile), 
02848                                              tsource_thisLineNumber (s), col),
02849                       cstring_fromChars (lsymbol_toCharsSafe (bname))));
02850         }
02851       
02852       if (strcmp (kstr, "vec") == 0)
02853         {                       
02854           objName = lsymbol_fromChars (objstr);
02855           objSort = sort_lookupName (lsymbol_translateSort (map, objName));
02856           (void) sort_construct (sname, SRT_VECTOR, bsort, lsymbol_undefined,
02857                                  FALSE, objSort, smemberInfo_undefined);
02858         }
02859       else
02860         {
02861           sort_loadOther (kstr, sname, bsort);
02862         }
02863     } 
02864 }
02865 
02866 void
02867 sort_import (tsource *imported, ltoken tok, mapping * map)
02868 {
02869   /* tok is only used for error message line number */
02870   char *buf, *importfile;
02871   tsource *lclsource;
02872   sort bsort;
02873   lsymbolList slist = lsymbolList_new ();
02874 
02875   buf = tsource_nextLine (imported);
02876 
02877   llassert (buf != NULL);
02878 
02879   importfile = tsource_fileName (imported);
02880 
02881   if (!firstWord (buf, "%LCLSortTable"))
02882     {
02883       lclsource = LCLScanSource ();
02884 
02885       lclfatalerror (tok, message ("Expecting \"%%LCLSortTable\" line "
02886                                    "in import file %s:\n%s",
02887                                    cstring_fromChars (importfile), 
02888                                    cstring_fromChars (buf)));
02889       
02890     }
02891 
02892   for (;;)
02893     {
02894       buf = tsource_nextLine (imported);
02895 
02896       llassert (buf != NULL);
02897 
02898       if (firstWord (buf, "%LCLSortTableEnd"))
02899         {
02900           break;
02901         }
02902       else
02903         { /* a good line, remove %LCL from line first */
02904           if (firstWord (buf, "%LCL"))
02905             {
02906               parseSortLine (buf + 4, tok, imported, map, slist);
02907             }
02908           else
02909             {
02910               lclsource = LCLScanSource ();
02911               lclfatalerror
02912                 (tok, 
02913                  message ("Expecting '%%LCL' prefix in import file %s:\n%s\n",
02914                           cstring_fromChars (importfile), 
02915                           cstring_fromChars (buf)));
02916             }
02917         }
02918     }
02919 
02920   /* now process the smemberInfo in the sort List */
02921   lsymbolList_elements (slist, s)
02922     {
02923       if (s != lsymbol_undefined)
02924         {
02925           sort sor;
02926           sortNode sn;
02927 
02928           sor = sort_lookupName (s);
02929           sn = sort_quietLookup (sor);
02930           
02931           switch (sn.kind)
02932             {
02933             case SRT_ENUM:
02934               {                 /* update the symbol table with members of enum */
02935                 varInfo vi;
02936                 smemberInfo *mlist = sn.members;
02937                 for (; mlist != NULL; mlist = mlist->next)
02938                   {
02939                     /* check that enumeration constants are unique */
02940                     vi = symtable_varInfo (g_symtab, mlist->name);
02941                     if (!varInfo_exists (vi))
02942                       { /* put info into symbol table */
02943                         vi = (varInfo) dmalloc (sizeof (*vi));
02944                         vi->id = ltoken_create (NOTTOKEN, mlist->name);
02945                         vi->kind = VRK_ENUM;
02946                         vi->sort = sor;
02947                         vi->export = TRUE;
02948 
02949                         (void) symtable_enterVar (g_symtab, vi);
02950                         varInfo_free (vi);
02951                       }
02952                     else
02953                       {
02954                         lclplainerror 
02955                           (message ("%s: enum member %s of %s has already been declared",
02956                                     cstring_fromChars (importfile), 
02957                                     lsymbol_toString (mlist->name),
02958                                     lsymbol_toString (sn.name)));
02959                       }
02960                   }
02961                 /*@switchbreak@*/ break;
02962               }
02963             case SRT_STRUCT:
02964             case SRT_UNION:
02965               {
02966                 smemberInfo *mlist = sn.members;
02967 
02968                 for (; mlist != NULL; mlist = mlist->next)
02969                   {
02970                     bsort = sort_lookupName (lsymbol_translateSort (map, mlist->sortname));
02971                     if (sort_isNoSort (bsort))
02972                       {
02973                         lclbug (message ("%s: member %s of %s has unknown sort\n",
02974                                          cstring_fromChars (importfile), 
02975                                          cstring_fromChars (lsymbol_toChars (mlist->name)),
02976                                          cstring_fromChars (lsymbol_toChars (sn.name))));
02977                       }
02978                     else
02979                       {
02980                         mlist->sort = bsort;
02981                       }
02982                   }
02983                 /*@switchbreak@*/ break;
02984               }
02985             default:
02986               lclbug (message ("%s: %s has unexpected sort kind %s",
02987                                cstring_fromChars (importfile), 
02988                                cstring_fromChars (lsymbol_toChars (sn.name)),
02989                                sort_unparseKind (sn.kind)));
02990             }
02991         }
02992     } end_lsymbolList_elements;
02993   
02994   /* list and sorts in it are not used anymore */
02995   lsymbolList_free (slist);
02996 }
02997 
02998 bool
02999 sort_equal (sort *s1, sort *s2)
03000 {
03001   sort syn1, syn2;
03002   if ((s1 != 0) && (s2 != 0))
03003     {
03004       if ((*s1) == (*s2))
03005         return TRUE;
03006      /* handle synonym sorts */
03007       syn1 = sort_getUnderlying (*s1);
03008       syn2 = sort_getUnderlying (*s2);
03009       if (syn1 == syn2)
03010         return TRUE;
03011      /* makes bool and Bool equal */
03012     }
03013   return FALSE;
03014 }
03015 
03016 bool
03017 sort_compatible (sort s1, sort s2)
03018 {
03019   sort syn1, syn2;
03020  /* later: might consider "char" and enum types the same as "int" */
03021   if (s1 == s2)
03022     return TRUE;
03023  /* handle synonym sorts */
03024   syn1 = sort_getUnderlying (s1);
03025   syn2 = sort_getUnderlying (s2);
03026   if (syn1 == syn2)
03027     return TRUE;
03028   /* makes bool and Bool equal */
03029   return FALSE;
03030 }
03031 
03032 bool
03033 sort_compatible_modulo_cstring (sort s1, sort s2)
03034 {
03035  /* like sort_compatible but also handles special cstring inits,
03036     allows the following 2 cases:
03037      char c[] = "abc"; (LHS: char_Obj_Arr, RHS = char_Vec)
03038                        (c as implicitly coerced into c^)
03039      char *d = "abc";  (LHS: char_Obj_Ptr, RHS = char_Vec)
03040                        (d as implicitly coerced into d[]^)
03041                        */
03042   sort syn1, syn2;
03043   if (sort_compatible (s1, s2))
03044     return TRUE;
03045   syn1 = sort_getUnderlying (s1);
03046   syn2 = sort_getUnderlying (s2);
03047   if (sort_cstring == syn2 &&
03048       (syn1 == char_obj_ptrSort || syn1 == char_obj_ArrSort))
03049     return TRUE;
03050   return FALSE;
03051 }
03052 
03053 lsymbol
03054 sort_getLsymbol (sort sor)
03055 {
03056  /*  sortNode sn = sort_lookup (sor); */
03057   sortNode sn = sort_quietLookup (sor);
03058   return sn.name;
03059 }
03060 
03061 /* a few handy routines for debugging */
03062 
03063 char *sort_getName (sort s)
03064 {
03065   return (lsymbol_toCharsSafe (sort_getLsymbol (s)));
03066 }
03067 
03068 /*@exposed@*/ cstring
03069 sort_unparseName (sort s)
03070 {
03071     return (cstring_fromChars (sort_getName (s)));
03072 }
03073 
03074 static void
03075 sortError (ltoken t, sort oldsort, sortNode newnode)
03076 {
03077   sortNode old = sort_quietLookup (oldsort);
03078 
03079   if ((old.kind <= SRT_FIRST || old.kind >= SRT_LAST) ||
03080       (newnode.kind <= SRT_FIRST || newnode.kind >= SRT_LAST))
03081     {
03082       llbuglit ("sortError: illegal sort kind");
03083     }
03084 
03085   llassert (sortTable != NULL);
03086 
03087   lclerror (t, message ("Sort %s defined as %s cannot be redefined as %s",
03088                         cstring_fromChars (lsymbol_toChars (newnode.name)),
03089                         sort_unparseKindName (sortTable[oldsort]),
03090                         sort_unparseKindName (newnode)));
03091 }
03092 
03093 static /*@observer@*/ cstring
03094   sort_unparseKindName (sortNode s)
03095 {
03096   switch (s.kind)
03097     {
03098     case SRT_NONE:
03099       return cstring_fromChars (sortKindName[(int)s.kind]);
03100     default:
03101       if (s.abstract)
03102         {
03103           if (s.mutable)
03104             {
03105               return cstring_makeLiteralTemp ("MUTABLE");
03106             }
03107           else
03108             {
03109               return cstring_makeLiteralTemp ("IMMUTABLE");
03110             }
03111         }
03112       else
03113         return cstring_fromChars (sortKindName[(int)s.kind]);
03114     }
03115   
03116   BADEXIT;
03117 }
03118 
03119 sort
03120 sort_fromLsymbol (lsymbol sortid)
03121 {
03122  /* like sort_lookupName but creates sort if not already present */
03123   sort sort = sort_lookupName (sortid);
03124   if (sort == NOSORTHANDLE)
03125     sort = sort_makeSort (ltoken_undefined, sortid);
03126   return sort;
03127 }
03128 
03129 bool
03130 sort_isHOFSortKind (sort s)
03131 {
03132   sortNode sn = sort_quietLookup (s);
03133   if (sn.kind == SRT_HOF)
03134     return TRUE;
03135   return FALSE;
03136 }
03137 
03138 /*
03139 ** returns TRUE iff s has State operators (', ~, ^)
03140 */
03141 
03142 static bool
03143 sort_hasStateFcns (sort s)
03144 {
03145   sortNode sn = sort_quietLookup (s);
03146   sortKind kind = sn.kind;
03147 
03148   if (kind == SRT_SYN)
03149     {
03150       return (sort_hasStateFcns (sn.baseSort));
03151     }
03152 
03153   return ((kind == SRT_PTR) ||
03154           (kind == SRT_OBJ) ||
03155           (kind == SRT_ARRAY) ||
03156           (kind == SRT_STRUCT) ||
03157           (kind == SRT_UNION));
03158 }
03159 
03160 

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