]> andersk Git - splint.git/blobdiff - src/context.c
Fixed branch state bug with definitely null values (reported by Jon Wilson).
[splint.git] / src / context.c
index 76be59280109adce3397a15d21be52091d656840..7cc5c82a2526e397b1c2c7d4dbb1f3eeeb584a1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** LCLint - annotation-assisted static program checker
+** Splint - annotation-assisted static program checker
 ** Copyright (C) 1994-2001 University of Virginia,
 **         Massachusetts Institute of Technology
 **
@@ -19,7 +19,7 @@
 **
 ** For information on lclint: lclint-request@cs.virginia.edu
 ** To report a bug: lclint-bug@cs.virginia.edu
-** For more information: http://lclint.cs.virginia.edu
+** For more information: http://www.splint.org
 */
 /*
 ** context.c
@@ -35,7 +35,6 @@
 
 # include "lclintMacros.nf"
 # include "llbasic.h"
-# include "mtincludes.h"
 
 # ifndef NOLCL
 # include "usymtab_interface.h"
@@ -64,7 +63,8 @@ typedef enum {
   CX_GLOBAL, CX_INNER, 
   CX_FUNCTION, CX_FCNDECLARATION,
   CX_MACROFCN, CX_MACROCONST, CX_UNKNOWNMACRO, 
-  CX_ITERDEF, CX_ITEREND,
+  CX_ITERDEF, CX_ITEREND, 
+  CX_OLDSTYLESCOPE, /* Parsing old-style parameter declarations */
   CX_LCL, CX_LCLLIB, CX_MT
 } kcontext;
 
@@ -135,7 +135,6 @@ static struct
   /*@reldef@*/ maccesst *moduleaccess; /* Not defined is nmods == 0. */
   
   kcontext kind;
-  kcontext savekind;
 
   ctype boolType;
 
@@ -152,12 +151,15 @@ static struct
 
   metaStateTable stateTable; /* User-defined state information. */
   annotationTable annotTable; /* User-defined annotations table. */
-  union 
+  union u_cont
     {
       bool glob;
       int  cdepth;
       /*@dependent@*/ /*@exposed@*/ uentry  fcn;
     } cont;
+
+  kcontext savekind;
+  union u_cont savecont;
 } gc;
 
 static /*@exposed@*/ cstring context_exposeString (flagcode p_flag) ;
@@ -700,7 +702,7 @@ conext_resetAllCounters (void)
 }
 
 void
