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

usymtab_interface.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 ** usymtab_interface.c
00026 **
00027 ** Grammar interface to symtab.
00028 **
00029 ** The LCLint parser will build symbol tables for abstract types and
00030 ** function declarations.
00031 **
00032 */
00033 
00034 # include "lclintMacros.nf"
00035 # include "llbasic.h"
00036 # include "gram.h"
00037 # include "lclscan.h"
00038 # include "lclsyntable.h"
00039 # include "lslparse.h"
00040 # include "usymtab_interface.h"
00041 # include "structNames.h"
00042 
00043 static void 
00044   declareFcnAux (fcnNode p_f, /*@only@*/ qtype p_qt, ctype p_ct, typeId p_tn, 
00045                  bool p_priv, bool p_spec);
00046 
00047 static uentryList paramNodeList_toUentryList (paramNodeList p_p);
00048 static /*@observer@*/ cstring getVarName (/*@null@*/ typeExpr p_x);
00049 static qtype convertLclTypeSpecNode (/*@null@*/ lclTypeSpecNode p_n);
00050 static ctype convertTypeExpr (ctype p_c, /*@null@*/ typeExpr p_x);
00051 static ctype convertCTypeExpr (ctype p_c, /*@null@*/ typeExpr p_x);
00052 static /*@exposed@*/ sRef fixTermNode (termNode p_n, fcnNode p_f, uentryList p_cl);
00053 static sRefSet fixModifies (fcnNode p_f, uentryList p_cl);
00054 
00055 static uentryList
00056   convertuentryList (stDeclNodeList x)
00057 {
00058   uentryList fl = uentryList_new ();
00059 
00060   
00061   stDeclNodeList_elements (x, i)
00062   {
00063     declaratorNodeList d = i->declarators;
00064     qtype q = convertLclTypeSpecNode (i->lcltypespec);
00065 
00066     declaratorNodeList_elements (d, j)
00067     {
00068       idDecl id;
00069 
00070       qtype_setType (q, convertTypeExpr (qtype_getType (q), j->type));
00071       id = idDecl_create (cstring_copy (getVarName (j->type)), qtype_copy (q));
00072       fl = uentryList_add (fl, uentry_makeIdVariable (id));
00073       idDecl_free (id);
00074     } end_declaratorNodeList_elements;
00075 
00076     qtype_free (q);
00077   } end_stDeclNodeList_elements;
00078 
00079   
00080   return (fl);
00081 }
00082 
00083 static uentryList
00084   convert_uentryList (paramNodeList x)
00085 {
00086   uentryList p = uentryList_undefined;
00087   bool first_one = TRUE;
00088 
00089   
00090   paramNodeList_elements (x, i)
00091   {
00092     if (i != (paramNode) 0)
00093       {
00094         if (paramNode_isElipsis (i))
00095           {
00096             first_one = FALSE;
00097             p = uentryList_add (p, uentry_makeElipsisMarker ());
00098           }
00099         else
00100           {
00101             qtype q = convertLclTypeSpecNode (i->type);
00102             typeExpr t = i->paramdecl;
00103             
00104             qtype_setType (q, convertTypeExpr (qtype_getType (q), t));
00105             
00106             /* note: has to be like this to hack around void  ???? still */ 
00107 
00108             if (first_one)
00109               {
00110                 if (ctype_isVoid (qtype_getType (q)))
00111                   {
00112                     llassert (uentryList_isUndefined (p));
00113                     qtype_free (q);
00114                     return (p);
00115                   }
00116                 
00117                 first_one = FALSE;
00118               }
00119             
00120             /*
00121             ** don't do qualifiers here, will get errors later
00122             */
00123 
00124             p = uentryList_add (p, uentry_makeUnnamedVariable (qtype_getType (q)));
00125             qtype_free (q);
00126           }
00127       }
00128     else
00129       {
00130         llbug (cstring_makeLiteral ("convertuentryList: null paramNode"));
00131       }
00132   } end_paramNodeList_elements;
00133   
00134   if (first_one)
00135     {
00136       llassert (uentryList_isUndefined (p));
00137       
00138       p = uentryList_makeMissingParams ();
00139     }
00140 
00141   return p;
00142 }
00143 
00144 /*
00145 ** convertTypeExpr
00146 **
00147 ** modify c with pointer, array, function
00148 **
00149 ** (based on printTypeExpr2 from abstract.c)
00150 **
00151 */
00152 
00153 static ctype
00154 convertTypeExpr (ctype c, typeExpr x)
00155 {
00156   if (x == (typeExpr) 0)
00157     {
00158       return c;
00159     }
00160   
00161   switch (x->kind)
00162     {
00163     case TEXPR_BASE:
00164       return (c);
00165     case TEXPR_PTR:
00166       return (convertTypeExpr (ctype_makePointer (c), x->content.pointer));
00167     case TEXPR_ARRAY:
00168       return (convertTypeExpr (ctype_makeArray (c), x->content.array.elementtype));
00169     case TEXPR_FCN:
00170       {
00171         ctype rv = convertTypeExpr (c, x->content.function.returntype);
00172         uentryList p = paramNodeList_toUentryList (x->content.function.args);
00173         
00174         if (x->content.function.returntype != NULL
00175             && x->content.function.returntype->wrapped == 1 
00176             && ctype_isPointer (rv))
00177           {
00178             rv = ctype_baseArrayPtr (rv);
00179           }
00180 
00181         return (ctype_makeParamsFunction (rv, p));
00182       }
00183     default:
00184       {
00185         llfatalbug (message ("convertTypeExpr: unknown typeExprKind: %d",
00186                              (int) x->kind));
00187       }
00188     }
00189 
00190   BADEXIT;
00191 }
00192 
00193 static 
00194 ctype convertCTypeExpr (ctype c, typeExpr x)
00195 {
00196   if (x == (typeExpr) 0)
00197     {
00198       return c;
00199     }
00200 
00201   switch (x->kind)
00202     {
00203     case TEXPR_BASE:     return (c);
00204     case TEXPR_PTR:  return (convertCTypeExpr (ctype_makePointer (c), 
00205                                                  x->content.pointer));
00206     case TEXPR_ARRAY:    return (convertCTypeExpr (ctype_makeArray (c), 
00207                                                  x->content.array.elementtype));
00208     case TEXPR_FCN:
00209       {
00210         ctype rv = convertCTypeExpr (c, x->content.function.returntype);
00211         uentryList p = convert_uentryList (x->content.function.args);
00212 
00213         return (ctype_makeParamsFunction (rv, p));
00214       }
00215     default:
00216       {
00217         llfatalbug (message ("convertCTypeExpr: unknown typeExprKind: %d", (int) x->kind));
00218       }
00219     }
00220   BADEXIT;
00221 }
00222 
00223 /*
00224 ** convertLclTypeSpecNode
00225 **
00226 ** LclTypeSpecNode --> ctype
00227 ** this is the base type only!
00228 */
00229 
00230 /*
00231 ** convertLeaves
00232 **
00233 ** for now, assume only last leaf is relevant.
00234 ** this should be a safe assumption in general???
00235 */
00236 
00237 static ctype
00238   convertLeaves (ltokenList f)
00239 {
00240   ctype c = ctype_unknown;
00241   
00242   ltokenList_reset (f);
00243   
00244   ltokenList_elements (f, current)
00245     {
00246       switch (ltoken_getCode (current))
00247         {
00248         case LLT_TYPEDEF_NAME:
00249           {
00250             cstring tn = ltoken_getRawString (current);
00251 
00252             if (usymtab_existsTypeEither (tn))
00253               {
00254                 c = ctype_combine (uentry_getAbstractType 
00255                                    (usymtab_lookupEither (tn)), c);
00256               }
00257             else if (cstring_equalLit (tn, "bool"))
00258               {
00259                 /*
00260                 ** Bogus...keep consistent with old lcl builtin.
00261                 */
00262                 c = ctype_bool;
00263               }
00264             else
00265               {
00266                 fileloc loc = fileloc_fromTok (current);
00267 
00268                 voptgenerror (FLG_UNRECOG, 
00269                               message ("Unrecognized type: %s", tn), loc);
00270                 fileloc_free (loc);
00271                 
00272                 usymtab_supEntry 
00273                   (uentry_makeDatatype 
00274                    (tn, ctype_unknown, MAYBE, NO, fileloc_getBuiltin ()));
00275                 
00276               }
00277             /*@switchbreak@*/ break;
00278           }
00279         case LLT_CHAR:
00280           c = ctype_combine (ctype_char, c);
00281           /*@switchbreak@*/ break;
00282           
00283         case LLT_DOUBLE:
00284           c = ctype_combine (ctype_double, c);
00285           /*@switchbreak@*/ break;
00286         case LLT_FLOAT:     
00287           c = ctype_combine (ctype_float, c);
00288           /*@switchbreak@*/ break;
00289         case LLT_CONST:    
00290         case LLT_VOLATILE: 
00291           /*@switchbreak@*/ break;
00292         case LLT_INT:      
00293           c = ctype_combine (ctype_int, c);
00294           /*@switchbreak@*/ break;
00295         case LLT_LONG:  
00296           c = ctype_combine (c, ctype_lint); 
00297           /*@switchbreak@*/ break;
00298         case LLT_SHORT:    
00299           c = ctype_combine (c, ctype_sint);
00300           /*@switchbreak@*/ break;
00301         case LLT_SIGNED:    
00302           c = ctype_combine (c, ctype_int); 
00303           /*@switchbreak@*/ break;
00304         case LLT_UNSIGNED:  
00305           c = ctype_combine (c, ctype_uint);
00306           /*@switchbreak@*/ break;
00307         case LLT_UNKNOWN:   
00308           c = ctype_combine (ctype_unknown, c);
00309           /*@switchbreak@*/ break;
00310         case LLT_VOID:      
00311           c = ctype_combine (ctype_void, c); 
00312           /*@switchbreak@*/ break;
00313         case LLT_ENUM:
00314           llcontbug (cstring_makeLiteral ("convertLeaves: enum"));
00315           c = ctype_int; 
00316           /*@switchbreak@*/ break;
00317         default:
00318           llfatalbug (message ("convertLeaves: bad token: %q", 
00319                                ltoken_unparseCodeName (current)));
00320         }
00321     } end_ltokenList_elements;
00322 
00323   return c;
00324 }
00325 
00326 static enumNameList
00327   convertEnumList (ltokenList enums)
00328 {
00329   enumNameList el = enumNameList_new ();
00330 
00331   if (ltokenList_isDefined (enums))
00332     {
00333       ltokenList_elements (enums, i)
00334         {
00335           enumNameList_addh 
00336             (el, enumName_create (cstring_copy (ltoken_unparse (i))));
00337         } end_ltokenList_elements;
00338     }
00339 
00340   return el;
00341 }
00342 
00343 static /*@only@*/ qtype 
00344   convertLclTypeSpecNode (/*@null@*/ lclTypeSpecNode n)
00345 {
00346   
00347   if (n != (lclTypeSpecNode) 0)
00348     {
00349       qtype result;
00350       
00351       switch (n->kind)
00352         {
00353         case LTS_CONJ:
00354           {
00355             qtype c1 = convertLclTypeSpecNode (n->content.conj->a);
00356             qtype c2 = convertLclTypeSpecNode (n->content.conj->b);
00357 
00358             /*
00359             ** Is it explicit?
00360             */
00361 
00362             if (fileloc_isLib (g_currentloc)
00363                 || fileloc_isStandardLibrary (g_currentloc))
00364               {
00365                 result = qtype_mergeImplicitAlt (c1, c2);
00366               }
00367             else
00368               {
00369                 result = qtype_mergeAlt (c1, c2);
00370               }
00371             
00372             break;
00373           }
00374         case LTS_TYPE:
00375           llassert (n->content.type != NULL);
00376           result = qtype_create (convertLeaves (n->content.type->ctypes));
00377           break;
00378         case LTS_STRUCTUNION:
00379           {
00380             strOrUnionNode sn;
00381             cstring cn = cstring_undefined;
00382 
00383             sn = n->content.structorunion;
00384 
00385             llassert (sn != (strOrUnionNode) 0);
00386 
00387             if (!ltoken_isUndefined (sn->opttagid))
00388               {
00389                 cn = cstring_copy (ltoken_getRawString (sn->opttagid));
00390               }
00391             else
00392               {
00393                 cn = fakeTag ();
00394               }
00395 
00396             switch (sn->kind)
00397               {
00398               case SU_STRUCT:
00399                 if (usymtab_existsStructTag (cn))
00400                   {
00401                     
00402                     result = qtype_create (uentry_getAbstractType
00403                                            (usymtab_lookupStructTag (cn)));
00404                     cstring_free (cn);
00405                   }
00406                 else
00407                   {
00408                     uentryList fl = convertuentryList (sn->structdecls);
00409                     ctype ct;
00410 
00411                                     ct = ctype_createStruct (cstring_copy (cn), fl);
00412 
00413                     /*
00414                     ** If it was a forward declaration, this could add it to
00415                     ** the table.  Need to check if it exists again...
00416                     */
00417 
00418                     if (usymtab_existsStructTag (cn))
00419                       {
00420                         result = qtype_create (uentry_getAbstractType
00421                                                (usymtab_lookupStructTag (cn)));
00422                       }
00423                     else
00424                       {
00425                         fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
00426                         uentry ue = uentry_makeStructTag (cn, ct, loc);
00427 
00428                         result = qtype_create (usymtab_supTypeEntry (ue));
00429                       }
00430                         
00431                     cstring_free (cn);
00432                   }
00433                 /*@switchbreak@*/ break;
00434               case SU_UNION:
00435                 if (usymtab_existsUnionTag (cn))
00436                   {
00437                     
00438                     result = qtype_create (uentry_getAbstractType
00439                                            (usymtab_lookupUnionTag (cn)));
00440                     cstring_free (cn);
00441                   }
00442                 else
00443                   {
00444                     uentryList fl;
00445                     ctype ct;
00446                     
00447                     fl = convertuentryList (sn->structdecls);
00448                     ct = ctype_createUnion (cstring_copy (cn), fl);
00449 
00450                     /*
00451                     ** If it was a forward declaration, this could add it to
00452                     ** the table.  Need to check if it exists again...
00453                     */
00454 
00455                     
00456                     
00457                     if (usymtab_existsUnionTag (cn))
00458                       {
00459                         
00460                         result = qtype_create (uentry_getAbstractType
00461                                                (usymtab_lookupUnionTag (cn)));
00462                       }
00463                     else
00464                       {
00465                         fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
00466                         uentry ue = uentry_makeUnionTag (cn, ct, loc);
00467 
00468                         result = qtype_create (usymtab_supTypeEntry (ue));
00469                       }
00470                         
00471                     cstring_free (cn);
00472                   }
00473                 /*@switchbreak@*/ break;
00474               BADDEFAULT
00475               }
00476             break;
00477           }
00478         case LTS_ENUM:
00479           {
00480             enumSpecNode e = n->content.enumspec;
00481             enumNameList el;
00482             cstring ename;
00483             bool first = TRUE;
00484             ctype ta;
00485             ctype cet;
00486 
00487             llassert (e != NULL);
00488             el = convertEnumList (e->enums);
00489 
00490             if (!ltoken_isUndefined (e->opttagid))      /* named enumerator */
00491               {
00492                 ename = cstring_copy (ltoken_getRawString (e->opttagid));
00493               }
00494             else
00495               {
00496                 ename = fakeTag ();
00497               }
00498 
00499             cet = ctype_createEnum (ename, el);
00500             
00501             if (usymtab_existsEnumTag (ename))
00502               {
00503                 ta = uentry_getAbstractType (usymtab_lookupEnumTag (ename));
00504               }
00505             else
00506               { 
00507                 fileloc loc = fileloc_fromTok (e->tok);
00508                 uentry ue = uentry_makeEnumTag (ename, cet, loc);
00509 
00510                 ta = usymtab_supTypeEntry (ue);
00511               }
00512 
00513             enumNameList_elements (el, en)
00514               {
00515                 uentry ue;
00516                 fileloc loc;
00517 
00518                 if (first)
00519                   {
00520                     ltokenList_reset (e->enums);
00521                     first = FALSE;
00522                   }
00523                 else
00524                   {
00525                     ltokenList_advance (e->enums);
00526                   }
00527 
00528                 loc = fileloc_fromTok (ltokenList_current (e->enums));
00529                 ue = uentry_makeSpecEnumConstant (en, cet, loc);
00530 
00531                 /*
00532                 ** Can't check name here, might not have
00533                 ** type yet.  Will check in .lh file?
00534                 */
00535                 
00536                 ue = usymtab_supGlobalEntryReturn (ue);
00537                 
00538                 if (context_inLCLLib ())
00539                   {
00540                     uentry_setDefined (ue, loc);
00541                   }
00542               } end_enumNameList_elements;
00543             
00544             result = qtype_create (ta);
00545           }
00546           break;
00547         default:
00548           {
00549             llfatalbug (message ("convertLclTypeSpecNode: unknown lclTypeSpec kind: %d",
00550                                  (int) n->kind));
00551           }
00552         }
00553       
00554       result = qtype_addQualList (result, n->quals);
00555 
00556       if (n->pointers > 0)
00557         {
00558           qtype_adjustPointers (n->pointers, result);
00559         }
00560 
00561       return result;
00562     }
00563   else
00564     {
00565       llcontbug (cstring_makeLiteral ("convertLclTypeSpecNode: null"));
00566       return qtype_unknown (); 
00567     }
00568   BADEXIT;
00569 } 
00570 
00571 static /*@only@*/ multiVal
00572   literalValue (ctype ct, ltoken lit)
00573 {
00574   cstring text = cstring_fromChars (lsymbol_toChars (ltoken_getText (lit)));
00575   char first;
00576 
00577   if (cstring_length (text) > 0)
00578     {
00579       first = cstring_firstChar (text);
00580     }
00581   else
00582     {
00583       return multiVal_unknown ();
00584     }
00585 
00586   
00587   if /*@-usedef@*/ (first == '\"') /*@=usedef@*/
00588     {
00589       int len = cstring_length (text) - 2;
00590       char *val = mstring_create (len);
00591       
00592       llassert (cstring_lastChar (text) == '\"');
00593       strncpy (val, cstring_toCharsSafe (text) + 1, size_fromInt (len));
00594       return (multiVal_makeString (cstring_fromCharsO (val)));
00595     }
00596 
00597   if (ctype_isDirectInt (ct) || ctype_isPointer (ct))
00598     {
00599       long val = 0;
00600      
00601       if (sscanf (cstring_toCharsSafe (text), "%ld", &val) == 1)
00602         {
00603           return multiVal_makeInt (val);
00604         }
00605     }
00606 
00607   return multiVal_unknown ();
00608 }
00609 
00610 
00611 /*
00612 ** declareConstant
00613 **
00614 ** unfortunately, because the abstract types are different, this
00615 ** cannot be easily subsumed into declareVar.
00616 */
00617 
00618 void
00619 doDeclareConstant (constDeclarationNode c, bool priv)
00620 {
00621   lclTypeSpecNode t;
00622   ctype ctx;
00623   qtype qt;
00624   
00625   if (c == (constDeclarationNode) 0)
00626     {
00627       return;
00628     }
00629 
00630   t = c->type;
00631   qt = convertLclTypeSpecNode (t);
00632 
00633   ctx = qtype_getType (qt);
00634 
00635   initDeclNodeList_elements (c->decls, i)
00636     {
00637       ctype ct = convertTypeExpr (ctx, i->declarator->type);
00638       cstring s = getVarName (i->declarator->type);
00639 
00640       if (ctype_isFunction (ct))
00641         {
00642           fcnNode fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t), 
00643                                                 declaratorNode_copy (i->declarator));
00644 
00645           /* FALSE == unspecified function, only a declaration */
00646 
00647           doDeclareFcn (fcn, typeId_invalid, priv, FALSE);
00648           fcnNode_free (fcn);
00649         }
00650       else
00651         {
00652           uentry ue;
00653           fileloc loc = fileloc_fromTok (i->declarator->id);
00654 
00655           if (i->value != (termNode)0 &&
00656               i->value->kind == TRM_LITERAL)
00657             {
00658               ue = uentry_makeConstantAux (s, ct, loc, priv, 
00659                                            literalValue (ct, i->value->literal));
00660             }
00661           else
00662             {
00663               ue = uentry_makeConstantAux (s, ct, loc, priv, multiVal_unknown ());
00664             }
00665 
00666                   uentry_reflectQualifiers (ue, qtype_getQuals (qt));
00667 
00668           
00669           if (context_inLCLLib () && !priv)
00670             {
00671               uentry_setDefined (ue, loc);
00672             }
00673 
00674           usymtab_supGlobalEntry (ue);
00675         }
00676     } end_initDeclNodeList_elements;
00677 
00678   qtype_free (qt);
00679 }
00680 
00681 static cstring
00682 getVarName (/*@null@*/ typeExpr x)
00683 {
00684   cstring s = cstring_undefined;
00685 
00686   if (x != (typeExpr) 0)
00687     {
00688       switch (x->kind)
00689         {
00690         case TEXPR_BASE:
00691           s = ltoken_getRawString (x->content.base);
00692           break;
00693         case TEXPR_PTR:
00694           s = getVarName (x->content.pointer);
00695           break;
00696         case TEXPR_ARRAY:
00697           s = getVarName (x->content.array.elementtype);
00698           break;
00699         case TEXPR_FCN:
00700           s = getVarName (x->content.function.returntype);
00701           break;
00702         default:
00703           llfatalbug (message ("getVarName: unknown typeExprKind: %d", (int) x->kind));
00704         }
00705     }
00706 
00707   return s;
00708 }
00709 
00710 void
00711 doDeclareVar (varDeclarationNode v, bool priv)
00712 {
00713   lclTypeSpecNode t;
00714   qtype c;
00715 
00716   if (v == (varDeclarationNode) 0)
00717     {
00718       return;
00719     }
00720 
00721   t = v->type;
00722   c = convertLclTypeSpecNode (t);
00723 
00724   initDeclNodeList_elements (v->decls, i)
00725     {
00726       ctype ct = convertTypeExpr (qtype_getType (c), i->declarator->type);
00727       cstring s = getVarName (i->declarator->type);
00728 
00729       qtype_setType (c, ct);
00730 
00731       if (ctype_isFunction (ct))
00732         {
00733           fcnNode fcn;
00734 
00735                   
00736           fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t), 
00737                                         declaratorNode_copy (i->declarator));
00738 
00739           /* FALSE == unspecified function, only a declaration */
00740           declareFcnAux (fcn, qtype_unknown (), ct,
00741                          typeId_invalid, priv, FALSE);
00742           fcnNode_free (fcn);
00743         }
00744       else
00745         {
00746           fileloc loc = fileloc_fromTok (i->declarator->id);
00747           uentry le = uentry_makeVariable (s, ct, loc, priv);
00748           
00749           uentry_reflectQualifiers (le, qtype_getQuals (c));
00750           
00751           if (uentry_isCheckedUnknown (le))
00752             {
00753               if (context_getFlag (FLG_IMPCHECKEDSTRICTSPECGLOBALS))
00754                 {
00755                   uentry_setCheckedStrict (le);
00756                 }
00757               else if (context_getFlag (FLG_IMPCHECKEDSPECGLOBALS))
00758                 {
00759                   uentry_setChecked (le);
00760                 }
00761               else if (context_getFlag (FLG_IMPCHECKMODSPECGLOBALS))
00762                 {
00763                   uentry_setCheckMod (le);
00764                 }
00765               else
00766                 {
00767                   ; /* okay */
00768                 }
00769             }
00770 
00771           if (context_inLCLLib () && !priv)
00772             {
00773               uentry_setDefined (le, loc);
00774             }
00775 
00776           if (initDeclNode_isRedeclaration (i))
00777             {
00778               usymtab_replaceEntry (le);
00779             }
00780           else
00781             {
00782               le = usymtab_supEntrySrefReturn (le);
00783             }
00784         }
00785     } end_initDeclNodeList_elements;
00786 
00787   qtype_free (c);
00788 }
00789 
00790 static globSet
00791 processGlob (/*@returned@*/ globSet globs, varDeclarationNode v)
00792 {
00793   if (v == (varDeclarationNode) 0)
00794     {
00795       return globs;
00796     }
00797 
00798   if (v->isSpecial)
00799     {
00800       globs = globSet_insert (globs, v->sref);
00801     }
00802   else
00803     {
00804       lclTypeSpecNode t = v->type;
00805       qtype qt = convertLclTypeSpecNode (t);
00806       ctype c = qtype_getType (qt);
00807       cstring s;      
00808 
00809       initDeclNodeList_elements (v->decls, i)
00810         {
00811           ctype ct;
00812           uentry ue;
00813           qualList quals = qtype_getQuals (qt);
00814           
00815           s = getVarName (i->declarator->type);
00816           ue = usymtab_lookupGlobSafe (s);
00817           
00818           if (uentry_isInvalid (ue))
00819             {
00820               ; /* error already reported */ 
00821             }
00822           else
00823             {
00824               if (uentry_isPriv (ue))
00825                 {
00826                   globs = globSet_insert (globs, sRef_makeSpecState ());
00827                 }
00828               else
00829                 {
00830                   uentry ce = uentry_copy (ue);
00831                   ctype lt = uentry_getType (ce);
00832                   fileloc loc = fileloc_fromTok (i->declarator->id);
00833                   
00834                   ct = convertTypeExpr (c, i->declarator->type);
00835                   
00836                   if (!ctype_match (lt, ct))
00837                     {
00838                       (void) gentypeerror
00839                         (lt, exprNode_undefined,
00840                          ct, exprNode_undefined,
00841                          message ("Global type mismatch %s (%t, %t)",
00842                                   s, lt, ct), 
00843                          loc);
00844                     }
00845                   
00846                   uentry_reflectQualifiers (ce, quals);
00847                   globs = globSet_insert (globs,
00848                                           sRef_copy (uentry_getSref (ce)));
00849                   fileloc_free (loc);
00850                   uentry_free (ce);
00851                 }
00852             }
00853         } end_initDeclNodeList_elements;
00854 
00855       qtype_free (qt);
00856     }
00857 
00858   return globs;
00859 }
00860 
00861 static void
00862 declareAbstractType (abstractNode n, bool priv)
00863 {
00864   cstring tn;
00865   fileloc loc;
00866   uentry ue;
00867   usymId uid;
00868   abstBodyNode ab;
00869 
00870   if (n == (abstractNode) 0)
00871     {
00872       return;
00873     }
00874 
00875   
00876   tn = ltoken_getRawString (n->name);
00877 
00878   loc = fileloc_fromTok (n->tok);
00879   
00880   ue = uentry_makeDatatypeAux (tn, ctype_unknown, 
00881                                ynm_fromBool (n->isMutable), YES, loc, priv);
00882 
00883   if (n->isRefCounted)
00884     {
00885       uentry_setRefCounted (ue);
00886     }
00887 
00888   if (context_inLCLLib () && !priv)
00889     {
00890       uentry_setDefined (ue, loc);
00891     }
00892 
00893   uid = usymtab_supAbstractTypeEntry (ue, context_inLCLLib() && !priv);
00894   
00895 
00896   if (!priv && (ab = n->body) != (abstBodyNode) 0)
00897     {
00898       fcnNodeList ops = ab->fcns;
00899 
00900       if (!fcnNodeList_isEmpty (ops))
00901         {
00902           fcnNodeList_elements (ops, i)
00903           {
00904             if (i->typespec == (lclTypeSpecNode) 0)
00905               {
00906                 cstring fname = ltoken_getRawString (i->name);
00907 
00908                 if (usymtab_exists (fname))
00909                   {
00910                     uentry e = usymtab_lookup (fname);
00911                     fileloc floc = fileloc_fromTok (i->declarator->id);
00912 
00913                     if (uentry_isForward (e))
00914                       {
00915                         usymtab_supEntry  
00916                           (uentry_makeTypeListFunction 
00917                            (fname, typeIdSet_insert (uentry_accessType (e), uid), 
00918                             floc));
00919                       }
00920                     else
00921                       {
00922                         usymtab_supEntry 
00923                           (uentry_makeSpecFunction 
00924                            (fname, uentry_getType (e),
00925                             typeIdSet_insert (uentry_accessType (e), uid),
00926                             globSet_undefined,
00927                             sRefSet_undefined,
00928                             floc));
00929                         
00930                         if (context_inLCLLib ())
00931                           {
00932                             llbuglit ("Jolly jeepers Wilma, it ain't dead after all!");
00933                           }
00934                       }
00935                   }
00936                 else
00937                   {
00938                     usymtab_supEntry 
00939                       (uentry_makeForwardFunction (fname, uid, loc));
00940                   }
00941               }
00942             else
00943               {
00944                 declareFcn (i, uid);
00945               }
00946           } end_fcnNodeList_elements;
00947         }
00948     }
00949 }
00950 
00951 static void
00952   declareExposedType (exposedNode n, bool priv)
00953 {
00954   usymId uid;
00955   qtype c;
00956   cstring s;
00957 
00958   
00959   if (n == (exposedNode) 0)
00960     {
00961       return;
00962     }
00963 
00964   c = convertLclTypeSpecNode (n->type);
00965 
00966   declaratorInvNodeList_elements (n->decls, i)
00967   {
00968     ctype realType = convertTypeExpr (qtype_getType (c), i->declarator->type);
00969     fileloc loc = fileloc_fromTok (i->declarator->id);
00970     uentry ue;
00971 
00972     s = getVarName (i->declarator->type);
00973 
00974     ue = uentry_makeDatatypeAux (s, realType, MAYBE, NO, loc, priv);
00975 
00976     uentry_reflectQualifiers (ue, qtype_getQuals (c));
00977     
00978     if (context_inLCLLib () && !priv)
00979       {
00980         uentry_setDefined (ue, loc);
00981       }
00982 
00983     uid = usymtab_supExposedTypeEntry (ue, context_inLCLLib () && !priv);
00984   } end_declaratorInvNodeList_elements;
00985 
00986   qtype_free (c);
00987 }
00988 
00989 /*
00990 ** ah...remember ye old days...
00991 **
00992 ** wow...same thing in THREE symbol tables!  talk about space efficiency
00993 ** (or as Joe Theory once said, its only a constant factor)
00994 */
00995 
00996 void
00997 doDeclareType (typeNode t, bool priv)
00998 {
00999   
01000   if (t != (typeNode) 0)
01001     {
01002       switch (t->kind)
01003         {
01004         case TK_ABSTRACT:
01005           declareAbstractType (t->content.abstract, priv);
01006           break;
01007           
01008         case TK_EXPOSED:
01009           declareExposedType (t->content.exposed, priv);
01010           break;
01011           
01012         case TK_UNION:
01013         default:
01014           {
01015             llfatalbug (message ("declareType ERROR: unknown kind: %q",
01016                                  cstring_fromCharsO (FormatInt ((int)t->kind))));
01017           }
01018         }
01019     }
01020   
01021 }
01022 
01023 extern void
01024 declareIter (iterNode iter)
01025 {
01026   fileloc loc = fileloc_fromTok (iter->name);
01027   uentry ue = 
01028     uentry_makeIter (ltoken_unparse (iter->name), 
01029                      ctype_makeFunction 
01030                      (ctype_void,
01031                       paramNodeList_toUentryList (iter->params)), 
01032                      fileloc_copy (loc));
01033   
01034   usymtab_supEntry (ue);
01035   usymtab_supEntry 
01036     (uentry_makeEndIter (ltoken_unparse (iter->name), loc));
01037 }
01038 
01039 /*
01040 ** declareFcn
01041 */
01042 
01043 static void
01044 declareFcnAux (fcnNode f, /*@only@*/ qtype qt, ctype ct,
01045                typeId tn, bool priv, bool spec)
01046 {
01047   globalList globals;
01048   typeIdSet acct;
01049   sRefSet sl = sRefSet_undefined;
01050   globSet globlist = globSet_undefined;
01051   cstring s = getVarName (f->declarator->type);
01052   fileloc loc = fileloc_fromTok (f->declarator->id);
01053   uentryList args;
01054 
01055   /*
01056   ** type conversion generates args 
01057   */
01058 
01059   if (ctype_isFunction (ct))
01060     {
01061       args = ctype_argsFunction (ct);
01062     }
01063   else
01064     {
01065       llcontbug (message ("Not function: %s", ctype_unparse (ct)));
01066       args = uentryList_undefined;
01067     }
01068 
01069   
01070   fileloc_setColumnUndefined (loc);
01071 
01072   if (spec)
01073     {
01074       globals = f->globals;
01075       
01076             sl = fixModifies (f, args);
01077 
01078       /*
01079       ** Bind let declarations in modifies list 
01080       */
01081 
01082       varDeclarationNodeList_elements (globals, glob)
01083         {
01084           globlist = processGlob (globlist, glob);
01085         } end_varDeclarationNodeList_elements;
01086       
01087       
01088       if (f->checks != (lclPredicateNode) 0)
01089         /* push stderr on globalList */
01090         /* modifies *stderr^ */
01091         {
01092           uentry ue;
01093 
01094           if (!(usymtab_existsVar (cstring_makeLiteralTemp ("stderr"))))
01095             {
01096               ctype tfile;
01097               
01098               llmsglit ("Global stderr implied by checks clause, "
01099                         "not declared in initializations.");
01100 
01101               tfile = usymtab_lookupType (cstring_makeLiteralTemp ("FILE"));
01102               
01103               if (ctype_isUndefined (tfile))
01104                 {
01105                   llmsglit ("FILE datatype implied by checks clause not defined.");
01106                   tfile = ctype_unknown;
01107                 }
01108               
01109               usymtab_supGlobalEntry 
01110                 (uentry_makeVariable (cstring_makeLiteralTemp ("stderr"), 
01111                                      tfile, fileloc_getBuiltin (), FALSE));
01112             }
01113           
01114           ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stderr"));
01115           
01116                   globlist = globSet_insert (globlist, sRef_copy (uentry_getSref (ue)));
01117           sl = sRefSet_insert (sl, sRef_buildPointer (uentry_getSref (ue)));
01118 
01119         }
01120     }
01121 
01122   if (usymId_isInvalid (tn))
01123     {
01124       acct = context_fileAccessTypes ();
01125     }
01126   else
01127     {
01128       acct = typeIdSet_single (tn);
01129     }
01130   
01131   if (usymtab_exists (s))
01132     {
01133       uentry l = usymtab_lookup (s);
01134       uentry ue;
01135 
01136       if (uentry_isForward (l) || (fileloc_isLib (uentry_whereSpecified (l))))
01137         {
01138           typeIdSet accessType;
01139 
01140           if (uentry_isFunction (l))
01141             {
01142               accessType = typeIdSet_union (uentry_accessType (l), 
01143                                             context_fileAccessTypes ());
01144             }
01145           else
01146             {
01147               accessType = context_fileAccessTypes ();
01148             }
01149 
01150           if (spec)
01151             {
01152               ue = uentry_makeSpecFunction (s, ct, accessType, globlist, sl, loc);
01153             }
01154           else
01155             {
01156               sRefSet_free (sl);
01157               globSet_free (globlist);
01158 
01159               ue = uentry_makeUnspecFunction (s, ct, accessType, loc);
01160             }
01161 
01162           uentry_reflectQualifiers (ue, qtype_getQuals (qt));
01163 
01164           usymtab_supEntry (ue);
01165         }
01166       else
01167         {
01168           /*
01169           ** error reported by symtable already
01170           **
01171           ** llgenerror (message ("Function redeclared: %s (previous declaration: %s)", s,
01172           **                  fileloc_unparse (uentry_whereSpecified (l))),
01173           **          loc);
01174           */
01175 
01176           
01177           fileloc_free (loc);
01178           sRefSet_free (sl);
01179           globSet_free (globlist);
01180         }
01181     }
01182   else
01183     {
01184       uentry le;
01185       
01186       if (spec)
01187         {
01188           if (priv)
01189             {
01190               le = uentry_makePrivFunction2 (s, ct, acct, globlist, sl, loc);
01191             }
01192           else
01193             {
01194               le = uentry_makeSpecFunction (s, ct, acct, globlist, sl, loc);
01195             }
01196         }
01197       else
01198         {
01199           le = uentry_makeUnspecFunction (s, ct, acct, loc);
01200 
01201           sRefSet_free (sl);
01202           globSet_free (globlist);
01203         }
01204 
01205       if (context_inLCLLib () && !priv)
01206         {
01207           uentry_setDefined (le, loc);
01208         }      
01209 
01210       uentry_reflectQualifiers (le, qtype_getQuals (qt));
01211 
01212       switch (f->special)
01213         {
01214         case QU_UNKNOWN:     break;
01215         case QU_PRINTFLIKE:  uentry_setPrintfLike (le); break;
01216         case QU_SCANFLIKE:   uentry_setScanfLike (le); break;
01217         case QU_MESSAGELIKE: uentry_setMessageLike (le); break;
01218         BADDEFAULT;
01219         }
01220 
01221       usymtab_supEntry (le);
01222     }
01223 
01224   qtype_free (qt);
01225 }
01226 
01227 extern void
01228 doDeclareFcn (fcnNode f, typeId tn, bool priv, bool spec)
01229 {
01230   qtype qt = convertLclTypeSpecNode (f->typespec);
01231   ctype ct = convertTypeExpr (qtype_getType (qt), f->declarator->type);
01232 
01233     declareFcnAux (f, qt, ct, tn, priv, spec);
01234 }
01235 
01236 /*
01237 ** is s is an argument to f, return its arg no.
01238 ** otherwise, return 0
01239 */
01240 
01241 static int
01242 getParamNo (cstring s, fcnNode f)
01243 {
01244   /* gasp, maybe should do run-time checks here */
01245   paramNodeList params;
01246   typeExpr fd = f->declarator->type;
01247   
01248   /* is this a bug in the LCL grammar? */
01249 
01250   while (fd != NULL && (fd->kind == TEXPR_PTR || fd->kind == TEXPR_ARRAY))
01251     {
01252       if (fd->kind == TEXPR_PTR)
01253         {
01254           fd = fd->content.pointer;
01255         }
01256       else
01257         {
01258           /*@-null@*/ fd = fd->content.array.elementtype; /*@=null@*/
01259          
01260           /*
01261           ** This is a bug in checking, that I should eventually fix.
01262           ** Need some way of deleting the guard from the true branch,
01263           ** but adding it back in the false branch...
01264           */
01265         }
01266     }
01267 
01268   llassert (fd != NULL);
01269 
01270   if (fd->kind != TEXPR_FCN)
01271     {
01272       llfatalbug (message ("getParamNo: not a function: %q (%d)",
01273                            typeExpr_unparse (fd), (int) fd->kind));
01274     }
01275 
01276   params = fd->content.function.args;
01277 
01278   if (paramNodeList_empty (params))
01279     {
01280       return -1;
01281     }
01282   else
01283     {
01284       int pno = 0;
01285 
01286       paramNodeList_elements (params, i)
01287         {
01288           if (i->paramdecl != (typeExpr) 0)     /* handle (void) */
01289             {
01290               if (cstring_equal (s, getVarName (i->paramdecl)))
01291                 {
01292                   return pno;
01293                 }
01294             }
01295           pno++;
01296         } end_paramNodeList_elements;
01297       return -1;
01298     }
01299 }
01300 
01301 static /*@null@*/ /*@observer@*/ termNode
01302 getLetDecl (cstring s, fcnNode f)
01303 {
01304   letDeclNodeList x = f->lets;
01305 
01306   letDeclNodeList_elements (x, i)
01307   {
01308     if (cstring_equal (s, ltoken_getRawString (i->varid)))
01309       {
01310         if (i->sortspec != NULL)
01311           {
01312             llbuglit ("getLetDecl: cannot return sort!");
01313           }
01314         else
01315           {                     /* is a termNode */
01316             return i->term;
01317           }
01318       }
01319   } end_letDeclNodeList_elements;
01320 
01321   return (termNode) 0;
01322 }
01323 
01324 /*
01325 ** processTermNode --- based on printTermNode2
01326 */
01327 
01328 static /*@exposed@*/ sRef 
01329   processTermNode (/*@null@*/ opFormNode op, termNodeList args, 
01330                    fcnNode f, uentryList cl)
01331 {
01332   if (op != (opFormNode) 0)
01333     {
01334       switch (op->kind)
01335         {
01336         case OPF_IF:
01337           llcontbuglit ("processTermNode: OPF_IF: not handled");
01338           break;
01339         case OPF_ANYOP:
01340           llcontbuglit ("processTermNode: OPF_ANYOP: not handled");
01341           break;
01342         case OPF_MANYOP:
01343           {
01344             int size = termNodeList_size (args);
01345 
01346             if (size == 1 
01347                 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "'") ||
01348                     cstring_equalLit (ltoken_getRawString (op->content.anyop), "^")))
01349               {
01350                 return (fixTermNode (termNodeList_head (args), f, cl));
01351               }
01352             else 
01353               {
01354                 ;
01355               }
01356             break;
01357           }
01358         case OPF_ANYOPM:
01359           {
01360             int size = termNodeList_size (args);
01361 
01362             if (size == 1 
01363                 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "*")))
01364               {
01365                 sRef ft;
01366                 sRef res;
01367 
01368                 ft = fixTermNode (termNodeList_head (args), f, cl);
01369                 res = sRef_buildPointer (ft);
01370                 return (res);
01371               }
01372             else
01373               {
01374                 ;
01375               }
01376             break;
01377           }
01378         case OPF_MANYOPM:
01379           llcontbuglit ("OPF_MANYOPM: not handled\n");
01380           break;
01381         case OPF_MIDDLE:
01382           llcontbuglit ("OPF_MIDDLE: not handled\n");
01383           break;
01384         case OPF_MMIDDLE:
01385           llcontbuglit ("OPF_MMIDDLE: not handled\n");
01386           break;
01387         case OPF_MIDDLEM:
01388           llcontbuglit ("OPF_MIDDLEM: not handled\n");
01389           break;
01390         case OPF_MMIDDLEM:
01391           llcontbuglit ("OPF_MMIDDLEM: not handled\n");
01392           break;
01393         case OPF_BMIDDLE:
01394           if (op->content.middle == 1)
01395             llbug (message ("array fetch: [%q]",
01396                             termNodeList_unparse (args)));
01397           else
01398             llcontbuglit ("OPF_BMIDDLE: bad\n");
01399           break;
01400 
01401         case OPF_BMMIDDLE:
01402           if (op->content.middle <= 1)
01403             {
01404               sRef arr = fixTermNode (termNodeList_head (args), f, cl);
01405               sRef ret;
01406 
01407               if (op->content.middle == 1)
01408                 {
01409                   termNode t = (termNodeList_reset (args),
01410                                 termNodeList_advance (args),
01411                                 termNodeList_current (args));
01412                   
01413                   if (t->kind == TRM_LITERAL)
01414                     {
01415                       int i;
01416 
01417                       if (sscanf 
01418                           (cstring_toCharsSafe 
01419                            (ltoken_getRawString (t->literal)),
01420                            "%d", &i) == 1)
01421                         {
01422                           ret = sRef_buildArrayFetchKnown (arr, i);
01423                         }
01424                       else
01425                         {
01426                           ret = sRef_buildArrayFetch (arr);
01427                         }
01428 
01429                       return (ret);
01430                     }
01431                 }
01432                       
01433               /* unknown index */
01434 
01435               ret = sRef_buildArrayFetch (arr);
01436 
01437               return (ret);
01438             }
01439           else 
01440             {
01441               llcontbug (message ("op->content.middle = %d", 
01442                                   op->content.middle));
01443               break;
01444             }
01445 
01446         case OPF_BMIDDLEM:
01447           llcontbuglit ("OPF_BMIDDLEM not handled");
01448           break; 
01449 
01450         case OPF_BMMIDDLEM:
01451           llcontbuglit ("OPF_BMMIDDLEM not handled");
01452           break;
01453 
01454         case OPF_SELECT:
01455           llcontbug (message ("select: .%s", 
01456                               ltoken_getRawString (op->content.id)));
01457           break; 
01458 
01459         case OPF_MAP:
01460           llcontbug (message ("map: .%s", 
01461                               ltoken_getRawString (op->content.id)));
01462           break;
01463 
01464         case OPF_MSELECT:
01465           {
01466             sRef rec = fixTermNode (termNodeList_head (args), f, cl);
01467             sRef ret; 
01468             ctype ct = ctype_realType (sRef_deriveType (rec, cl));
01469             cstring fieldname = ltoken_getRawString (op->content.id);
01470 
01471             ct = ctype_realType (ct);
01472 
01473             /*
01474             ** does it correspond to a typedef struct field
01475             **
01476             ** (kind of kludgey, but there is no direct way to
01477             **  tell if it is an lsl operator instead)
01478             */
01479             
01480             if (ctype_isStructorUnion (ct) &&
01481                 uentry_isValid 
01482                 (uentryList_lookupField (ctype_getFields (ct), fieldname)))
01483               {
01484                 cstring fname = cstring_copy (fieldname);
01485 
01486                 ret = sRef_buildField (rec, fname);
01487                 cstring_markOwned (fname);
01488               }
01489             else
01490               {
01491                 ret = sRef_undefined;
01492               }
01493 
01494             return ret;
01495           }
01496         case OPF_MMAP: 
01497           {
01498             sRef rec = fixTermNode (termNodeList_head (args), f, cl);
01499             sRef ret = sRef_undefined;
01500             ctype ct = ctype_realType (sRef_deriveType (rec, cl));
01501             cstring fieldname = ltoken_getRawString (op->content.id);
01502 
01503             /*
01504             ** does it correspond to a typedef struct field
01505             */
01506             
01507             if (ctype_isPointer (ct))
01508               {
01509                 ctype ctb = ctype_realType (ctype_baseArrayPtr (ct));
01510 
01511                 if (ctype_isStructorUnion (ctb) &&
01512                     uentry_isValid (uentryList_lookupField
01513                                     (ctype_getFields (ctb), fieldname)))
01514                   {
01515                     cstring fname = cstring_copy (fieldname);
01516 
01517                     ret = sRef_buildArrow (rec, fname);
01518                     cstring_markOwned (fname);
01519                   }
01520               }
01521 
01522             return ret;
01523           }
01524         }
01525     }
01526 
01527   return sRef_undefined;
01528 }
01529 
01530 /*
01531 ** fixModifies
01532 **
01533 ** o replace anything in modifies that is bound with let with value
01534 ** o replace spec variables with internal state 
01535 ** o replace paramaters with paramno identifiers
01536 ** o replace globals with their usymid's
01537 ** o make everything sRefs
01538 */
01539 
01540 static /*@exposed@*/ sRef fixTermNode (termNode n, fcnNode f, uentryList cl)
01541 {
01542   if (n != (termNode) 0)
01543     {
01544       switch (n->kind)
01545         {
01546         case TRM_LITERAL:
01547           break;
01548         case TRM_CONST:
01549         case TRM_VAR:
01550         case TRM_ZEROARY:
01551           {
01552             cstring s = ltoken_getRawString (n->literal);
01553             termNode tl = getLetDecl (s, f);
01554 
01555             if (tl != (termNode) 0)
01556               {
01557                 return (fixTermNode (tl, f, cl));
01558               }
01559             else
01560               {
01561                 int i = getParamNo (s, f);
01562 
01563                 if (i < 0)
01564                   {
01565                     usymId usym = usymtab_getId (s);
01566                     
01567                     if (usymId_isInvalid (usym))
01568                       {
01569                         if (usymtab_existsEither (s))
01570                           {
01571                             return sRef_makeSpecState ();
01572                           }
01573                         else
01574                           {
01575                             llcontbuglit ("Invalid symbol in modifies list");
01576                             return sRef_undefined;
01577                           }
01578                       }
01579                     else
01580                       return (sRef_makeGlobal (usym, ctype_unknown));
01581                   }
01582                 
01583                 else
01584                   {
01585                     sRef p = sRef_makeParam (i, ctype_unknown);
01586 
01587                                     return (p);
01588                   }
01589               }
01590           }
01591         case TRM_APPLICATION:
01592           {
01593             nameNode nn = n->name;
01594 
01595             if (nn != (nameNode) 0)
01596               {
01597                 if (nn->isOpId)
01598                   {
01599                     /* must we handle n->given ? skip for now */
01600 
01601                     llfatalbug 
01602                       (message ("fixTermNode: expect non-empty nameNode: "
01603                                 "TRM_APPLICATION: %q",
01604                                 nameNode_unparse (nn)));
01605                   }
01606                 else
01607                   {
01608                     sRef sr;
01609 
01610                     sr = processTermNode (nn->content.opform, n->args, f, cl);
01611                                     return (sr);
01612                   }
01613               }
01614             
01615             return sRef_undefined;
01616           }
01617         case TRM_UNCHANGEDALL:      
01618         case TRM_UNCHANGEDOTHERS:
01619         case TRM_SIZEOF:
01620         case TRM_QUANTIFIER:
01621           return sRef_undefined;
01622         }
01623     }
01624 
01625   return sRef_undefined;
01626 }
01627 
01628 static 
01629 /*@only@*/ sRefSet fixModifies (fcnNode f, uentryList cl)
01630 {
01631   static bool shownWarning = FALSE;
01632   modifyNode m = f->modify;
01633   sRefSet sl = sRefSet_new ();
01634 
01635   if (m != (modifyNode) 0)
01636     {
01637       if (m->hasStoreRefList)
01638         {
01639           storeRefNodeList srefs = m->list;
01640 
01641           storeRefNodeList_elements (srefs, i)
01642             {
01643               if (storeRefNode_isObj (i) || storeRefNode_isType (i))
01644                 {
01645                   if (!shownWarning)
01646                     {
01647                       fileloc loc = fileloc_fromTok (f->name);
01648                   
01649                       llmsg (message
01650                              ("%q: Warning: object and type modifications "
01651                               "not understood by LCLint",
01652                               fileloc_unparse (loc)));
01653                       fileloc_free (loc);
01654                       shownWarning = TRUE;
01655                     }
01656                 }
01657               else if (storeRefNode_isSpecial (i))
01658                 {
01659                   sl = sRefSet_insert (sl, i->content.ref);
01660                 }
01661               else if (storeRefNode_isTerm (i))
01662                 {
01663                   sRef s = fixTermNode (i->content.term, f, cl);
01664 
01665                   if (sRef_isKnown (s)) 
01666                     {
01667                       sl = sRefSet_insert (sl, s);
01668                     }
01669                 }
01670               else
01671                 {
01672                   BADEXIT;
01673                 }
01674             } end_storeRefNodeList_elements;
01675           
01676         }
01677     }
01678 
01679   return sl;
01680 }
01681 
01682 static /*@only@*/ cstring
01683 paramNode_name (paramNode x)
01684 {
01685   return (typeExpr_name (x->paramdecl));
01686 }
01687 
01688 static /*@only@*/ uentry
01689 paramNode_toUentry (paramNode p)
01690 {
01691   if (p != (paramNode) 0)
01692     {
01693       if (p->kind == PELIPSIS)
01694         {
01695           return uentry_makeElipsisMarker ();
01696         }
01697       else
01698         {
01699           qtype ct = convertLclTypeSpecNode (p->type);
01700           ctype cr = convertTypeExpr (qtype_getType (ct), p->paramdecl);
01701           cstring pname = (p->paramdecl == (typeExpr)0) ? cstring_undefined 
01702                                                         : paramNode_name (p);
01703           uentry ue = uentry_makeVariableParam (pname, cr);
01704 
01705           uentry_reflectQualifiers (ue, qtype_getQuals (ct));
01706           qtype_free (ct);
01707           return (ue);
01708         }
01709     }
01710   else
01711     {
01712       llcontbuglit ("paramNode_toUentry: NULL");
01713       return uentry_undefined;
01714     }
01715   BADEXIT;
01716 }
01717 
01718 static uentryList
01719   paramNodeList_toUentryList (paramNodeList p)
01720 {
01721   uentryList cl = uentryList_new ();
01722 
01723   if (paramNodeList_isNull (p)) return (cl);
01724 
01725   paramNodeList_elements (p, current)
01726     {
01727       cl = uentryList_add (cl, paramNode_toUentry (current));
01728     } end_paramNodeList_elements;
01729 
01730   return cl;
01731 }
01732 
01733 

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