-context_resetAllFlags (void)
+context_resetAllFlags (void) 
 {
   allFlagCodes (code)
     {
@@ -822,6 +824,11 @@ context_resetAllFlags (void)
   gc.flags[FLG_NESTCOMMENT] = TRUE;
   gc.flags[FLG_GLOBALS] = TRUE;
   gc.flags[FLG_FULLINITBLOCK] = TRUE;
+  gc.flags[FLG_INITSIZE] = TRUE;
+  gc.flags[FLG_INITALLELEMENTS] = TRUE;
+
+  gc.flags[FLG_STRINGLITTOOLONG] = TRUE;
+
   gc.flags[FLG_LIKELYBOOL] = TRUE;
   gc.flags[FLG_ZEROPTR] = TRUE;
   gc.flags[FLG_NUMLITERAL] = TRUE;
@@ -858,6 +865,7 @@ context_resetAllFlags (void)
   gc.flags[FLG_FORMATTYPE] = TRUE;
   gc.flags[FLG_BADFLAG] = TRUE;
   gc.flags[FLG_WARNFLAGS] = TRUE;
+  gc.flags[FLG_WARNRC] = TRUE;
   gc.flags[FLG_FILEEXTENSIONS] = TRUE;
   gc.flags[FLG_WARNUNIXLIB] = TRUE;
   gc.flags[FLG_WARNPOSIX] = TRUE;
@@ -970,17 +978,19 @@ context_setMode (cstring s)
       flagcode modeflags[] = 
        {
          FLG_ENUMINT, FLG_MACROMATCHNAME,
+         FLG_STRINGLITNOROOM,
          FLG_MACROUNDEF, FLG_RELAXQUALS, 
          FLG_USEALLGLOBS, FLG_CHECKSTRICTGLOBALS,
          FLG_CHECKSTRICTGLOBALIAS,
          FLG_CHECKEDGLOBALIAS,
          FLG_CHECKMODGLOBALIAS,
          FLG_PREDBOOLOTHERS, FLG_PREDBOOLINT,
+         FLG_UNSIGNEDCOMPARE,
          FLG_PARAMUNUSED, FLG_VARUNUSED, FLG_FUNCUNUSED, 
          FLG_TYPEUNUSED,
          FLG_CONSTUNUSED, FLG_ENUMMEMUNUSED, FLG_FIELDUNUSED,
-         FLG_PTRNUMCOMPARE, FLG_BOOLCOMPARE, FLG_MUTREP, 
-         FLG_NOEFFECT, FLG_IMPTYPE,
+         FLG_PTRNUMCOMPARE, FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
+         FLG_MUTREP, FLG_NOEFFECT, FLG_IMPTYPE,
          FLG_RETVALOTHER, FLG_RETVALBOOL, FLG_RETVALINT,
          FLG_SPECUNDEF, FLG_INCONDEFS, FLG_INCONDEFSLIB, FLG_MISPLACEDSHAREQUAL,
          FLG_MATCHFIELDS,
@@ -1056,6 +1066,7 @@ context_setMode (cstring s)
           FLG_CHECKSTRICTGLOBALS, FLG_MACROMATCHNAME,
          FLG_RETVALOTHER,
          FLG_IFEMPTY, 
+         FLG_BUFFEROVERFLOWHIGH,
          FLG_RETSTACK, FLG_PTRNEGATE,
          FLG_STATETRANSFER, FLG_STATEMERGE,
          FLG_LONGUNSIGNEDINTEGRAL,
@@ -1080,9 +1091,11 @@ context_setMode (cstring s)
          FLG_CHECKMODGLOBALIAS,
          FLG_UNCHECKEDGLOBALIAS,
          FLG_FORMATCONST,
+         FLG_STRINGLITNOROOM,
+         FLG_STRINGLITSMALLER,
           FLG_EXITARG, FLG_PTRNUMCOMPARE, 
-         FLG_BOOLCOMPARE, FLG_MACROUNDEF
-         FLG_MUSTMOD, FLG_ALLGLOBALS,
+         FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE
+         FLG_MACROUNDEF, FLG_MUSTMOD, FLG_ALLGLOBALS,
          FLG_PREDBOOLOTHERS, FLG_PREDBOOLPTR, FLG_PREDBOOLINT,
          FLG_USEALLGLOBS, FLG_MUTREP, FLG_RETALIAS, 
          FLG_RETEXPOSE, FLG_ASSIGNEXPOSE, FLG_CASTEXPOSE,
@@ -1111,6 +1124,10 @@ context_setMode (cstring s)
 
          FLG_NESTEDEXTERN, 
 
+         /* warn use flags */
+         FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
+         FLG_BUFFEROVERFLOWHIGH,
+
          /* memchecks flags */
 
          FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
@@ -1167,6 +1184,8 @@ context_setMode (cstring s)
          FLG_MODFILESYSTEM,
          FLG_MACROMATCHNAME,
          FLG_FORMATCONST,
+         FLG_STRINGLITNOROOM,
+         FLG_STRINGLITSMALLER,
          FLG_STATETRANSFER, FLG_STATEMERGE,
           FLG_MACROUNDEF, FLG_MUTREP, FLG_MUSTMOD,
          FLG_ALLGLOBALS, FLG_IMPTYPE,
@@ -1191,8 +1210,8 @@ context_setMode (cstring s)
          FLG_VARUNUSED, 
          FLG_NULLPOINTERARITH, FLG_POINTERARITH, 
          FLG_PTRNUMCOMPARE, 
-         FLG_BOOLCOMPARE, FLG_NOEFFECT, 
-         FLG_RETVALINT, FLG_RETVALBOOL, FLG_RETVALOTHER, 
+         FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
+         FLG_NOEFFECT, FLG_RETVALINT, FLG_RETVALBOOL, FLG_RETVALOTHER, 
          FLG_ANSIRESERVED, FLG_ANSIRESERVEDLOCAL, FLG_CPPNAMES,
          FLG_RETVALBOOL, FLG_RETVALINT, FLG_SPECUNDEF, 
          FLG_DECLUNDEF, FLG_STRICTOPS, FLG_INCONDEFS, 
@@ -1214,6 +1233,11 @@ context_setMode (cstring s)
          FLG_NESTEDEXTERN, 
          FLG_FIRSTCASE,
 
+         /* warn use flags */
+         FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
+         FLG_BUFFEROVERFLOWHIGH,
+         FLG_BUFFEROVERFLOW, FLG_TOCTOU,
+
          /* memchecks flags */
          FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
          FLG_NULLPASS, FLG_NULLRET,
@@ -1295,44 +1319,44 @@ context_isSpecialFile (cstring fname)
 bool
 context_isSystemDir (cstring dir)
 {
-  cstring sysDirs = context_exposeString (FLG_SYSTEMDIRS);
-  char *thisdir = cstring_toCharsSafe (sysDirs);
-  char *nextdir = strchr (thisdir, SEPCHAR);
-
-  if (nextdir != NULL)
+  cstring thisdir = cstring_copy (context_getString (FLG_SYSTEMDIRS));
+  cstring savedir = thisdir;
+  cstring nextdir = cstring_afterChar (thisdir, PATH_SEPARATOR);
+  
+  if (cstring_isDefined (nextdir))
     {
-      *nextdir = '\0';
+      /*@access cstring@*/
+      *nextdir = '\0'; /* closes thisdir */
       nextdir += 1;
+      /*@noaccess cstring@*/
     }
 
-  while (thisdir != NULL)
+  /* 2001-09-09: added thisdir[0] != '\0' 
+  **   herbert: don't compare with an empty name! 
+  **   should return false for empty directory path
+  */
+
+  while (!cstring_isEmpty (thisdir))
     {
       DPRINTF (("Test: %s / %s", dir, thisdir));
 
-      if (cstring_equalCanonicalPrefix (dir, thisdir))
+      if (osd_equalCanonicalPrefix (dir, thisdir))
        {
-         if (nextdir != NULL)
-           {
-             *(nextdir - 1) = SEPCHAR;
-           }
-         
+         cstring_free (savedir);
          return TRUE;
        }
 
-      if (nextdir != NULL)
-       {
-         *(nextdir - 1) = SEPCHAR;
-       }
-
-      if (nextdir != NULL)
+      if (cstring_isDefined (nextdir))
        {
          thisdir = nextdir;
-         nextdir = strchr (thisdir, SEPCHAR);
+         nextdir = cstring_afterChar (thisdir, PATH_SEPARATOR);
          
-         if (nextdir != NULL)
+         if (cstring_isDefined (nextdir))
            {
+             /*@access cstring@*/
              *nextdir = '\0';
              nextdir += 1;
+             /*@noaccess cstring@*/
            } 
        }
       else
@@ -1342,6 +1366,7 @@ context_isSystemDir (cstring dir)
     } 
 
   DPRINTF (("Returns FALSE"));
+  cstring_free (savedir);
   return FALSE;
 }
 
@@ -1378,13 +1403,31 @@ context_removeFileAccessType (typeId t)
 
 void context_enterFunctionHeader (void)
 {
-  llassert (gc.kind == CX_GLOBAL);
-  DPRINTF (("Enter function header!"));
-  gc.inFunctionHeader = TRUE;
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Enter function header: %q", context_unparse ()));
+    }
+
+  if (gc.kind != CX_GLOBAL)
+    {
+      llparseerror (cstring_makeLiteral
+                   ("Likely parse error.  Function header outside global context."));
+    }
+  else
+    {
+      llassert (gc.kind == CX_GLOBAL);
+      DPRINTF (("Enter function header!"));
+      gc.inFunctionHeader = TRUE;
+    }
 }
 
 void context_exitFunctionHeader (void)
 {
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Exit function header: %q", context_unparse ()));
+    }
+
   DPRINTF (("Exit function header!"));
   gc.inFunctionHeader = FALSE;
 }
@@ -1396,21 +1439,38 @@ bool context_inFunctionHeader (void)
 
 void context_enterFunctionDeclaration (uentry e)
 {
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Enter function declaration: %q", context_unparse ()));
+    }
+
   DPRINTF (("Enter function decl"));
   llassert (gc.savekind == CX_ERROR);
   gc.savekind = gc.kind;
+  gc.savecont = gc.cont;
   gc.kind = CX_FCNDECLARATION;
   gc.cont.fcn = e;
 }
 
 void context_exitFunctionDeclaration (void)
 {
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Exit function declaration: %q", context_unparse ()));
+    }
+
   DPRINTF (("Exit function decl"));
   llassert (gc.savekind != CX_ERROR);
   llassert (gc.kind == CX_FCNDECLARATION);
   gc.kind = gc.savekind;
-  gc.cont.fcn = uentry_undefined;
+  gc.cont = gc.savecont;
+
   gc.savekind = CX_ERROR;
+
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("After exit function declaration: %q", context_unparse ()));
+    }
 }
 
 bool context_inFunctionDeclaration (void)
@@ -1752,6 +1812,61 @@ context_enterFunction (/*@exposed@*/ uentry e)
   sRef_enterFunctionScope ();
 }
 
+void
+context_enterOldStyleScope (void)
+{
+  gc.kind = CX_OLDSTYLESCOPE;
+  DPRINTF (("Enter old style scope!"));
+  usymtab_enterFunctionScope (uentry_undefined);
+}
+
+void 
+context_completeOldStyleFunction (uentry e)
+{
+  llassert (gc.kind == CX_OLDSTYLESCOPE);
+
+  gc.kind = CX_FUNCTION;
+  gc.cont.fcn = e;
+  
+  DPRINTF (("Enter function: %s", uentry_unparse (e)));
+  
+  if (uentry_hasAccessType (e))
+    {
+      gc.acct = typeIdSet_subtract (typeIdSet_union (gc.facct, uentry_accessType (e)), 
+                                   gc.nacct);
+    }
+  else
+    {
+      gc.acct = gc.facct;
+    }
+  
+  DPRINTF (("Enter function: %s / %s", uentry_unparse (e), 
+           typeIdSet_unparse (gc.acct)));
+  
+  gc.showfunction = context_getFlag (FLG_SHOWFUNC);
+  
+  if (!globSet_isEmpty (uentry_getGlobs (e))) 
+    {
+      llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
+                            fileloc_unparse (g_currentloc), uentry_unparse (e)));
+    }
+
+  gc.showfunction = context_getFlag (FLG_SHOWFUNC);
+  
+  gc.globs = uentry_getGlobs (e);
+  globSet_clear (gc.globs_used);
+
+  gc.mods = uentry_getMods (e);
+
+  if (!sRefSet_isEmpty (gc.mods))
+    {
+      llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
+                            fileloc_unparse (g_currentloc), uentry_unparse (e)));
+    }
+
+  sRef_enterFunctionScope ();
+}
+
 static bool context_checkStrictGlobals (void)
 {
   return (context_getFlag (FLG_CHECKSTRICTGLOBALS));
@@ -2298,13 +2413,17 @@ context_returnFunction (void)
 void
 context_exitFunction (void)
 {    
+  DPRINTF (("Exit function: %s", context_unparse ()));
+
   if (!context_inFunction () && !context_inMacroConstant () 
-      && !context_inMacroUnknown () 
+      && !context_inUnknownMacro () 
       && !context_inIterDef () && !context_inIterEnd ())
     {
       /*
       ** not a bug because of parse errors
       */
+
+      BADBRANCH;
     }
   else
     {
@@ -2349,6 +2468,7 @@ context_exitFunction (void)
 
   llassert (clauseStack_isEmpty (gc.clauses));
   llassert (gc.inclause == NOCLAUSE);
+  DPRINTF (("After exit function: %s", context_unparse ()));
 }
 
 void
@@ -2359,7 +2479,7 @@ context_quietExitFunction (void)
       context_exitInnerPlain ();
     }
 
-  if (!context_inFunction () && !context_inMacroConstant () && !context_inMacroUnknown () 
+  if (!context_inFunction () && !context_inMacroConstant () && !context_inUnknownMacro () 
       && !context_inIterDef () && !context_inIterEnd ())
     {
     }
@@ -2738,7 +2858,7 @@ context_setString (flagcode flag, cstring val)
     }
 
   if (cstring_length (val) >= 1
-      && cstring_firstChar (val) == '"')
+      && cstring_firstChar (val) == '\"')
     {
       llerror_flagWarning (message
                       ("setting %s to string beginning with \".  You probably "
@@ -2779,7 +2899,10 @@ void context_initMod (void)
    /*@globals undef gc; @*/
 {
   gc.kind = CX_GLOBAL;
+
   gc.savekind = CX_ERROR;
+  gc.savecont.glob = FALSE;
+
   gc.instandardlib = FALSE;
   gc.numerrors = 0;
   gc.neednl = FALSE;
@@ -2839,7 +2962,14 @@ void context_initMod (void)
   usymtab_initMod ();
 
   context_resetAllFlags ();
+  assertSet (gc.flags); /* Can't use global in defines */
+  assertSet (gc.saveflags);
+  assertSet (gc.values);
+  assertSet (gc.strings);
+
   conext_resetAllCounters ();
+  assertSet (gc.counters);
+
   context_setMode (DEFAULT_MODE);
 
   gc.stateTable = metaStateTable_create ();
@@ -2903,7 +3033,9 @@ context_unparse (void)
       s = message ("Global Context:%q", fileloc_unparse (g_currentloc));
       break;
     case CX_INNER:
-      s = message ("Inner Context:%q", fileloc_unparse (g_currentloc));
+      s = message ("Inner Context [%d] : %q", 
+                  gc.cont.cdepth,
+                  fileloc_unparse (g_currentloc));
       break;
     case CX_FUNCTION:
       s = message ("Function %q :%q \n\taccess %q\n\tmodifies %q",
@@ -2927,6 +3059,9 @@ context_unparse (void)
     case CX_ITEREND:
       s = message ("Iter end %q", uentry_unparse (gc.cont.fcn));
       break;
+    case CX_FCNDECLARATION:
+      s = message ("Function declaration %q", uentry_unparse (gc.cont.fcn));
+      break;
     default:
       s = message ("Un-unparseable context: %d", (int) gc.kind);
       break;
@@ -2959,6 +3094,11 @@ context_currentFunctionType (void)
 void
 context_enterInnerContext (void)
 {
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
+    }
+
   if (gc.kind == CX_GLOBAL)
     {
       gc.kind = CX_INNER;
@@ -2973,7 +3113,6 @@ context_enterInnerContext (void)
       ;
     }
 
-  
   usymtab_enterScope ();
   pushClause (NOCLAUSE);
 }
@@ -2987,7 +3126,11 @@ context_exitInnerPlain (void) /*@modifies gc;@*/
 void
 context_exitInner (exprNode exp)
 {
-  
+   if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
+    }
   llassertprint (gc.inclause == NOCLAUSE || gc.inclause == CASECLAUSE,
                 ("inclause = %s", clause_nameTaken (gc.inclause)));
 
@@ -3018,6 +3161,11 @@ context_exitInner (exprNode exp)
 void
 context_enterStructInnerContext (void)
 {
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
+    }
+
   if (gc.kind == CX_GLOBAL)
     {
       gc.kind = CX_INNER;
@@ -3033,18 +3181,39 @@ context_enterStructInnerContext (void)
     }
 
   usymtab_enterScope ();
+
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
+    }
 }
 
 void
 context_exitStructInnerContext (void)
 {
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
+    }
+
   if (gc.kind == CX_INNER)
     {
-      if (--gc.cont.cdepth == 0)
+      if (gc.cont.cdepth <= 0)
        {
+         llcontbuglit ("Attempt to exit inner context with no depth");
          gc.kind = CX_GLOBAL;
          gc.cont.glob = TRUE;
+         gc.cont.cdepth = 0;
        }
+      else {
+       gc.cont.cdepth--;
+
+       if (gc.cont.cdepth == 0)
+         {
+           gc.kind = CX_GLOBAL;
+           gc.cont.glob = TRUE;
+         }
+      }
     }
   else 
     {
@@ -3056,17 +3225,26 @@ context_exitStructInnerContext (void)
     }
 
   usymtab_exitScope (exprNode_undefined);
+
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("After exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
+    }
 }
 
 void
 context_exitInnerSafe (void)
 {
-  
+  if (context_getFlag (FLG_GRAMMAR))
+    {
+      lldiagmsg (message ("Exit inner safe: %q", context_unparse ()));
+    }
+
   if (gc.kind == CX_INNER)
     {
-      if (--gc.cont.cdepth == 0)
+      if (--gc.cont.cdepth <= 0)
        {
-         gc.cont.cdepth++;
+         gc.cont.cdepth = 0;
        }
     }
   else if (gc.kind == CX_GLOBAL)
@@ -3330,18 +3508,15 @@ void
 context_saveLocation (void)
 {
   /* was llassert (fileloc_isUndefined (gc.saveloc)) */
-      fileloc_free (gc.saveloc);
-    
-
+  fileloc_free (gc.saveloc);
   gc.saveloc = fileloc_copy (g_currentloc);
-  }
+}
 
 fileloc
 context_getSaveLocation (void)
 {
   fileloc fl = gc.saveloc;
-
-    gc.saveloc = fileloc_undefined;
+  gc.saveloc = fileloc_undefined;
   return fl;
 }
 
@@ -3924,14 +4099,14 @@ void context_setFilename (fileId fid, int lineno)
 
 void context_enterIterDef (/*@observer@*/ uentry le)
 {
-    context_enterMacro (le);
+  context_enterMacro (le);
   gc.acct = typeIdSet_subtract (gc.facct, gc.nacct);
   gc.kind = CX_ITERDEF;
 }
 
 void context_enterIterEnd (/*@observer@*/ uentry le)
 {
-    context_enterMacro (le);
+  context_enterMacro (le);
   gc.kind = CX_ITEREND;
 }
 
@@ -4043,6 +4218,7 @@ bool context_anyErrors (void)
 void context_hasError (void)
 {
   gc.numerrors++;
+  DPRINTF (("num errors: %d", gc.numerrors));
 }
 
 int context_numErrors (void)
@@ -4142,7 +4318,7 @@ bool context_inMacroConstant (void)
   return (gc.kind == CX_MACROCONST);
 }
 
-bool context_inMacroUnknown (void)
+bool context_inUnknownMacro (void)
 {   
   return (gc.kind == CX_UNKNOWNMACRO);
 }
@@ -4238,6 +4414,37 @@ bool context_inGlobalContext (void)
   return (gc.kind == CX_GLOBAL);
 }
 
+static void context_quietExitScopes (void)
+{
+  /*
+  ** Try to restore the global scope (after an error).
+  */
+
+  while (!usymtab_inFileScope ())
+    {
+      usymtab_quietExitScope (g_currentloc);
+    }
+
+  gc.cont.glob = TRUE;
+  gc.kind = CX_GLOBAL;
+}
+
+void context_checkGlobalScope (void)
+{
+  if (gc.kind != CX_GLOBAL)
+    {
+      if (context_inMacro ())
+       {
+         ; /* evans 2001-10-14: Okay to be in a macro here! */ 
+       }
+      else
+       {
+         llcontbug (message ("Not in global scope as expected: %q", context_unparse ()));
+         context_quietExitScopes ();
+       }
+    }
+}
+
 void context_setFileId (fileId s)
 {
   g_currentloc = fileloc_updateFileId (g_currentloc, s); 
@@ -4375,7 +4582,7 @@ void context_addMetaState (cstring mname, metaStateInfo msinfo)
     }
 }
 
-valueTable context_createValueTable (sRef s)
+valueTable context_createValueTable (sRef s, stateInfo sinfo)
 {
   if (metaStateTable_size (gc.stateTable) > 0)
     {
@@ -4395,8 +4602,8 @@ valueTable context_createValueTable (sRef s)
              valueTable_insert 
                (res,
                 cstring_copy (metaStateInfo_getName (msi)),
-                stateValue_createImplicit (metaStateInfo_getDefaultValue (msi, s),
-                                           stateInfo_undefined));
+                stateValue_createImplicit (metaStateInfo_getDefaultValue (msi, s), 
+                                           stateInfo_copy (sinfo)));
            }
          else
            {
@@ -4405,16 +4612,18 @@ valueTable context_createValueTable (sRef s)
        } 
       end_metaStateTable_elements ;
       
+      stateInfo_free (sinfo);
       DPRINTF (("Value table: %s", valueTable_unparse (res)));
       return res;
     }
   else
     {
+      stateInfo_free (sinfo);
       return valueTable_undefined;
     }
 }
 
-valueTable context_createGlobalMarkerValueTable ()
+valueTable context_createGlobalMarkerValueTable (stateInfo sinfo)
 {
   if (metaStateTable_size (gc.stateTable) > 0)
     {
@@ -4430,15 +4639,17 @@ valueTable context_createGlobalMarkerValueTable ()
          valueTable_insert (res,
                             cstring_copy (metaStateInfo_getName (msi)),
                             stateValue_create (metaStateInfo_getDefaultGlobalValue (msi),
-                                               stateInfo_undefined));
+                                               stateInfo_copy (sinfo)));
        } 
       end_metaStateTable_elements ;
       
+      stateInfo_free (sinfo);
       DPRINTF (("Value table: %s", valueTable_unparse (res)));
       return res;
     }
   else
     {
+      stateInfo_free (sinfo);
       return valueTable_undefined;
     }
 }
This page took 0.095959 seconds and 4 git commands to generate.