]> andersk Git - splint.git/blob - src/context.c
Fixed fatal errors in constraint checking.
[splint.git] / src / context.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** context.c
26 */
27 /*
28  * Modified by Herbert 04/19/97:
29  * - added include for new header portab.h containing OS dependent stuff.
30  * - changed occurrances of '/' as path delimiters to macro from portab.h
31  * - changed the handling of the tmp directory -- will no longer always be
32  *   ".", if possible, environment variables "TMP" or, if not set, "TMP", 
33  *   or, if not set "." will be used.
34  */
35
36 # include "splintMacros.nf"
37 # include "llbasic.h"
38
39 # include "usymtab_interface.h"
40 # include "exprChecks.h"
41 # include "filelocStack.h"
42 # include "llmain.h"
43 # include "intSet.h"
44 # include "osd.h"
45 # include "portab.h"
46
47 extern /*@external@*/ int yydebug;
48 extern /*@external@*/ int mtdebug;
49
50 typedef struct
51
52   cstring file; 
53   typeIdSet daccess; 
54 } maccesst;
55
56 typedef enum { 
57   CX_ERROR,
58
59   CX_GLOBAL, CX_INNER, 
60   CX_FUNCTION, CX_FCNDECLARATION,
61   CX_MACROFCN, CX_MACROCONST, CX_UNKNOWNMACRO, 
62   CX_ITERDEF, CX_ITEREND, 
63   CX_OLDSTYLESCOPE, /* Parsing old-style parameter declarations */
64   CX_LCL, CX_LCLLIB, CX_MT
65 } kcontext;
66
67 static struct
68 {
69   int linesprocessed;
70   int speclinesprocessed;
71
72   flagMarkerList markers;
73
74   /*
75   **  used to record state where a macro must match a function name
76   **   (i.e., no params were listed in the macro definition
77   */
78
79   bool macroMissingParams BOOLBITS;
80   bool preprocessing BOOLBITS;
81   bool incommandline BOOLBITS;
82   bool insuppressregion  BOOLBITS;
83   bool inDerivedFile BOOLBITS;
84   bool instandardlib  BOOLBITS;
85   bool inimport  BOOLBITS;
86   bool inheader  BOOLBITS;
87   bool inmacrocache  BOOLBITS;
88   bool protectVars  BOOLBITS;
89   bool neednl  BOOLBITS;
90   bool showfunction  BOOLBITS;
91   bool savedFlags  BOOLBITS;
92   bool justpopped  BOOLBITS;
93   bool anyExports BOOLBITS;
94   bool inFunctionHeader BOOLBITS;
95
96   flagcode library;
97
98   ynm isNullGuarded;
99   fileloc saveloc;
100   fileloc pushloc;
101
102   clauseStack clauses; 
103   clause inclause;
104
105   int numerrors;
106
107   filelocStack locstack;
108   fileTable ftab;
109   cstring msgAnnote;
110   /*@observer@*/ sRef aliasAnnote;
111   /*@observer@*/ sRef aliasAnnoteAls;
112   messageLog  msgLog;
113
114   macrocache  mc;
115   /*@observer@*/ sRefSet mods;
116
117   /* file access types */
118   typeIdSet facct;   
119
120   /* local access types (this function) */
121   typeIdSet acct;  
122
123   /* no access types (@noaccess) */
124   typeIdSet nacct; 
125
126   /*@observer@*/ globSet globs;
127   /*@only@*/ globSet globs_used;
128   
129   int nmods;
130   int maxmods;
131   /*@reldef@*/ maccesst *moduleaccess; /* Not defined is nmods == 0. */
132   
133   kcontext kind;
134
135   ctype boolType;
136
137   bool flags[NUMFLAGS];
138   bool saveflags[NUMFLAGS];
139   bool setGlobally[NUMFLAGS];
140   bool setLocally[NUMFLAGS];
141
142   int values[NUMVALUEFLAGS];
143   int counters[NUMVALUEFLAGS];
144
145   o_cstring strings[NUMSTRINGFLAGS];
146   sRefSetList modrecs; /*@i32 ???? what is this for? */
147
148   metaStateTable stateTable; /* User-defined state information. */
149   annotationTable annotTable; /* User-defined annotations table. */
150   union u_cont
151     {
152       bool glob;
153       int  cdepth;
154       /*@dependent@*/ /*@exposed@*/ uentry  fcn;
155     } cont;
156
157   kcontext savekind;
158   union u_cont savecont;
159 } gc;
160
161 static /*@exposed@*/ cstring context_exposeString (flagcode p_flag) ;
162 static void context_restoreFlagSettings (void) /*@modifies gc@*/ ;
163 static void context_saveFlagSettings (void) /*@modifies gc@*/ ;
164 static void context_exitClauseAux (exprNode p_pred, exprNode p_tbranch)
165    /*@modifies gc@*/ ;
166 static void context_exitClauseSimp (void)  /*@modifies gc@*/ ;
167 static void context_exitClausePlain (void) /*@modifies gc@*/ ;
168 static void context_setJustPopped (void) /*@modifies gc.justpopped@*/ ;
169 static void context_setValue (flagcode p_flag, int p_val) /*@modifies gc.flags@*/ ;
170 static void context_setFlag (flagcode p_f, bool p_b, fileloc p_loc)
171   /*@modifies gc.flags@*/ ;
172
173 static void
174   context_setFlagAux (flagcode p_f, bool p_b, bool p_inFile, 
175                       bool p_isRestore, fileloc p_loc)
176   /*@modifies gc.flags@*/ ;
177
178 static void context_restoreFlag (flagcode p_f, fileloc p_loc)
179   /*@modifies gc.flags@*/ ;
180
181 /*@+enumindex@*/ 
182
183 cstring context_unparseFlagMarkers ()
184 {
185   return (flagMarkerList_unparse (gc.markers));
186 }
187
188 void context_setPreprocessing (void)
189 {
190   llassert (!gc.preprocessing);
191   gc.preprocessing = TRUE;
192 }
193
194 void context_clearPreprocessing (void)
195 {
196   llassert (gc.preprocessing);
197   gc.preprocessing = FALSE;
198 }
199
200 bool context_isPreprocessing (void)
201 {
202   return gc.preprocessing;
203 }
204
205 bool context_loadingLibrary (void)
206 {
207   return (fileloc_isLib (g_currentloc));
208 }
209
210 bool context_inXHFile (void)
211 {
212   return (fileloc_isXHFile (g_currentloc));
213 }
214
215 void context_setInCommandLine (void)
216 {
217   llassert (!gc.incommandline);
218   gc.incommandline = TRUE;
219 }
220
221 void context_clearInCommandLine (void)
222 {
223   llassert (gc.incommandline);
224   gc.incommandline = FALSE;
225 }
226
227 bool context_isInCommandLine (void)
228 {
229   return gc.incommandline;
230 }
231
232 static
233 void pushClause (clause c) /*@modifies gc.clauses, gc.inclause@*/
234 {
235   gc.inclause = c;
236   clauseStack_push (gc.clauses, c);
237
238   if (clause_isConditional (c)
239       && context_getFlag (FLG_CONTROLNESTDEPTH))
240     {
241       int maxdepth = context_getValue (FLG_CONTROLNESTDEPTH);
242       int depth = clauseStack_controlDepth (gc.clauses);
243       
244       if (depth == maxdepth + 1)
245         {
246           voptgenerror 
247             (FLG_CONTROLNESTDEPTH,
248              message ("Maximum control nesting depth "
249                       "(%d) exceeded",
250                       maxdepth),
251              g_currentloc);
252         }
253     }
254 }
255
256 static
257 clause topClause (clauseStack s) /*@*/
258 {
259   if (clauseStack_isEmpty (s)) return NOCLAUSE;
260   return ((clause) clauseStack_top (s));
261 }
262
263 void
264 context_addMacroCache (/*@only@*/ cstring def)
265 {
266   DPRINTF (("macro cache: %s", def));
267   macrocache_addEntry (gc.mc, fileloc_copy (g_currentloc), def);
268 }
269
270 void
271 context_addComment (/*@only@*/ cstring def, fileloc loc)
272 {
273   macrocache_addComment (gc.mc, fileloc_copy (loc), def);
274 }
275
276 /*
277 ** returns TRUE is fl is in ignore region, or region where -code
278 **
279 ** the logic is fuzzy...
280 */
281
282 static bool
283 context_inSuppressFlagZone (fileloc fl, flagcode code)
284 {
285   ynm ret = flagMarkerList_suppressError (gc.markers, code, fl);
286   bool res = FALSE;
287   
288   if (ynm_isMaybe (ret))
289     {
290       /*
291       ** whas is dis?
292       */
293
294       if (gc.savedFlags)
295         {
296           res = !gc.saveflags[code];
297         }
298       else
299         {
300           res = !context_getFlag (code);
301         }
302     }
303   else
304     {
305       res = ynm_toBoolStrict (ret);
306     }
307   
308     return res;
309 }
310
311 static bool
312 context_suppressSystemMsg (fileloc fl)
313 {
314   if (context_getFlag (FLG_SYSTEMDIRERRORS))
315     {
316       return FALSE;
317     }
318   else
319     {
320       return (fileloc_isSystemFile (fl));
321     }
322 }
323
324 bool 
325 context_suppressFlagMsg (flagcode flag, fileloc fl)
326 {
327   if (context_suppressSystemMsg (fl))
328     {
329       return TRUE;
330     }
331
332   DPRINTF (("Checking suppress: %s / %s", fileloc_unparse (fl), fileloc_unparse (g_currentloc)));
333
334   /* want same object compare here */
335
336   if (fileloc_equal (fl, g_currentloc) || gc.inDerivedFile)
337     {
338       DPRINTF (("In derived file: %s", bool_unparse (gc.inDerivedFile)));
339
340       return (!context_getFlag (flag)
341               || context_inSuppressRegion ()
342               || context_inSuppressZone (fl)
343               || (/*@!@@#@ gc.inDerivedFile && */ context_inSuppressFlagZone (fl, flag)));
344     }
345   else
346     {
347       return (context_inSuppressFlagZone (fl, flag));
348     }
349 }
350
351 bool 
352 context_suppressNotFlagMsg (flagcode flag, fileloc fl)
353 {
354   
355   if (context_suppressSystemMsg (fl))
356     {
357       return TRUE;
358     }
359
360   /*@access fileloc@*/ 
361   if (fl == g_currentloc)
362     /*@noaccess fileloc@*/
363     {
364       return (context_getFlag (flag) || context_inSuppressRegion ());
365     }
366   else
367     {
368       /* for now... */
369       return (context_getFlag (flag) || context_inSuppressRegion ());
370     }
371 }
372
373 bool
374 context_inSuppressZone (fileloc fl) 
375 {
376   if (context_suppressSystemMsg (fl))
377     {
378       return TRUE;
379     }
380
381   return (flagMarkerList_inIgnore (gc.markers, fl));
382 }
383
384 bool
385 context_inSuppressRegion (void)
386 {
387   return (gc.insuppressregion);
388 }
389
390 void
391 context_enterSuppressRegion (fileloc loc)
392 {
393   if (gc.insuppressregion)
394     {
395       gc.insuppressregion = FALSE;      /* get this msg! */
396       llmsg (message
397              ("%q: New ignore errors region entered while in ignore errors region",
398               fileloc_unparse (loc)));
399     }
400   
401   gc.insuppressregion = TRUE;
402   (void) flagMarkerList_add (gc.markers, flagMarker_createIgnoreOn (loc));
403 }
404
405 static void
406 context_addFlagMarker (flagcode code, ynm set, fileloc loc)
407 {
408   (void) flagMarkerList_add (gc.markers,
409                              flagMarker_createLocalSet (code, set, loc));
410 }
411
412 void
413 context_enterSuppressLine (int count, fileloc loc)
414 {
415   if (context_processingMacros ())
416     {
417       return;
418     }
419
420   if (flagMarkerList_add 
421       (gc.markers,
422        flagMarker_createIgnoreCount (count, loc)))
423     {
424       fileloc nextline = fileloc_copy (loc);
425       fileloc_nextLine (nextline);
426       fileloc_setColumn (nextline, 0);
427
428       check (flagMarkerList_add (gc.markers,
429                                  flagMarker_createIgnoreOff (nextline)));
430       fileloc_free (nextline);
431     }
432 }
433
434 void context_checkSuppressCounts (void)
435 {
436   if (context_getFlag (FLG_SUPCOUNTS))
437     {
438       flagMarkerList_checkSuppressCounts (gc.markers);
439     }
440 }
441
442 void context_incLineno (void)
443 {
444   gc.linesprocessed++;
445   incLine ();
446 }
447
448 void
449 context_exitSuppressRegion (fileloc loc)
450 {
451   if (!gc.insuppressregion)
452     {
453       voptgenerror 
454         (FLG_SYNTAX, 
455          message ("End ignore errors in region while not ignoring errors"),
456          loc);
457     }
458   
459   gc.insuppressregion = FALSE;
460   (void) flagMarkerList_add (gc.markers, flagMarker_createIgnoreOff (loc));
461 }
462
463 void
464 context_enterMTfile (void)
465 {
466   gc.kind = CX_MT;
467 }
468
469 void
470 context_exitMTfile (void)
471 {
472   llassert (gc.kind == CX_MT);
473   gc.kind = CX_GLOBAL;
474 }
475
476 void
477 context_enterLCLfile (void)
478 {
479   gc.kind = CX_LCL;
480   gc.facct = typeIdSet_emptySet ();
481 }
482
483 static void
484 addModuleAccess (/*@only@*/ cstring fname, typeIdSet mods)
485 {
486   int i;
487
488   for (i = 0; i < gc.nmods; i++)
489     {
490       if (cstring_equal (gc.moduleaccess[i].file, fname))
491         {
492           gc.moduleaccess[i].daccess = typeIdSet_union (gc.moduleaccess[i].daccess, mods);
493           cstring_free (fname);
494           return;
495         }
496     }
497   
498   if (gc.nmods == gc.maxmods)
499     {
500       maccesst *oldmods;
501       
502       gc.maxmods = gc.maxmods + DEFAULTMAXMODS;      
503       oldmods = gc.moduleaccess;
504       
505       gc.moduleaccess = (maccesst *) dmalloc (sizeof (*gc.moduleaccess) * (gc.maxmods));
506       
507       for (i = 0; i < gc.nmods; i++)
508         {
509           gc.moduleaccess[i] = oldmods[i];
510         }
511       
512       sfree (oldmods);
513     }
514   
515   gc.moduleaccess[gc.nmods].file = fname;
516   gc.moduleaccess[gc.nmods].daccess = mods;
517   
518   gc.nmods++;
519 }
520
521 static void
522 insertModuleAccess (cstring fname, typeId t)
523 {
524   int i;
525   
526   for (i = 0; i < gc.nmods; i++)
527     {
528       if (cstring_equal (gc.moduleaccess[i].file, fname))
529         {
530           gc.moduleaccess[i].daccess = typeIdSet_insert (gc.moduleaccess[i].daccess, t);
531           break;
532         }
533     }
534   
535     addModuleAccess (cstring_copy (fname), typeIdSet_single (t));
536 }
537
538 void
539 context_exitLCLfile (void)
540 {
541   if (gc.kind != CX_LCLLIB)
542     {
543       cstring lclname =  
544         fileLib_withoutExtension (fileTable_fileName (currentFile ()), LCL_EXTENSION);
545       
546       addModuleAccess (fileLib_removePath (lclname), gc.facct);
547       cstring_free (lclname);
548     }
549   
550   gc.kind = CX_LCL;
551   gc.kind = CX_GLOBAL;
552   gc.facct = typeIdSet_emptySet ();
553 }
554
555 void
556 context_dumpModuleAccess (FILE *fout)
557 {
558   int i = 0;
559
560   for (i = 0; i < gc.nmods; i++)
561     {
562       cstring td = typeIdSet_dump (gc.moduleaccess[i].daccess);
563
564       fprintf (fout, "%s#%s@\n", 
565                cstring_toCharsSafe (gc.moduleaccess[i].file), 
566                cstring_toCharsSafe (td));
567       
568       cstring_free (td);
569     }
570 }
571
572 bool context_usingPosixLibrary ()
573 {
574   return (gc.library == FLG_POSIXLIB 
575           || gc.library == FLG_POSIXSTRICTLIB
576           || gc.library == FLG_UNIXLIB
577           || gc.library == FLG_UNIXSTRICTLIB);
578 }
579
580 bool context_usingAnsiLibrary ()
581 {
582   return (gc.library != FLG_NOLIB);
583 }
584
585 flagcode context_getLibrary ()
586 {
587   return gc.library;
588 }
589
590 void context_setLibrary (flagcode code)
591 {
592   gc.library = code;
593 }
594
595 /*@observer@*/ cstring context_selectedLibrary ()
596 {
597   switch (gc.library)
598     {
599     case FLG_STRICTLIB:
600       return cstring_makeLiteralTemp (LLSTRICTLIBS_NAME);
601     case FLG_POSIXLIB:
602       return cstring_makeLiteralTemp (LLPOSIXLIBS_NAME);
603     case FLG_POSIXSTRICTLIB:
604       return cstring_makeLiteralTemp (LLPOSIXSTRICTLIBS_NAME);
605     case FLG_UNIXLIB:
606       return cstring_makeLiteralTemp (LLUNIXLIBS_NAME);    
607     case FLG_UNIXSTRICTLIB:
608       return cstring_makeLiteralTemp (LLUNIXSTRICTLIBS_NAME);
609     case FLG_ANSILIB:
610       return cstring_makeLiteralTemp (LLSTDLIBS_NAME);
611     BADDEFAULT;
612     }
613 }
614   
615
616 void
617 context_loadModuleAccess (FILE *in)
618 {
619   char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
620   char *lasts = s;
621   char *name = mstring_create (MAX_NAME_LENGTH);
622   char *oname = name;
623 # ifndef NOFREE
624   char *os = s;
625 # endif
626
627   while ((reader_readLine (in, s, MAX_DUMP_LINE_LENGTH) != NULL )
628          && *s == ';')
629     {
630       ;
631     }
632
633   while (s != NULL && *s != ';' && *s != '\0')
634     {
635       name = oname;
636       
637       while (*s != '#' && *s != '\0')
638         {
639           *name++ = *s++;
640         }
641
642       *name = '\0';
643
644       if (*s != '#')
645         {
646           llcontbug (message ("context_loadModuleAccess: bad library line: %s\n", 
647                               cstring_fromChars (s)));
648           break;
649         }
650
651       s++;
652
653       addModuleAccess (cstring_copy (cstring_fromChars (oname)), 
654                        typeIdSet_undump (&s)); 
655
656       (void) reader_readLine (in, s, MAX_DUMP_LINE_LENGTH);
657       llassert (s != lasts);
658       lasts = s;
659     }
660
661   sfree (oname);
662 # ifndef NOFREE
663   sfree (os);
664 # endif
665 }
666
667 typeIdSet context_fileAccessTypes (void)
668 {
669   return gc.facct;
670 }
671
672 void
673 context_resetModeFlags (void)
674 {  
675   allFlagCodes (code)
676     {
677       if (flagcode_isModeFlag (code))
678         {
679           context_setFlag (code, FALSE, g_currentloc);
680         }
681     } end_allFlagCodes;  
682 }
683
684 /*
685 ** resetAllFlags
686 **
687 ** Set all flags to FALSE, except for a few which are
688 ** true by default.
689 **
690 ** Set all values and strings to appropriate defaults.
691 ** Set all counters to 0.
692 */
693
694 static void
695 conext_resetAllCounters (void)
696 {
697   int i;
698
699   for (i = 0; i < NUMVALUEFLAGS; i++)
700     {
701       gc.counters[i] = 0;
702     }
703 }
704
705 void
706 context_resetAllFlags (void) 
707 {
708   DPRINTF (("******** Reset all flags"));
709
710   allFlagCodes (code)
711     {
712       gc.flags[code] = FALSE;
713
714       if (flagcode_hasNumber (code))
715         {
716           int val = 0;
717           
718           /*@-loopswitchbreak@*/
719           switch (code)
720             {
721             case FLG_LIMIT: 
722               val = DEFAULT_LIMIT; break;
723             case FLG_BUGSLIMIT:
724               val = DEFAULT_BUGSLIMIT; break;
725             case FLG_LINELEN: 
726               val = DEFAULT_LINELEN; break;
727             case FLG_INDENTSPACES: 
728               val = DEFAULT_INDENTSPACES; break;
729             case FLG_EXTERNALNAMELEN:
730               val = ISO99_EXTERNALNAMELEN; break;
731             case FLG_INTERNALNAMELEN:
732               val = ISO99_INTERNALNAMELEN; break;
733             case FLG_COMMENTCHAR: 
734               val = (int) DEFAULT_COMMENTCHAR; break;
735             case FLG_CONTROLNESTDEPTH:
736               val = (int) ISO99_CONTROLNESTDEPTH; break;
737             case FLG_STRINGLITERALLEN:
738               val = (int) ISO99_STRINGLITERALLEN; break;
739             case FLG_INCLUDENEST:
740               val = (int) ISO99_INCLUDENEST; break;
741             case FLG_NUMSTRUCTFIELDS:
742               val = (int) ISO99_NUMSTRUCTFIELDS; break;
743             case FLG_NUMENUMMEMBERS:
744               val = (int) ISO99_NUMENUMMEMBERS; break;
745             case FLG_EXPECT:
746             case FLG_LCLEXPECT:
747               break;
748             default:
749               llbug (message ("Bad value flag: %s", flagcode_unparse (code)));
750             }
751           /*@=loopswitchbreak@*/          
752
753           DPRINTF (("Set value: [%s] / %d",  flagcode_unparse (code), val));
754           context_setValue (code, val);
755           DPRINTF (("Set value: [%s] / %d",  flagcode_unparse (code), context_getValue (code)));
756           llassert (context_getValue (code) == val);
757         }
758       else if (flagcode_hasChar (code))
759         {
760           llassert (code == FLG_COMMENTCHAR);
761           context_setCommentMarkerChar (DEFAULT_COMMENTCHAR);
762         }
763       else if (flagcode_hasString (code))
764         {
765           cstring val = cstring_undefined;
766           
767           switch (code)
768             { /*@-loopswitchbreak@*/
769             case FLG_LARCHPATH:
770               {
771                 cstring larchpath = osd_getEnvironmentVariable (LARCH_PATH);
772                 
773                 if (cstring_isDefined (larchpath))
774                   {
775                     val = cstring_copy (larchpath);
776                   }
777                 else
778                   {
779                     val = cstring_makeLiteral (DEFAULT_LARCHPATH);
780                   }
781                 
782                 break;
783               }
784             case FLG_LCLIMPORTDIR:
785               {
786                 val = cstring_copy (osd_getEnvironment (cstring_makeLiteralTemp (LCLIMPORTDIR), cstring_makeLiteralTemp (DEFAULT_LCLIMPORTDIR)));
787                 break;
788               }
789             case FLG_TMPDIR: 
790 # if defined(OS2) || defined(MSDOS) || defined(WIN32)
791               {
792                 char *env = osd_getEnvironmentVariable ("TMP");
793
794                 if (env == NULL)
795                   {
796                     env = osd_getEnvironmentVariable ("TEMP");
797                   }
798
799                 val = cstring_makeLiteral (env != NULL ? env : DEFAULT_TMPDIR);
800               }
801 # else
802               val = cstring_makeLiteral (DEFAULT_TMPDIR);
803 # endif /* !defined(OS2) && !defined(MSDOS) */
804
805               break;
806             case FLG_BOOLTYPE:
807               val = cstring_makeLiteral (DEFAULT_BOOLTYPE); break;
808             case FLG_BOOLFALSE:
809               val = cstring_makeLiteral ("FALSE"); break;
810             case FLG_BOOLTRUE:
811               val = cstring_makeLiteral ("TRUE"); break;
812             case FLG_MACROVARPREFIX: 
813               val = cstring_makeLiteral ("m_"); break;
814             case FLG_SYSTEMDIRS:
815               val = cstring_makeLiteral (DEFAULT_SYSTEMDIR); break;
816             default:
817               break;
818             } /*@=loopswitchbreak@*/
819
820           context_setString (code, val);
821         }
822       else
823         { 
824           ; /* nothing to set */
825         }
826     } end_allFlagCodes;
827   
828   /*
829   ** These flags are true by default.
830   */
831
832   /*@i34 move this into flags.def */
833     
834   gc.flags[FLG_STREAMOVERWRITE] = TRUE;
835
836   gc.flags[FLG_OBVIOUSLOOPEXEC] = TRUE;
837   gc.flags[FLG_MODIFIES] = TRUE;
838   gc.flags[FLG_NESTCOMMENT] = TRUE;
839   gc.flags[FLG_GLOBALS] = TRUE;
840   gc.flags[FLG_FULLINITBLOCK] = TRUE;
841   gc.flags[FLG_INITSIZE] = TRUE;
842   gc.flags[FLG_INITALLELEMENTS] = TRUE;
843
844   gc.flags[FLG_STRINGLITTOOLONG] = TRUE;
845
846   gc.flags[FLG_LIKELYBOOL] = TRUE;
847   gc.flags[FLG_ZEROPTR] = TRUE;
848   gc.flags[FLG_NUMLITERAL] = TRUE;
849   gc.flags[FLG_DUPLICATEQUALS] = TRUE;
850   gc.flags[FLG_SKIPISOHEADERS] = TRUE;
851   gc.flags[FLG_SKIPPOSIXHEADERS] = TRUE;
852   gc.flags[FLG_SYSTEMDIREXPAND] = TRUE;
853   gc.flags[FLG_UNRECOGCOMMENTS] = TRUE;
854   gc.flags[FLG_UNRECOGFLAGCOMMENTS] = TRUE;
855   gc.flags[FLG_CASTFCNPTR] = TRUE;
856   gc.flags[FLG_DOLCS] = TRUE;
857   gc.flags[FLG_USEVARARGS] = TRUE;
858   gc.flags[FLG_MAINTYPE] = TRUE;
859   gc.flags[FLG_SPECMACROS] = TRUE;
860   gc.flags[FLG_REDEF] = TRUE;
861   gc.flags[FLG_MACRONEXTLINE] = TRUE;
862
863   gc.flags[FLG_SIZEOFFORMALARRAY] = TRUE;
864   gc.flags[FLG_FIXEDFORMALARRAY] = TRUE;
865
866   gc.flags[FLG_UNRECOGDIRECTIVE] = TRUE;
867   gc.flags[FLG_WARNUSE] = TRUE;
868   gc.flags[FLG_PREDASSIGN] = TRUE;
869   gc.flags[FLG_MODOBSERVER] = TRUE;
870   gc.flags[FLG_MACROVARPREFIXEXCLUDE] = TRUE;
871   gc.flags[FLG_EXTERNALNAMECASEINSENSITIVE] = TRUE;
872
873   gc.flags[FLG_PARAMIMPTEMP] = TRUE;
874   gc.flags[FLG_RETIMPONLY] = TRUE;
875   gc.flags[FLG_GLOBIMPONLY] = TRUE;
876   gc.flags[FLG_STRUCTIMPONLY] = TRUE;
877   gc.flags[FLG_PREPROC] = TRUE;
878   gc.flags[FLG_NAMECHECKS] = TRUE;
879   gc.flags[FLG_FORMATCODE] = TRUE;
880   gc.flags[FLG_FORMATTYPE] = TRUE;
881   gc.flags[FLG_BADFLAG] = TRUE;
882   gc.flags[FLG_WARNFLAGS] = TRUE;
883   gc.flags[FLG_WARNRC] = TRUE;
884   gc.flags[FLG_FILEEXTENSIONS] = TRUE;
885   gc.flags[FLG_WARNUNIXLIB] = TRUE;
886   gc.flags[FLG_WARNPOSIX] = TRUE;
887   gc.flags[FLG_SHOWCOL] = TRUE;
888   gc.flags[FLG_SHOWFUNC] = TRUE;
889   gc.flags[FLG_SUPCOUNTS] = TRUE;
890   gc.flags[FLG_HINTS] = TRUE;
891   gc.flags[FLG_SYNTAX] = TRUE;
892   gc.flags[FLG_TYPE] = TRUE;
893   gc.flags[FLG_INCOMPLETETYPE] = TRUE;
894   gc.flags[FLG_ABSTRACT] = TRUE;
895   gc.flags[FLG_ITERBALANCE] = TRUE;
896   gc.flags[FLG_ITERYIELD] = TRUE;
897   gc.flags[FLG_DUPLICATECASES] = TRUE;
898   gc.flags[FLG_ALWAYSEXITS] = TRUE;
899   gc.flags[FLG_EMPTYRETURN] = TRUE;
900   gc.flags[FLG_MACRORETURN] = TRUE;
901   gc.flags[FLG_UNRECOG] = TRUE;
902   gc.flags[FLG_SYSTEMUNRECOG] = TRUE;
903   gc.flags[FLG_LINTCOMMENTS] = TRUE;
904   gc.flags[FLG_ACCESSCZECH] = TRUE;
905   gc.flags[FLG_ACCESSMODULE] = TRUE;
906   gc.flags[FLG_ACCESSFILE] = TRUE;
907   gc.flags[FLG_MACROVARPREFIX] = TRUE;
908
909   gc.flags[FLG_ANNOTATIONERROR] = TRUE;
910   gc.flags[FLG_COMMENTERROR] = TRUE;
911
912   /*
913   ** Changed for version 2.4.
914   */
915
916   gc.flags[FLG_GNUEXTENSIONS] = TRUE;
917
918   /*
919     Changed for 3.0.0.19
920    */
921
922   /* commenting ou until some output issues are fixed */
923   gc.flags[FLG_ORCONSTRAINT] = TRUE; 
924   
925   gc.flags[FLG_CONSTRAINTLOCATION] = TRUE;
926
927   /*drl 1/18/2002*/
928   gc.flags[FLG_WARNSYSFILES] = TRUE;
929
930   /*
931   ** On by default for Win32, but not Unix
932   */
933
934 # ifdef WIN32
935   gc.flags[FLG_PARENFILEFORMAT] = TRUE;
936   gc.flags[FLG_CASEINSENSITIVEFILENAMES] = TRUE;
937 # endif
938 }
939
940 /*
941 ** C is way-lame, and you can initialize an array to a constant except where
942 ** it is declared.  Hence, a macro is used to set the modeflags.
943 */
944
945 /*@notfunction@*/
946 # define SETFLAGS() \
947   { int i = 0; while (modeflags[i] != INVALID_FLAG) { \
948       if (!flagcode_isModeFlag (modeflags[i])) \
949         { llbug (message ("not a mode flag: %s", \
950                           flagcode_unparse (modeflags[i]))); } \
951       else { context_setFlag (modeflags[i], TRUE, g_currentloc); }  i++; }}
952
953 static void context_setModeAux (cstring p_s, bool p_warn) ;
954
955 void
956 context_setMode (cstring s)
957 {
958   context_setModeAux (s, TRUE);
959 }
960
961 void
962 context_setModeNoWarn (cstring s)
963 {
964   context_setModeAux (s, FALSE);
965 }
966
967 void
968 context_setModeAux (cstring s, bool warn)
969 {
970   intSet setflags = intSet_new ();
971   
972   allFlagCodes (code)
973     {
974       if (flagcode_isModeFlag (code))
975         {
976           if (gc.setGlobally[code])
977             {
978               (void) intSet_insert (setflags, (int) code);
979             }
980         }
981     } end_allFlagCodes;
982   
983   if (!intSet_isEmpty (setflags))
984     {
985       cstring rflags = cstring_undefined;
986       int num = 0;
987
988       intSet_elements (setflags, el)
989         {
990           if (cstring_isUndefined (rflags))
991             {
992               rflags = cstring_copy (flagcode_unparse ((flagcode) (el)));
993             }
994           else
995             {
996               rflags = message ("%q, %s", rflags, 
997                                 flagcode_unparse ((flagcode) el));
998             }
999
1000           num++;
1001           if (num > 4 && intSet_size (setflags) > 6)
1002             {
1003               rflags = message ("%q, (%d others) ...", rflags, 
1004                                 intSet_size (setflags) - num);
1005               break;
1006             }
1007         } end_intSet_elements ;
1008       
1009       if (warn)
1010         {
1011           voptgenerror (FLG_WARNFLAGS,
1012                         message ("Setting mode %s after setting mode flags will "
1013                                  "override set values of flags: %s",
1014                                  s, rflags),
1015                         g_currentloc);
1016         }
1017
1018       cstring_free (rflags);
1019     }
1020
1021   intSet_free (setflags);
1022
1023   context_resetModeFlags ();
1024
1025   if (cstring_equalLit (s, "standard"))
1026     {
1027       flagcode modeflags[] = 
1028         {
1029           FLG_ENUMINT, FLG_MACROMATCHNAME,
1030           FLG_STRINGLITNOROOM,
1031           FLG_STRINGLITNOROOMFINALNULL,
1032           FLG_MACROUNDEF, FLG_RELAXQUALS, 
1033           FLG_USEALLGLOBS, FLG_CHECKSTRICTGLOBALS,
1034           FLG_CHECKSTRICTGLOBALIAS,
1035           FLG_CHECKEDGLOBALIAS,
1036           FLG_CHECKMODGLOBALIAS,
1037           FLG_PREDBOOLOTHERS, FLG_PREDBOOLINT,
1038           FLG_UNSIGNEDCOMPARE,
1039           FLG_PARAMUNUSED, FLG_VARUNUSED, FLG_FUNCUNUSED, 
1040           FLG_TYPEUNUSED,
1041           FLG_CONSTUNUSED, FLG_ENUMMEMUNUSED, FLG_FIELDUNUSED,
1042           FLG_PTRNUMCOMPARE, FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
1043           FLG_MUTREP, FLG_NOEFFECT, FLG_IMPTYPE, 
1044           FLG_RETVALOTHER, FLG_RETVALBOOL, FLG_RETVALINT,
1045           FLG_SPECUNDEF, FLG_INCONDEFS, FLG_INCONDEFSLIB, FLG_MISPLACEDSHAREQUAL,
1046           FLG_MATCHFIELDS,
1047           FLG_FORMATCONST,
1048           FLG_MACROPARAMS, FLG_MACROASSIGN, FLG_SEFPARAMS, 
1049           FLG_MACROSTMT, FLG_MACROPARENS, 
1050           FLG_MACROFCNDECL,
1051           FLG_MACROCONSTDECL,
1052           FLG_MACROREDEF, FLG_INFLOOPS, FLG_UNREACHABLE, 
1053           FLG_NORETURN, FLG_CASEBREAK, FLG_MISSCASE, FLG_USEDEF, 
1054           FLG_FIRSTCASE,
1055           FLG_NESTEDEXTERN, 
1056           FLG_NUMLITERAL,
1057           FLG_ZEROBOOL,
1058           /* memchecks flags */
1059           FLG_NULLDEREF, 
1060           FLG_NULLSTATE, FLG_NULLASSIGN,
1061           FLG_NULLPASS, FLG_NULLRET,        
1062
1063           FLG_COMPDEF, FLG_COMPMEMPASS, FLG_UNIONDEF,
1064           FLG_RETSTACK,
1065
1066           /* memtrans flags */
1067           FLG_EXPOSETRANS,
1068           FLG_OBSERVERTRANS,
1069           FLG_DEPENDENTTRANS,
1070           FLG_NEWREFTRANS,
1071           FLG_ONLYTRANS,
1072           FLG_OWNEDTRANS,
1073           FLG_FRESHTRANS,
1074           FLG_SHAREDTRANS,
1075           FLG_TEMPTRANS,
1076           FLG_KEPTTRANS,
1077           FLG_REFCOUNTTRANS,
1078           FLG_STATICTRANS,
1079           FLG_UNKNOWNTRANS,
1080           FLG_KEEPTRANS,
1081           FLG_IMMEDIATETRANS,
1082
1083           FLG_EXPORTLOCAL,
1084
1085           FLG_USERELEASED, FLG_ALIASUNIQUE, FLG_MAYALIASUNIQUE,
1086           FLG_MUSTFREEONLY, 
1087           FLG_MUSTFREEFRESH,
1088           FLG_MUSTDEFINE, FLG_GLOBSTATE, 
1089           FLG_COMPDESTROY, FLG_MUSTNOTALIAS,
1090           FLG_MEMIMPLICIT,
1091           FLG_BRANCHSTATE, 
1092           FLG_STATETRANSFER, FLG_STATEMERGE,
1093           FLG_EVALORDER, FLG_SHADOW, FLG_READONLYSTRINGS,
1094           FLG_EXITARG,
1095           FLG_IMPCHECKEDSPECGLOBALS,
1096           FLG_MODGLOBS, FLG_WARNLINTCOMMENTS,
1097           FLG_IFEMPTY, FLG_REALCOMPARE,
1098           FLG_BOOLOPS, FLG_PTRNEGATE,
1099           FLG_SHIFTNEGATIVE,      
1100           FLG_SHIFTIMPLEMENTATION,
1101           FLG_BUFFEROVERFLOWHIGH,
1102           FLG_BUFFEROVERFLOW,
1103           INVALID_FLAG 
1104         } ;
1105
1106       SETFLAGS ();
1107     }
1108   else if (cstring_equalLit (s, "weak"))
1109     {
1110       flagcode modeflags[] = 
1111         { 
1112           FLG_BOOLINT, FLG_CHARINT, FLG_FLOATDOUBLE,
1113           FLG_ENUMINT, FLG_RELAXQUALS, FLG_FORWARDDECL, 
1114           FLG_CHARINDEX, FLG_ABSTVOIDP, FLG_USEALLGLOBS, 
1115           FLG_CHARUNSIGNEDCHAR,
1116           FLG_PREDBOOLOTHERS, 
1117           FLG_VARUNUSED, FLG_FUNCUNUSED, 
1118           FLG_TYPEUNUSED,
1119           FLG_CHECKSTRICTGLOBALS, FLG_MACROMATCHNAME,
1120           FLG_RETVALOTHER,
1121           FLG_IFEMPTY, 
1122           FLG_BUFFEROVERFLOWHIGH,
1123           FLG_RETSTACK, FLG_PTRNEGATE,
1124           FLG_STATETRANSFER, FLG_STATEMERGE,
1125           FLG_LONGUNSIGNEDINTEGRAL,
1126           FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL,
1127           FLG_NUMLITERAL,
1128           FLG_CHARINTLITERAL,
1129           FLG_ZEROBOOL,
1130           FLG_BUFFEROVERFLOWHIGH,
1131           FLG_STRINGLITNOROOM,
1132           FLG_STRINGLITNOROOMFINALNULL,
1133           INVALID_FLAG 
1134           } ;
1135
1136       SETFLAGS ();
1137     }
1138   else if (cstring_equalLit (s, "checks"))
1139     {
1140       flagcode modeflags[] = 
1141         { 
1142           FLG_EXPORTLOCAL, FLG_IMPTYPE,
1143           FLG_STATETRANSFER, FLG_STATEMERGE,
1144           FLG_CHECKSTRICTGLOBALIAS,
1145           FLG_CHECKEDGLOBALIAS,
1146           FLG_CHECKMODGLOBALIAS,
1147           FLG_UNCHECKEDGLOBALIAS,
1148           FLG_FORMATCONST,
1149           FLG_STRINGLITNOROOM,
1150           FLG_STRINGLITNOROOMFINALNULL,
1151           FLG_STRINGLITSMALLER,
1152           FLG_EXITARG, FLG_PTRNUMCOMPARE, 
1153           FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE, 
1154           FLG_MACROUNDEF, FLG_MUSTMOD, FLG_ALLGLOBALS,
1155           FLG_PREDBOOLOTHERS, FLG_PREDBOOLPTR, FLG_PREDBOOLINT,
1156           FLG_USEALLGLOBS, FLG_MUTREP, FLG_RETALIAS, 
1157           FLG_RETEXPOSE, FLG_ASSIGNEXPOSE, FLG_CASTEXPOSE,
1158           FLG_FUNCUNUSED, FLG_GLOBALSIMPMODIFIESNOTHING,
1159           FLG_TYPEUNUSED, FLG_FIELDUNUSED, FLG_PARAMUNUSED, FLG_VARUNUSED,
1160           FLG_CONSTUNUSED, FLG_ENUMMEMUNUSED,
1161           FLG_NOEFFECT, FLG_EXPORTHEADER, FLG_EXPORTHEADERVAR,
1162           FLG_RETVALOTHER, FLG_RETVALBOOL, FLG_RETVALINT,
1163           FLG_SPECUNDEF, FLG_IMPCHECKMODINTERNALS,
1164           FLG_DECLUNDEF, FLG_INCONDEFS, FLG_INCONDEFSLIB, 
1165           FLG_MISPLACEDSHAREQUAL, FLG_REDUNDANTSHAREQUAL,
1166           FLG_MATCHFIELDS, 
1167           FLG_MACROPARAMS,
1168           FLG_MACROASSIGN,
1169           FLG_DECLPARAMMATCH,
1170           FLG_FCNDEREF,
1171           FLG_FIRSTCASE,
1172           FLG_SEFPARAMS, FLG_SEFUNSPEC, FLG_MACROSTMT, FLG_MACROPARENS, 
1173           FLG_MACROCONSTDECL,
1174           FLG_MACROFCNDECL,
1175           FLG_MACROREDEF, 
1176           FLG_INFLOOPS, FLG_INFLOOPSUNCON,
1177           FLG_UNREACHABLE, 
1178           FLG_NORETURN, FLG_CASEBREAK, FLG_MISSCASE,
1179           FLG_EVALORDER, FLG_USEDEF, 
1180           FLG_NESTEDEXTERN, 
1181
1182           /* warn use flags */
1183           FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
1184           FLG_BUFFEROVERFLOWHIGH,
1185
1186           /* memchecks flags */
1187
1188           FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
1189           FLG_NULLPASS, FLG_NULLRET,
1190
1191           FLG_COMPDEF, FLG_COMPMEMPASS, FLG_UNIONDEF, FLG_RETSTACK,       
1192
1193           /* memtrans flags */
1194           FLG_EXPOSETRANS,
1195           FLG_OBSERVERTRANS,
1196           FLG_DEPENDENTTRANS,
1197           FLG_NEWREFTRANS,
1198           FLG_ONLYTRANS,
1199           FLG_OWNEDTRANS,
1200           FLG_FRESHTRANS,
1201           FLG_SHAREDTRANS,
1202           FLG_TEMPTRANS,
1203           FLG_KEPTTRANS,
1204           FLG_REFCOUNTTRANS,
1205           FLG_STATICTRANS,
1206           FLG_UNKNOWNTRANS,
1207           FLG_STATICINITTRANS,
1208           FLG_UNKNOWNINITTRANS,
1209           FLG_KEEPTRANS,
1210           FLG_IMMEDIATETRANS,
1211           FLG_ONLYUNQGLOBALTRANS,
1212           FLG_USERELEASED, FLG_ALIASUNIQUE, FLG_MAYALIASUNIQUE,
1213           FLG_MUSTFREEONLY,
1214           FLG_MUSTFREEFRESH,
1215           FLG_MUSTDEFINE, FLG_GLOBSTATE, 
1216           FLG_COMPDESTROY, FLG_MUSTNOTALIAS,
1217           FLG_MEMIMPLICIT,
1218           FLG_BRANCHSTATE, 
1219           FLG_NULLPOINTERARITH,
1220           FLG_SHADOW, FLG_DEPARRAYS,
1221           FLG_REDECL, FLG_READONLYSTRINGS, FLG_READONLYTRANS,
1222           FLG_LOOPLOOPBREAK, FLG_SWITCHLOOPBREAK, FLG_MODGLOBS,
1223           FLG_CHECKSTRICTGLOBALS, FLG_IMPCHECKEDSPECGLOBALS,
1224           FLG_MACROMATCHNAME, FLG_WARNLINTCOMMENTS,
1225           FLG_INCLUDENEST, FLG_ISORESERVED, FLG_CPPNAMES, 
1226           FLG_NOPARAMS, FLG_IFEMPTY, FLG_WHILEEMPTY, FLG_REALCOMPARE,
1227           FLG_BOOLOPS, FLG_SHIFTNEGATIVE,
1228           FLG_SHIFTIMPLEMENTATION,
1229           FLG_BUFFEROVERFLOWHIGH, FLG_BUFFEROVERFLOW,
1230           INVALID_FLAG } ;
1231
1232       SETFLAGS ();
1233     }
1234   else if (cstring_equalLit (s, "strict"))
1235     {
1236       flagcode modeflags[] = 
1237         { 
1238           FLG_CHECKSTRICTGLOBALIAS,
1239           FLG_CHECKEDGLOBALIAS,
1240           FLG_CHECKMODGLOBALIAS,
1241           FLG_UNCHECKEDGLOBALIAS,
1242           FLG_MODFILESYSTEM,
1243           FLG_MACROMATCHNAME,
1244           FLG_FORMATCONST,
1245           FLG_STRINGLITNOROOM,
1246           FLG_STRINGLITNOROOMFINALNULL,
1247           FLG_STRINGLITSMALLER,
1248           FLG_STATETRANSFER, FLG_STATEMERGE,
1249           FLG_MACROUNDEF, FLG_MUTREP, FLG_MUSTMOD,
1250           FLG_ALLGLOBALS, FLG_IMPTYPE,
1251           FLG_MODNOMODS, FLG_MODGLOBSUNSPEC, FLG_MODSTRICTGLOBSUNSPEC,
1252           FLG_GLOBUNSPEC, FLG_SIZEOFTYPE,
1253           FLG_EXPORTHEADER, FLG_EXPORTHEADERVAR,
1254           FLG_NOPARAMS, FLG_OLDSTYLE, FLG_EXITARG, 
1255           FLG_RETSTACK,
1256           FLG_FCNDEREF,
1257           FLG_ONLYUNQGLOBALTRANS,
1258           FLG_GLOBALSIMPMODIFIESNOTHING,
1259           FLG_PREDBOOLOTHERS, FLG_PREDBOOLPTR, FLG_PREDBOOLINT,
1260           FLG_INTERNALGLOBS, FLG_INTERNALGLOBSNOGLOBS,
1261           FLG_USEALLGLOBS, FLG_RETALIAS, 
1262           FLG_MODGLOBS, FLG_MODGLOBSUNSPEC, FLG_MODGLOBSUNCHECKED,
1263           FLG_RETEXPOSE, FLG_ASSIGNEXPOSE, FLG_CASTEXPOSE,
1264           FLG_NOEFFECTUNCON, FLG_EVALORDERUNCON,
1265           FLG_FUNCUNUSED,
1266           FLG_EXPORTITER, FLG_EXPORTCONST,
1267           FLG_TYPEUNUSED, FLG_FIELDUNUSED, FLG_PARAMUNUSED, FLG_TOPUNUSED,
1268           FLG_CONSTUNUSED, FLG_ENUMMEMUNUSED,
1269           FLG_VARUNUSED, 
1270           FLG_NULLPOINTERARITH, FLG_POINTERARITH, 
1271           FLG_PTRNUMCOMPARE, 
1272           FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
1273           FLG_NOEFFECT, FLG_RETVALINT, FLG_RETVALBOOL, FLG_RETVALOTHER, 
1274           FLG_ISORESERVED, FLG_ISORESERVEDLOCAL, FLG_CPPNAMES,
1275           FLG_RETVALBOOL, FLG_RETVALINT, FLG_SPECUNDEF, 
1276           FLG_DECLUNDEF, FLG_STRICTOPS, FLG_INCONDEFS, 
1277           FLG_MISPLACEDSHAREQUAL, FLG_REDUNDANTSHAREQUAL,
1278           FLG_INCONDEFSLIB, FLG_MATCHFIELDS, FLG_EXPORTMACRO, FLG_EXPORTVAR, 
1279           FLG_EXPORTFCN, FLG_EXPORTTYPE, FLG_EXPORTLOCAL, FLG_MACROPARAMS, 
1280           FLG_MACROASSIGN,
1281           FLG_SEFPARAMS, FLG_SEFUNSPEC, FLG_MACROSTMT, FLG_MACROPARENS, 
1282           FLG_MACROFCNDECL,
1283           FLG_MACROCONSTDECL,
1284           FLG_MACROREDEF, FLG_MACROEMPTY,
1285           FLG_INFLOOPS, FLG_INFLOOPSUNCON,
1286           FLG_UNREACHABLE, 
1287           FLG_NORETURN, FLG_CASEBREAK, FLG_MISSCASE, FLG_USEDEF,
1288           FLG_EVALORDER,
1289           FLG_MODUNCON, FLG_MODUNCONNOMODS, FLG_MODINTERNALSTRICT,
1290           FLG_MODOBSERVERUNCON,
1291
1292           FLG_NESTEDEXTERN, 
1293           FLG_FIRSTCASE,
1294
1295           /* warn use flags */
1296           FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
1297           FLG_BUFFEROVERFLOWHIGH,
1298           FLG_BUFFEROVERFLOW, FLG_TOCTOU,
1299
1300           /* memchecks flags */
1301           FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
1302           FLG_NULLPASS, FLG_NULLRET,
1303
1304           FLG_COMPDEF, FLG_COMPMEMPASS, FLG_UNIONDEF,
1305
1306           /* memtrans flags */
1307           FLG_EXPOSETRANS,
1308           FLG_OBSERVERTRANS,
1309           FLG_DEPENDENTTRANS,
1310           FLG_NEWREFTRANS,
1311           FLG_ONLYTRANS,
1312           FLG_OWNEDTRANS,
1313           FLG_FRESHTRANS,
1314           FLG_SHAREDTRANS,
1315           FLG_TEMPTRANS,
1316           FLG_KEPTTRANS,
1317           FLG_REFCOUNTTRANS,
1318           FLG_STATICTRANS,
1319           FLG_UNKNOWNTRANS,
1320           FLG_KEEPTRANS,
1321           FLG_IMMEDIATETRANS,
1322           FLG_STATICINITTRANS,
1323           FLG_UNKNOWNINITTRANS,
1324
1325           FLG_USERELEASED, FLG_ALIASUNIQUE, FLG_MAYALIASUNIQUE,
1326           FLG_MUSTFREEONLY,
1327           FLG_MUSTFREEFRESH,
1328           FLG_MUSTDEFINE, FLG_GLOBSTATE, 
1329           FLG_COMPDESTROY, FLG_MUSTNOTALIAS,
1330           FLG_MEMIMPLICIT,
1331           FLG_BRANCHSTATE, 
1332
1333           FLG_DECLPARAMNAME, FLG_DECLPARAMMATCH,
1334
1335           FLG_SHADOW, FLG_DEPARRAYS, 
1336           FLG_STRICTDESTROY, FLG_STRICTUSERELEASED, FLG_STRICTBRANCHSTATE,
1337           FLG_REDECL, FLG_READONLYSTRINGS, FLG_READONLYTRANS,
1338           FLG_LOOPLOOPBREAK, FLG_LOOPSWITCHBREAK, FLG_SWITCHLOOPBREAK,
1339           FLG_SWITCHSWITCHBREAK, FLG_LOOPLOOPCONTINUE,
1340           FLG_CHECKSTRICTGLOBALS, FLG_IMPCHECKEDSPECGLOBALS,
1341           FLG_ALLGLOBALS, FLG_IMPCHECKEDSTRICTGLOBALS,
1342           FLG_IMPCHECKEDSTRICTSTATICS,
1343           FLG_IMPCHECKEDSTRICTSPECGLOBALS,
1344           FLG_IMPCHECKMODINTERNALS,
1345           FLG_WARNMISSINGGLOBALS, FLG_WARNMISSINGGLOBALSNOGLOBS,
1346           FLG_WARNLINTCOMMENTS, FLG_ISORESERVEDLOCAL,
1347           FLG_INCLUDENEST, FLG_STRINGLITERALLEN,
1348           FLG_NUMSTRUCTFIELDS, FLG_NUMENUMMEMBERS,
1349           FLG_CONTROLNESTDEPTH,
1350           FLG_FORBLOCK, FLG_WHILEBLOCK,
1351           FLG_FOREMPTY, FLG_WHILEEMPTY,
1352           FLG_IFEMPTY, FLG_IFBLOCK,
1353           FLG_ELSEIFCOMPLETE,
1354           FLG_REALCOMPARE, FLG_BOOLOPS,
1355           FLG_SYSTEMDIRERRORS, FLG_UNUSEDSPECIAL,
1356
1357           FLG_SHIFTNEGATIVE,
1358           FLG_SHIFTIMPLEMENTATION,
1359           FLG_BITWISEOPS,
1360           FLG_BUFFEROVERFLOWHIGH, FLG_BUFFEROVERFLOW,
1361           INVALID_FLAG
1362         } ;
1363
1364       SETFLAGS ();
1365     }
1366   else
1367     {
1368       llcontbug (message ("context_setMode: bad mode: %s", s));
1369      }
1370 }
1371
1372 bool
1373 context_isSpecialFile (cstring fname)
1374 {
1375   cstring ext = fileLib_getExtension (fname);
1376   
1377   return (cstring_equalLit (ext, ".y") 
1378           || cstring_equalLit (ext, ".l")
1379           || cstring_equalLit (fname, "lex.yy.c"));
1380 }
1381
1382 bool
1383 context_isSystemDir (cstring dir)
1384 {
1385   cstring thisdir = cstring_copy (context_getString (FLG_SYSTEMDIRS));
1386   cstring savedir = thisdir;
1387   cstring nextdir = cstring_afterChar (thisdir, PATH_SEPARATOR);
1388   
1389   if (cstring_isDefined (nextdir))
1390     {
1391       /*@access cstring@*/
1392       *nextdir = '\0'; /* closes thisdir */
1393       nextdir += 1;
1394       /*@noaccess cstring@*/
1395     }
1396
1397   /* 2001-09-09: added thisdir[0] != '\0' 
1398   **   herbert: don't compare with an empty name! 
1399   **   should return false for empty directory path
1400   */
1401
1402   while (!cstring_isEmpty (thisdir))
1403     {
1404       DPRINTF (("Test: %s / %s", dir, thisdir));
1405
1406       if (osd_equalCanonicalPrefix (dir, thisdir))
1407         {
1408           cstring_free (savedir);
1409           return TRUE;
1410         }
1411
1412       if (cstring_isDefined (nextdir))
1413         {
1414           thisdir = nextdir;
1415           nextdir = cstring_afterChar (thisdir, PATH_SEPARATOR);
1416           
1417           if (cstring_isDefined (nextdir))
1418             {
1419               /*@access cstring@*/
1420               *nextdir = '\0';
1421               nextdir += 1;
1422               /*@noaccess cstring@*/
1423             } 
1424         }
1425       else
1426         {
1427           break;
1428         }
1429     } 
1430
1431   DPRINTF (("Returns FALSE"));
1432   cstring_free (savedir);
1433   return FALSE;
1434 }
1435
1436 void
1437 context_addFileAccessType (typeId t)
1438 {
1439   cstring base;
1440
1441   if (context_inFunctionLike ())
1442     {
1443       gc.acct = typeIdSet_insert (gc.acct, t);
1444     }
1445   
1446   gc.facct = typeIdSet_insert (gc.facct, t);
1447   
1448   base = fileloc_getBase (g_currentloc);
1449   insertModuleAccess (base, t);
1450   DPRINTF (("Add file access: %s / %s", typeIdSet_unparse (gc.facct),
1451             typeIdSet_unparse (gc.acct)));
1452 }
1453
1454 void
1455 context_removeFileAccessType (typeId t)
1456 {
1457   if (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN 
1458       || gc.kind == CX_UNKNOWNMACRO)
1459     {
1460       gc.acct = typeIdSet_removeFresh (gc.acct, t);
1461     }
1462   
1463   gc.facct = typeIdSet_removeFresh (gc.facct, t);
1464   gc.nacct = typeIdSet_insert (gc.nacct, t);
1465 }
1466
1467 void context_enterFunctionHeader (void)
1468 {
1469   if (context_getFlag (FLG_GRAMMAR))
1470     {
1471       lldiagmsg (message ("Enter function header: %q", context_unparse ()));
1472     }
1473
1474   if (gc.kind != CX_GLOBAL)
1475     {
1476       llparseerror (cstring_makeLiteral
1477                     ("Likely parse error.  Function header outside global context."));
1478     }
1479   else
1480     {
1481       llassert (gc.kind == CX_GLOBAL);
1482       DPRINTF (("Enter function header!"));
1483       gc.inFunctionHeader = TRUE;
1484     }
1485 }
1486
1487 void context_exitFunctionHeader (void)
1488 {
1489   if (context_getFlag (FLG_GRAMMAR))
1490     {
1491       lldiagmsg (message ("Exit function header: %q", context_unparse ()));
1492     }
1493
1494   DPRINTF (("Exit function header!"));
1495   gc.inFunctionHeader = FALSE;
1496 }
1497
1498 bool context_inFunctionHeader (void)
1499 {
1500   return (gc.inFunctionHeader);
1501 }
1502
1503 void context_enterFunctionDeclaration (uentry e)
1504 {
1505   if (context_getFlag (FLG_GRAMMAR))
1506     {
1507       lldiagmsg (message ("Enter function declaration: %q", context_unparse ()));
1508     }
1509
1510   DPRINTF (("Enter function decl"));
1511   llassert (gc.savekind == CX_ERROR);
1512   gc.savekind = gc.kind;
1513   gc.savecont = gc.cont;
1514   gc.kind = CX_FCNDECLARATION;
1515   gc.cont.fcn = e;
1516 }
1517
1518 void context_exitFunctionDeclaration (void)
1519 {
1520   if (context_getFlag (FLG_GRAMMAR))
1521     {
1522       lldiagmsg (message ("Exit function declaration: %q", context_unparse ()));
1523     }
1524
1525   DPRINTF (("Exit function decl"));
1526   llassert (gc.savekind != CX_ERROR);
1527   llassert (gc.kind == CX_FCNDECLARATION);
1528   gc.kind = gc.savekind;
1529   gc.cont = gc.savecont;
1530
1531   gc.savekind = CX_ERROR;
1532
1533   if (context_getFlag (FLG_GRAMMAR))
1534     {
1535       lldiagmsg (message ("After exit function declaration: %q", context_unparse ()));
1536     }
1537 }
1538
1539 bool context_inFunctionDeclaration (void)
1540 {
1541   return (gc.kind == CX_FCNDECLARATION);
1542 }
1543
1544
1545 void
1546 context_enterMacro (/*@observer@*/ uentry e)
1547 {
1548   context_enterFunction (e);
1549   gc.kind = CX_MACROFCN;
1550 }
1551
1552 void
1553 context_enterUnknownMacro (/*@dependent@*/ uentry e)
1554 {
1555   llassert (uentry_isFunction (e));
1556   context_enterFunction (e);
1557   gc.kind = CX_UNKNOWNMACRO;
1558 }
1559
1560 void context_enterAndClause (exprNode e)
1561 {
1562   
1563   usymtab_trueBranch (guardSet_copy (exprNode_getGuards (e)));
1564   pushClause (ANDCLAUSE);
1565 }
1566
1567 void context_enterOrClause (exprNode e)
1568 {
1569   usymtab_trueBranch (guardSet_invert (exprNode_getGuards (e)));
1570   pushClause (ORCLAUSE);
1571 }
1572
1573 bool context_inDeepLoop (void)
1574 {
1575   bool inLoop = FALSE;
1576
1577   clauseStack_elements (gc.clauses, el)
1578     {
1579       if (clause_isLoop (el))
1580         {
1581           if (inLoop)
1582             {
1583               return TRUE;
1584             }
1585
1586           inLoop = TRUE;
1587         }
1588     } end_clauseStack_elements;
1589
1590   return FALSE;
1591 }
1592
1593 bool context_inDeepSwitch (void)
1594 {
1595   bool inLoop = FALSE;
1596
1597   clauseStack_elements (gc.clauses, el)
1598     {
1599       if (clause_isSwitch (el))
1600         {
1601           if (inLoop)
1602             {
1603               return TRUE;
1604             }
1605
1606           inLoop = TRUE;
1607         }
1608     } end_clauseStack_elements;
1609
1610   return FALSE;
1611 }
1612
1613 bool context_inDeepLoopSwitch (void)
1614 {
1615   bool inLoop = FALSE;
1616
1617   clauseStack_elements (gc.clauses, el)
1618     {
1619       if (clause_isBreakable (el))
1620         {
1621           if (inLoop)
1622             {
1623               return TRUE;
1624             }
1625
1626           inLoop = TRUE;
1627         }
1628     } end_clauseStack_elements;
1629
1630   return FALSE;
1631 }
1632
1633 clause context_breakClause (void)
1634 {
1635   clauseStack_elements (gc.clauses, el)
1636     {
1637       if (clause_isSwitch (el))
1638         {
1639           return el;
1640         }
1641       else if (clause_isLoop (el))
1642         {
1643           return el;
1644         }
1645       else
1646         {
1647           ;
1648         }
1649     } end_clauseStack_elements;
1650
1651   return NOCLAUSE;
1652 }
1653
1654 clause context_nextBreakClause (void)
1655 {
1656   bool hasOne = FALSE;
1657
1658   clauseStack_elements (gc.clauses, el)
1659     {
1660       if (clause_isBreakable (el))
1661         {
1662           if (hasOne)
1663             {
1664               return el;
1665             }
1666           else
1667             {
1668               hasOne = TRUE;
1669             }
1670         }
1671     } end_clauseStack_elements;
1672
1673   return NOCLAUSE;
1674 }
1675   
1676 bool context_inConditional (void)
1677 {
1678   clauseStack_elements (gc.clauses, el)
1679     {
1680       /*
1681       ** Should also include TRUECLAUSE and FALSECLAUSE, but need
1682       ** to distinguish if from ? for this
1683       */
1684
1685       if (clause_isBreakable (el) && (el != DOWHILECLAUSE))
1686         {
1687           return TRUE;
1688         }
1689     } end_clauseStack_elements;
1690
1691   return FALSE;
1692 }
1693
1694 void context_exitAndClause (exprNode pred, exprNode tbranch)
1695 {
1696   context_setJustPopped ();
1697   
1698   llassert (gc.inclause == ANDCLAUSE);
1699   
1700   usymtab_popAndBranch (pred, tbranch);
1701   clauseStack_pop (gc.clauses);
1702   gc.inclause = topClause (gc.clauses);
1703 }
1704
1705 void context_exitOrClause (exprNode pred, exprNode tbranch)
1706 {
1707   context_setJustPopped ();
1708   
1709   llassert (gc.inclause == ORCLAUSE);
1710   
1711   usymtab_popOrBranch (pred, tbranch);
1712   clauseStack_pop (gc.clauses);
1713   gc.inclause = topClause (gc.clauses);
1714 }
1715
1716 static void context_enterCondClauseAux (clause cl)
1717      /*@modifies gc@*/
1718 {
1719   pushClause (cl);
1720 }
1721
1722 static void context_enterTrueAux (exprNode e, clause cl)
1723    /*@modifies gc@*/
1724 {
1725   usymtab_trueBranch (guardSet_copy (exprNode_getGuards (e)));
1726   pushClause (cl);
1727 }
1728
1729 void context_enterIterClause (void)
1730 {
1731   context_enterTrueAux (exprNode_undefined, ITERCLAUSE);
1732 }
1733
1734 void context_enterDoWhileClause (void)
1735 {
1736   pushClause (DOWHILECLAUSE);
1737 }
1738
1739 void context_enterWhileClause (exprNode e)
1740 {
1741   context_enterTrueAux (e, WHILECLAUSE);
1742 }
1743
1744 void context_enterForClause (exprNode e)
1745 {
1746   context_enterTrueAux (e, FORCLAUSE);
1747 }
1748
1749 void context_enterTrueClause (exprNode e)
1750 {
1751   context_enterTrueAux (e, TRUECLAUSE);
1752 }
1753
1754 void context_enterSwitch (exprNode e)
1755 {
1756   DPRINTF (("Enter switch: %s", exprNode_unparse (e)));
1757   usymtab_switchBranch (e);
1758   context_enterCondClauseAux (SWITCHCLAUSE);
1759 }
1760
1761 void context_exitSwitch (exprNode e, bool allpaths)
1762 {
1763   usymtab_exitSwitch (e, allpaths);
1764   
1765   while (clause_isCase (clauseStack_top (gc.clauses)))
1766     {
1767       clauseStack_pop (gc.clauses);
1768     }
1769   
1770   context_exitClauseSimp ();
1771 }
1772
1773 void context_enterCaseClause (exprNode e)
1774 {
1775   bool branch = FALSE;
1776  
1777   DPRINTF (("Enter case clause!"));
1778
1779   branch = usymtab_newCase (exprNode_undefined, e);
1780   
1781   if (branch)
1782     {
1783       context_enterCondClauseAux (CASECLAUSE);
1784     }
1785 }
1786
1787 static void context_enterFalseClauseAux (exprNode e, clause cl)
1788      /*@modifies gc@*/
1789 {
1790   usymtab_altBranch (guardSet_invert (exprNode_getGuards (e)));
1791   gc.inclause = cl;
1792   clauseStack_switchTop (gc.clauses, cl);
1793 }
1794
1795 void context_enterFalseClause (exprNode e)
1796 {
1797   
1798   context_enterFalseClauseAux (e, FALSECLAUSE);
1799 }
1800
1801 void
1802 context_enterConstantMacro (/*@exposed@*/ /*@dependent@*/ uentry e)
1803 {
1804   gc.kind = CX_MACROCONST;
1805   gc.cont.fcn = e;
1806   gc.showfunction = context_getFlag (FLG_SHOWFUNC);
1807
1808   gc.acct = typeIdSet_subtract (typeIdSet_union (gc.facct, uentry_accessType (e)), 
1809                                 gc.nacct);
1810
1811   
1812   usymtab_enterScope ();
1813   sRef_enterFunctionScope ();
1814
1815   gc.globs = globSet_undefined;
1816   globSet_clear (gc.globs_used);
1817   gc.mods = sRefSet_undefined;
1818 }
1819
1820 uentry context_getHeader (void)
1821 {
1822   if (!(context_inFunctionLike () || (gc.kind == CX_MACROCONST)))
1823     {
1824       llfatalbug (message ("context_getHeader: bad call: %q",
1825                            context_unparse ()));
1826     }
1827
1828   return (gc.cont.fcn);
1829 }
1830
1831 void
1832 context_setFunctionDefined (fileloc loc)
1833 {
1834   switch (gc.kind)
1835     {
1836     case CX_UNKNOWNMACRO:
1837     case CX_FUNCTION:
1838     case CX_MACROFCN:
1839       uentry_setFunctionDefined (gc.cont.fcn, loc);
1840       break;
1841     default:
1842       /* (not a bug because of parse errors) */
1843       break;
1844     }
1845 }
1846
1847 void
1848 context_enterFunction (/*@exposed@*/ uentry e)
1849 {
1850   gc.kind = CX_FUNCTION;
1851   gc.cont.fcn = e;
1852
1853   DPRINTF (("Enter function: %s", uentry_unparse (e)));
1854
1855   if (uentry_hasAccessType (e))
1856     {
1857       gc.acct = typeIdSet_subtract (typeIdSet_union (gc.facct, uentry_accessType (e)), 
1858                                     gc.nacct);
1859     }
1860   else
1861     {
1862       gc.acct = gc.facct;
1863     }
1864
1865   DPRINTF (("Enter function: %s / %s", uentry_unparse (e), 
1866             typeIdSet_unparse (gc.acct)));
1867
1868   gc.showfunction = context_getFlag (FLG_SHOWFUNC);
1869   
1870   gc.globs = uentry_getGlobs (e);
1871   globSet_clear (gc.globs_used);
1872   gc.mods = uentry_getMods (e);
1873
1874   usymtab_enterFunctionScope (e);
1875   sRef_enterFunctionScope ();
1876 }
1877
1878 bool context_inOldSytleScope(void)
1879 {
1880   if (gc.kind == CX_OLDSTYLESCOPE)
1881     return TRUE;
1882   else
1883     return FALSE;
1884 }
1885
1886 void
1887 context_enterOldStyleScope (void)
1888 {
1889   gc.kind = CX_OLDSTYLESCOPE;
1890   DPRINTF (("Enter old style scope!"));
1891   usymtab_enterFunctionScope (uentry_undefined);
1892 }
1893
1894 void 
1895 context_completeOldStyleFunction (uentry e)
1896 {
1897   llassert (gc.kind == CX_OLDSTYLESCOPE);
1898
1899   gc.kind = CX_FUNCTION;
1900   gc.cont.fcn = e;
1901   
1902   DPRINTF (("Enter function: %s", uentry_unparse (e)));
1903   
1904   if (uentry_hasAccessType (e))
1905     {
1906       gc.acct = typeIdSet_subtract (typeIdSet_union (gc.facct, uentry_accessType (e)), 
1907                                     gc.nacct);
1908     }
1909   else
1910     {
1911       gc.acct = gc.facct;
1912     }
1913   
1914   DPRINTF (("Enter function: %s / %s", uentry_unparse (e), 
1915             typeIdSet_unparse (gc.acct)));
1916   
1917   gc.showfunction = context_getFlag (FLG_SHOWFUNC);
1918   
1919   if (!globSet_isEmpty (uentry_getGlobs (e))) 
1920     {
1921       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
1922                              fileloc_unparse (g_currentloc), uentry_unparse (e)));
1923     }
1924
1925   gc.showfunction = context_getFlag (FLG_SHOWFUNC);
1926   
1927   gc.globs = uentry_getGlobs (e);
1928   globSet_clear (gc.globs_used);
1929
1930   gc.mods = uentry_getMods (e);
1931
1932   if (!sRefSet_isEmpty (gc.mods))
1933     {
1934       llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
1935                              fileloc_unparse (g_currentloc), uentry_unparse (e)));
1936     }
1937
1938   sRef_enterFunctionScope ();
1939 }
1940
1941 static bool context_checkStrictGlobals (void)
1942 {
1943   return (context_getFlag (FLG_CHECKSTRICTGLOBALS));
1944 }
1945
1946 static bool context_hasGlobs (void)
1947 {
1948   if (context_inFunctionLike ())
1949     {
1950       return (uentry_hasGlobs (gc.cont.fcn));
1951     }
1952   else
1953     {
1954       return (FALSE);
1955     }
1956 }
1957
1958 static bool context_checkCheckedGlobals (void)
1959 {
1960   return (context_getFlag (FLG_GLOBALS)
1961           && (context_getFlag (FLG_GLOBUNSPEC)
1962               || context_hasGlobs ()));
1963 }
1964
1965 static bool context_checkUnknownGlobals (void)
1966 {
1967   /* should be uentry_hasGlobs ? */
1968
1969   return (context_getFlag (FLG_ALLGLOBALS)
1970           && (context_getFlag (FLG_GLOBUNSPEC)
1971               || context_hasGlobs ()));
1972 }      
1973
1974 static bool context_checkUncheckedGlobals (void)
1975 {
1976   return (FALSE);
1977 }      
1978
1979 bool 
1980 context_checkExport (uentry e)
1981 {
1982   if (!gc.anyExports) return FALSE;
1983
1984   if (uentry_isFunction (e)
1985       || (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))))
1986     {
1987       return context_maybeSet (FLG_EXPORTFCN);
1988     }
1989   else if (uentry_isExpandedMacro (e))
1990     {
1991       return context_maybeSet (FLG_EXPORTMACRO);
1992     }
1993   else if (uentry_isVariable (e))
1994     {
1995       return context_maybeSet (FLG_EXPORTVAR);
1996     }
1997   else if (uentry_isEitherConstant (e))
1998     {
1999       return context_maybeSet (FLG_EXPORTCONST);
2000     }
2001   else if (uentry_isIter (e) || uentry_isEndIter (e))
2002     {
2003       return context_maybeSet (FLG_EXPORTITER);
2004     }
2005   else if (uentry_isDatatype (e))
2006     {
2007       return context_maybeSet (FLG_EXPORTTYPE);
2008     }
2009   else
2010     {
2011       BADEXIT;
2012     }
2013 }
2014               
2015 bool
2016 context_checkGlobUse (uentry glob)
2017 {
2018   
2019   if (uentry_isCheckedStrict (glob))
2020     {
2021       return context_checkStrictGlobals ();
2022     }
2023   else if (uentry_isChecked (glob))
2024     {
2025       return context_checkCheckedGlobals ();
2026     }
2027   else if (uentry_isCheckedUnknown (glob) || uentry_isCheckMod (glob))
2028     {
2029       return context_checkUnknownGlobals ();
2030     }
2031   else 
2032     {
2033       llassert (uentry_isUnchecked (glob));
2034
2035       return context_checkUncheckedGlobals ();
2036     }
2037 }
2038
2039 bool
2040 context_checkAliasGlob (uentry glob)
2041 {
2042   if (uentry_isCheckedStrict (glob))
2043     {
2044       return gc.flags[FLG_CHECKSTRICTGLOBALIAS];
2045     }
2046   else if (uentry_isChecked (glob))
2047     {
2048       return gc.flags[FLG_CHECKEDGLOBALIAS];
2049     }
2050   else if (uentry_isCheckMod (glob))
2051     {
2052       return gc.flags[FLG_CHECKMODGLOBALIAS];
2053     }
2054   else 
2055     {
2056       llassert (uentry_isUnchecked (glob) || uentry_isCheckedUnknown (glob));
2057
2058       return gc.flags[FLG_UNCHECKEDGLOBALIAS];
2059     }
2060 }
2061
2062 bool context_checkInternalUse (void)
2063 {
2064   if (context_hasGlobs ())
2065     {
2066       return (gc.flags[FLG_INTERNALGLOBS]);
2067     }
2068   else
2069     {
2070       return (gc.flags[FLG_INTERNALGLOBSNOGLOBS]);
2071     }
2072 }
2073
2074 bool
2075 context_checkGlobMod (sRef el)
2076 {
2077   uentry ue = sRef_getUentry (el);
2078
2079   /* no: llassert (sRef_isFileOrGlobalScope (el)); also check local statics */
2080
2081   if (uentry_isCheckedModify (ue)
2082       || (!uentry_isUnchecked (ue) && (gc.flags[FLG_ALLGLOBALS])))
2083     {
2084       if (context_hasMods ())
2085         {
2086           return (gc.flags[FLG_MODGLOBS]);
2087         }
2088       else
2089         {
2090           if (uentry_isCheckedStrict (ue))
2091             {
2092               return (gc.flags[FLG_MODGLOBSUNSPEC]);
2093             }
2094           else
2095             {
2096               return (gc.flags[FLG_MODSTRICTGLOBSUNSPEC]);
2097             }
2098         }
2099     }
2100   else
2101     {
2102       if (context_hasMods ())
2103         {
2104           return (gc.flags[FLG_MODGLOBSUNCHECKED]);
2105         }
2106       else
2107         {
2108           return FALSE;
2109         }
2110     }
2111 }
2112
2113 void
2114 context_usedGlobal (/*@exposed@*/ sRef el)
2115 {
2116   if (!globSet_member (gc.globs_used, el))
2117     {
2118       /* 
2119       ** The first time a global is used in a function, we need
2120       ** to clear the derived sRefs, since they were set for the
2121       ** previous function.
2122       */
2123
2124       sRef_clearDerived (el);
2125       gc.globs_used = globSet_insert (gc.globs_used, el);
2126     }
2127 }
2128
2129 /*@observer@*/ sRefSet
2130 context_modList (void)
2131 {
2132   return gc.mods;
2133 }
2134
2135 bool
2136 context_globAccess (sRef s)
2137 {
2138   llassert (sRef_isFileOrGlobalScope (s) || sRef_isKindSpecial (s));
2139   return (globSet_member (gc.globs, s));
2140 }
2141
2142 bool
2143 context_hasAccess (typeId t)
2144 {
2145   if (context_inFunctionLike ())
2146     {
2147       DPRINTF (("Access %d / %s",
2148                 t, typeIdSet_unparse (gc.acct)));
2149       return (typeIdSet_member (gc.acct, t));
2150     }
2151   else
2152     {
2153       return (context_hasFileAccess (t));
2154     }
2155 }
2156
2157 bool
2158 context_hasFileAccess (typeId t)
2159 {
2160   return (typeIdSet_member (gc.facct, t));
2161 }
2162
2163 /*@only@*/ cstring
2164 context_unparseAccess (void)
2165 {
2166   return (message ("%q / %q", typeIdSet_unparse (gc.acct),
2167                    typeIdSet_unparse (gc.facct)));
2168 }
2169
2170 /*@only@*/ cstring
2171 context_unparseClauses (void)
2172 {
2173   return (clauseStack_unparse (gc.clauses));
2174 }
2175
2176 bool
2177 context_couldHaveAccess (typeId t)
2178 {
2179   if (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN || gc.kind == CX_UNKNOWNMACRO)
2180     {
2181       return (typeIdSet_member (gc.acct, t));
2182     }
2183   else
2184     {
2185       return (typeIdSet_member (gc.facct, t)); 
2186     }
2187 }
2188
2189 ctype
2190 context_getRetType (void)
2191 {
2192   ctype f = ctype_undefined;
2193
2194   if (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN)
2195     {
2196       f = uentry_getType (gc.cont.fcn);
2197     }
2198   else if (gc.kind == CX_UNKNOWNMACRO)
2199     {
2200       return ctype_unknown;
2201     }
2202   else
2203     {
2204       llcontbuglit ("context_getRetType: not in a function context");
2205       return ctype_unknown;
2206     }
2207
2208   if (!ctype_isFunction (f))
2209     {
2210       if (ctype_isKnown (f))
2211         {
2212           llbuglit ("context_getRetType: not a function");
2213         }
2214
2215       return ctype_unknown;
2216     }
2217   return (ctype_getReturnType (f));
2218 }    
2219
2220 bool
2221 context_hasMods (void)
2222 {
2223   if (context_inFunctionLike ())
2224     {
2225       return (uentry_hasMods (gc.cont.fcn));
2226     }
2227   else
2228     {
2229       return FALSE;
2230     }
2231 }
2232
2233 void
2234 context_exitAllClauses (void)
2235 {  
2236   while (!clauseStack_isEmpty (gc.clauses))
2237     {
2238       clause el = clauseStack_top (gc.clauses);
2239       gc.inclause = el;
2240
2241       if (clause_isNone (el))
2242         {
2243           usymtab_quietExitScope (g_currentloc);
2244           clauseStack_pop (gc.clauses);
2245         }
2246       else
2247         {
2248           context_exitClausePlain ();
2249         }
2250     }
2251
2252   clauseStack_clear (gc.clauses);  
2253   gc.inclause = NOCLAUSE;
2254 }
2255
2256 void
2257 context_exitAllClausesQuiet (void)
2258 {  
2259   while (!clauseStack_isEmpty (gc.clauses))
2260     {
2261       clause el = clauseStack_top (gc.clauses);
2262       gc.inclause = el;
2263
2264       usymtab_quietExitScope (g_currentloc);
2265       clauseStack_pop (gc.clauses);
2266     }
2267
2268   clauseStack_clear (gc.clauses);  
2269   gc.inclause = NOCLAUSE;
2270 }
2271
2272 static
2273 void context_exitClauseSimp (void)
2274 {
2275   
2276   context_setJustPopped ();
2277   clauseStack_pop (gc.clauses);
2278   gc.inclause = topClause (gc.clauses);
2279 }
2280
2281 static
2282 void context_exitCaseClause (void)
2283 {
2284   context_setJustPopped ();
2285   usymtab_popCaseBranch ();
2286   clauseStack_pop (gc.clauses);
2287   gc.inclause = topClause (gc.clauses);
2288 }
2289
2290 static
2291 void context_exitClauseAux (exprNode pred, exprNode tbranch)
2292 {
2293   context_setJustPopped ();
2294   /*@i32 was makeAlt */
2295   usymtab_popTrueBranch (pred, tbranch, gc.inclause);
2296   clauseStack_pop (gc.clauses);
2297   gc.inclause = topClause (gc.clauses);
2298 }
2299
2300 void context_exitTrueClause (exprNode pred, exprNode tbranch)
2301 {
2302   DPRINTF (("Exit true clause: %s", exprNode_unparse (tbranch)));
2303
2304   if (gc.inclause != TRUECLAUSE)
2305     {
2306       llparseerror (cstring_makeLiteral
2307                     ("Likely parse error.  Conditional clauses are inconsistent."));
2308       return;
2309     }
2310   
2311   context_setJustPopped ();  
2312   usymtab_popTrueBranch (pred, tbranch, TRUECLAUSE);
2313   clauseStack_pop (gc.clauses);
2314   gc.inclause = topClause (gc.clauses);  
2315 }
2316
2317 void context_exitIterClause (exprNode body)
2318 {
2319   llassert (gc.inclause == ITERCLAUSE);
2320
2321   context_setJustPopped ();
2322
2323   if (context_getFlag (FLG_ITERLOOPEXEC))
2324     {
2325       usymtab_popTrueExecBranch (exprNode_undefined, body, ITERCLAUSE);
2326     }
2327   else
2328     {
2329       usymtab_popTrueBranch (exprNode_undefined, body, ITERCLAUSE);
2330     }
2331
2332   clauseStack_pop (gc.clauses);
2333   gc.inclause = topClause (gc.clauses);
2334 }
2335
2336 static void context_popCase (void) {
2337   /*
2338   ** If we are exiting an outer clause, sometimes still in a switch case.
2339   **
2340   ** e.g.: 
2341   **
2342   ** switch(a)
2343   ** {
2344   **   case 1:
2345   **     while (c>3)
2346   **       {
2347   **         case 3: ++c;
2348   **       }
2349   ** }     
2350   */
2351
2352   DPRINTF (("Popping case clause: %s",
2353             clauseStack_unparse (gc.clauses)));
2354   
2355   if (gc.inclause == CASECLAUSE) {
2356     context_exitCaseClause ();
2357   }
2358 }
2359
2360 void context_exitWhileClause (exprNode pred, exprNode body)
2361 {
2362   guardSet invGuards = guardSet_invert (exprNode_getGuards (pred));
2363
2364   context_popCase (); 
2365
2366   if (gc.inclause != WHILECLAUSE) {
2367     DPRINTF (("Clause: %s / %s", clause_unparse (gc.inclause),
2368               clauseStack_unparse (gc.clauses)));
2369   }
2370
2371   llassert (gc.inclause == WHILECLAUSE);
2372
2373   context_setJustPopped ();
2374
2375   
2376   /*
2377   ** predicate must be false after while loop (unless there are breaks)
2378   */
2379
2380   if (context_getFlag (FLG_WHILELOOPEXEC))
2381     {
2382       usymtab_popTrueExecBranch (pred, body, WHILECLAUSE);
2383     }
2384   else
2385     {
2386       usymtab_popTrueBranch (pred, body, WHILECLAUSE);
2387     }
2388
2389   
2390   usymtab_addGuards (invGuards);
2391   guardSet_free (invGuards);
2392
2393   clauseStack_pop (gc.clauses);
2394   gc.inclause = topClause (gc.clauses);  
2395 }
2396
2397 void context_exitDoWhileClause (exprNode pred)
2398 {
2399   guardSet invGuards = guardSet_invert (exprNode_getGuards (pred));
2400
2401   if (gc.inclause == CASECLAUSE) {
2402     /* handle Duff's device */
2403     clauseStack_pop (gc.clauses);
2404     gc.inclause = topClause (gc.clauses);
2405   }
2406
2407   llassert (gc.inclause == DOWHILECLAUSE);
2408
2409   context_setJustPopped ();
2410
2411     
2412   usymtab_addGuards (invGuards);
2413   guardSet_free (invGuards);
2414
2415   clauseStack_pop (gc.clauses);
2416   gc.inclause = topClause (gc.clauses);  
2417 }
2418
2419 void context_exitForClause (exprNode forPred, exprNode body)
2420 {
2421   guardSet invGuards = guardSet_invert (exprNode_getForGuards (forPred));
2422
2423   llassert (gc.inclause == FORCLAUSE);
2424   context_setJustPopped ();
2425
2426   DPRINTF (("Exit for: %s / %s", exprNode_unparse (forPred), exprNode_unparse (body)));
2427
2428   /*
2429   ** Predicate must be false after for loop (unless there are breaks)
2430   */
2431
2432   if (context_getFlag (FLG_FORLOOPEXEC))
2433     {
2434       DPRINTF (("Here: for loop exec"));
2435       usymtab_popTrueExecBranch (forPred, body, FORCLAUSE);
2436     }
2437   else
2438     {
2439       if (context_getFlag (FLG_OBVIOUSLOOPEXEC)
2440           && exprNode_loopMustExec (forPred))
2441         {
2442           DPRINTF (("Here: loop must exec"));
2443           usymtab_popTrueExecBranch (forPred, body, FORCLAUSE);
2444         }
2445       else
2446         {
2447           DPRINTF (("Pop true branch:"));
2448           usymtab_popTrueBranch (forPred, body, FORCLAUSE);
2449         }
2450     }
2451
2452   usymtab_addGuards (invGuards);
2453   guardSet_free (invGuards);
2454   clauseStack_pop (gc.clauses);
2455   gc.inclause = topClause (gc.clauses);
2456 }
2457
2458 static void context_exitClausePlain (void)
2459 {
2460   llassert (gc.inclause != NOCLAUSE);
2461   
2462   if (gc.inclause == FALSECLAUSE)
2463     {
2464       context_exitClause (exprNode_undefined, exprNode_undefined, exprNode_undefined);
2465     }
2466   else
2467     {
2468       context_exitClauseAux (exprNode_undefined, exprNode_undefined);
2469     }
2470 }
2471
2472 void context_exitClause (exprNode pred, exprNode tbranch, exprNode fbranch)
2473 {
2474   context_setJustPopped ();
2475   
2476   if (gc.inclause == FALSECLAUSE)
2477     {
2478       usymtab_popBranches (pred, tbranch, fbranch, FALSE, FALSECLAUSE);
2479       
2480       llassert (clauseStack_top (gc.clauses) == FALSECLAUSE);
2481
2482       clauseStack_pop (gc.clauses);
2483       gc.inclause = topClause (gc.clauses);
2484     }
2485   else
2486     {
2487       context_exitTrueClause (pred, tbranch);
2488     }
2489 }
2490
2491 void
2492 context_returnFunction (void)
2493 {
2494   usymtab_checkFinalScope (TRUE);
2495 }
2496
2497 void
2498 context_exitFunction (void)
2499 {    
2500   DPRINTF (("Exit function: %s", context_unparse ()));
2501
2502   if (!context_inFunction () && !context_inMacroConstant () 
2503       && !context_inUnknownMacro () 
2504       && !context_inIterDef () && !context_inIterEnd ())
2505     {
2506       /*
2507       ** not a bug because of parse errors
2508       */
2509
2510       BADBRANCH;
2511     }
2512   else
2513     {
2514       if (context_inMacro () && usymtab_inFunctionScope ())
2515         {
2516           usymtab_exitScope (exprNode_undefined);
2517         }
2518       
2519       if (uentry_hasGlobs (gc.cont.fcn))
2520         {
2521           exprChecks_checkUsedGlobs (gc.globs, gc.globs_used);
2522         }
2523       
2524             
2525       if (uentry_hasMods (gc.cont.fcn))
2526         {
2527           if (context_getFlag (FLG_MUSTMOD))
2528             {
2529               exprNode_checkAllMods (gc.mods, gc.cont.fcn);
2530             }
2531         }
2532
2533       DPRINTF (("Exit function: %s", uentry_unparse (gc.cont.fcn)));
2534
2535       /*
2536       ** clear file static modifies
2537       */
2538       
2539       /* do this first to get unused error messages */
2540
2541       usymtab_exitScope (exprNode_undefined);
2542       sRef_exitFunctionScope ();
2543       
2544       gc.showfunction = FALSE;
2545       gc.kind = CX_GLOBAL;
2546       gc.cont.glob = TRUE;
2547       gc.acct = gc.facct; 
2548       gc.globs = globSet_new ();
2549       globSet_clear (gc.globs_used);
2550       gc.mods = sRefSet_new ();
2551     }
2552
2553   llassert (clauseStack_isEmpty (gc.clauses));
2554   llassert (gc.inclause == NOCLAUSE);
2555   DPRINTF (("After exit function: %s", context_unparse ()));
2556 }
2557
2558 void
2559 context_quietExitFunction (void)
2560 {
2561   while (gc.kind == CX_INNER)
2562     { 
2563       context_exitInnerPlain ();
2564     }
2565
2566   if (!context_inFunction () && !context_inMacroConstant () && !context_inUnknownMacro () 
2567       && !context_inIterDef () && !context_inIterEnd ())
2568     {
2569     }
2570   else
2571     {
2572       usymtab_quietExitScope (g_currentloc);
2573
2574       gc.showfunction = FALSE;
2575       gc.kind = CX_GLOBAL;
2576       gc.cont.glob = TRUE;
2577       gc.acct = gc.facct; 
2578       gc.globs = globSet_new ();
2579       globSet_clear (gc.globs_used);
2580       gc.mods = sRefSet_new ();
2581
2582       sRef_exitFunctionScope ();
2583     }
2584 }
2585
2586 /*@observer@*/ uentryList
2587 context_getParams (void)
2588 {
2589   if (context_inFunctionLike ())
2590     {
2591       return (uentry_getParams (gc.cont.fcn));
2592     }
2593   else
2594     {
2595       llcontbug (message ("context_getParams: not in function: %q", context_unparse ()));
2596       return uentryList_undefined;
2597     }
2598 }
2599
2600 /*@observer@*/ globSet
2601 context_getUsedGlobs (void)
2602 {
2603   llassert (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN 
2604             || gc.kind == CX_UNKNOWNMACRO || gc.kind == CX_ITERDEF);
2605
2606   return (gc.globs_used);
2607 }
2608
2609 cstring
2610 context_moduleName ()
2611 {
2612   return (fileloc_getBase (g_currentloc));
2613 }
2614
2615 /*@observer@*/ globSet
2616 context_getGlobs (void)
2617 {
2618   llassert (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN 
2619             || gc.kind == CX_UNKNOWNMACRO || gc.kind == CX_ITERDEF);
2620
2621   return (gc.globs);
2622 }
2623
2624 void
2625 context_addBoolAccess (void)
2626 {
2627   cstring bname = context_getString (FLG_BOOLTYPE);
2628   typeIdSet boolt = typeIdSet_single (usymtab_getTypeId (bname));
2629   
2630   addModuleAccess (cstring_copy (bname), boolt);
2631
2632   /* for sys/types (perhaps, this is bogus!) */ 
2633   addModuleAccess (cstring_makeLiteral ("types"), boolt); 
2634 }
2635
2636 # if 0
2637 bool
2638 context_canAccessBool (void)
2639 {
2640   return TRUE;
2641 }
2642 # endif
2643
2644 /*
2645   static typeId boolType = typeId_invalid;
2646
2647   if (typeId_isInvalid (boolType))
2648     { 
2649       boolType = usymtab_getTypeId (context_getBoolName ());
2650     }
2651
2652   if (typeId_isInvalid (boolType)) {
2653     return FALSE;
2654   } else {
2655     return (typeIdSet_member (gc.acct, boolType));
2656   }
2657 }
2658 */
2659
2660 /* evs 2000-07-25: old version - replaced */
2661
2662 ctype
2663 context_boolImplementationType () {
2664   /* For now, this is bogus! */
2665   return ctype_int;
2666 }
2667
2668 bool
2669 context_canAccessBool (void)
2670 {
2671   static typeId boolType = typeId_invalid;
2672
2673   if (typeId_isInvalid (boolType))
2674     { 
2675       boolType = usymtab_getTypeId (context_getBoolName ());
2676     }
2677
2678   if (!typeId_isInvalid (boolType))
2679     { 
2680       return context_hasAccess (boolType);
2681     }
2682   else 
2683     {
2684       ;
2685     }
2686
2687   return FALSE; 
2688 }
2689
2690 void
2691 context_setMessageAnnote (/*@only@*/ cstring s)
2692 {
2693   llassert (cstring_isUndefined (gc.msgAnnote));
2694     gc.msgAnnote = s;
2695 }
2696
2697 bool
2698 context_hasMessageAnnote (void)
2699 {
2700   return (cstring_isDefined (gc.msgAnnote));
2701 }
2702
2703 void
2704 context_clearMessageAnnote (void)
2705 {
2706   if (cstring_isDefined (gc.msgAnnote))
2707     {
2708       cstring_free (gc.msgAnnote);
2709       gc.msgAnnote = cstring_undefined;
2710     }
2711 }
2712
2713 /*@only@*/ cstring
2714 context_getMessageAnnote (void)
2715 {
2716   cstring st = gc.msgAnnote;
2717
2718     gc.msgAnnote = cstring_undefined;
2719   return st;
2720 }
2721
2722 void
2723 context_setAliasAnnote (/*@observer@*/ sRef s, /*@observer@*/ sRef t)
2724 {
2725     llassert (sRef_isInvalid (gc.aliasAnnote));
2726   llassert (!sRef_sameName (s, t));
2727   gc.aliasAnnote = s;
2728   gc.aliasAnnoteAls = t;
2729 }
2730
2731 bool
2732 context_hasAliasAnnote (void)
2733 {
2734   return (sRef_isValid (gc.aliasAnnote));
2735 }
2736
2737 void
2738 context_clearAliasAnnote (void)
2739 {
2740   gc.aliasAnnote = sRef_undefined;
2741 }
2742
2743 cstring
2744 context_getAliasAnnote (void)
2745 {
2746   sRef ret = gc.aliasAnnote;
2747   sRef als = gc.aliasAnnoteAls;
2748
2749   llassert (sRef_isValid (ret) && sRef_isValid (als));
2750
2751   gc.aliasAnnote = sRef_undefined;
2752   return (message ("%q aliases %q", sRef_unparse (als), sRef_unparse (ret)));
2753 }
2754
2755 void
2756 context_recordFileModifies (sRefSet mods)
2757 {
2758   gc.modrecs = sRefSetList_add (gc.modrecs, mods);
2759 }
2760
2761 void
2762 context_recordFileGlobals (globSet mods)
2763 {
2764   DPRINTF (("Recording file globals: %s", globSet_unparse (mods)));
2765   /*@access globSet@*/ context_recordFileModifies (mods); /*@noaccess globSet@*/
2766 }
2767
2768 void
2769 context_setCommentMarkerChar (char c)
2770 {
2771   llassert (c != '\0');
2772
2773   context_setValue (FLG_COMMENTCHAR, (int) c);
2774 }
2775
2776 char
2777 context_getCommentMarkerChar (void)
2778 {
2779   return ((char) context_getValue (FLG_COMMENTCHAR));
2780 }
2781
2782 static void
2783 context_setValue (flagcode flag, int val)
2784 {
2785   int index = flagcode_valueIndex (flag);
2786
2787   llassert (index >= 0 && index <= NUMVALUEFLAGS);
2788
2789   switch (flag)
2790     {
2791     case FLG_LINELEN:
2792       if (val <= 0)
2793         {
2794           
2795           llerror_flagWarning (message ("Value for %s must be a positive "
2796                                         "number (given %d)",
2797                                         flagcode_unparse (flag), val));
2798           return;
2799         }
2800       if (flag == FLG_LINELEN && val < MINLINELEN)
2801         {
2802           llerror_flagWarning (message ("Value for %s must be at least %d (given %d)",
2803                                         flagcode_unparse (flag), 
2804                                         MINLINELEN, val));
2805           val = MINLINELEN;
2806         }
2807       break;
2808
2809     case FLG_INCLUDENEST:
2810     case FLG_CONTROLNESTDEPTH:
2811     case FLG_STRINGLITERALLEN:
2812     case FLG_NUMSTRUCTFIELDS:
2813     case FLG_NUMENUMMEMBERS:      
2814     case FLG_INDENTSPACES:
2815       if (val < 0)
2816         {
2817           llerror_flagWarning (message ("Value for %s must be a non-negative "
2818                                         "number (given %d)",
2819                                         flagcode_unparse (flag), val));
2820           return;
2821         }
2822
2823       break;
2824     default:
2825       break;
2826     }
2827
2828   DPRINTF (("Set value [%s] %d = %d", flagcode_unparse (flag), index, val));
2829   gc.values[index] = val;
2830 }
2831
2832 void
2833 context_setValueAndFlag (flagcode flag, int val)
2834 {
2835   gc.flags[flag] = TRUE;
2836   context_setValue (flag, val);
2837 }
2838
2839 int
2840 context_getValue (flagcode flag)
2841 {
2842   int index = flagcode_valueIndex (flag);
2843
2844   llassert (index >= 0 && index <= NUMVALUEFLAGS);
2845   DPRINTF (("Get value [%s] %d = %d", flagcode_unparse (flag), index, gc.values[index]));
2846   return (gc.values[index]);
2847 }
2848
2849 int
2850 context_getCounter (flagcode flag)
2851 {
2852   int index = flagcode_valueIndex (flag);
2853
2854   llassert (index >= 0 && index <= NUMVALUEFLAGS);
2855   return (gc.counters[index]);
2856 }
2857
2858 void
2859 context_incCounter (flagcode flag)
2860 {
2861   int index = flagcode_valueIndex (flag);
2862
2863   llassert (index >= 0 && index <= NUMVALUEFLAGS);
2864   /* check limit */
2865   gc.counters[index]++;
2866 }
2867
2868 void
2869 context_decCounter (flagcode flag)
2870 {
2871   int index = flagcode_valueIndex (flag);
2872
2873   llassert (index >= 0 && index <= NUMVALUEFLAGS);
2874   gc.counters[index]--;
2875 }
2876
2877 bool context_showFunction (void)
2878 {
2879   return (gc.showfunction);
2880 }
2881
2882 void
2883 context_setString (flagcode flag, cstring val)
2884 {
2885   int index = flagcode_stringIndex (flag);
2886
2887   llassert (index >= 0 && index <= NUMSTRINGFLAGS);
2888
2889   DPRINTF (("set string: %s", flagcode_unparse (flag)));
2890
2891   switch (flag)
2892     {
2893       /*
2894     case FLG_BOOLTRUE:
2895       usymtab_supGlobalEntry 
2896         (uentry_makeConstantValue (val, ctype_bool, 
2897                                    fileloc_getBuiltin (), TRUE, 
2898                                    multiVal_makeInt (1)));
2899       break;
2900     case FLG_BOOLFALSE:
2901       usymtab_supGlobalEntry 
2902         (uentry_makeConstantValue (val, ctype_bool, 
2903                                    fileloc_getBuiltin (), FALSE, 
2904                                    multiVal_makeInt (0)));
2905       break;
2906       */
2907     case FLG_MESSAGESTREAM:
2908     case FLG_WARNINGSTREAM:
2909     case FLG_ERRORSTREAM:
2910       {
2911         if (cstring_isDefined (val))
2912           {
2913             FILE *fstream;
2914
2915             if (osd_fileExists (val))
2916               {
2917                 if (context_getFlag (FLG_STREAMOVERWRITE))
2918                   {
2919                     llfatalerror (message 
2920                                   ("Output stream file %s would overwrite existing file. "
2921                                    "Use -streamoverwrite if you want to allow this.", 
2922                                    val));
2923                   }
2924               }
2925             
2926             fstream = fopen (cstring_toCharsSafe (val), "w");
2927
2928             if (fstream == NULL)
2929               {
2930                 llfatalerror (message ("Unable to open output stream file %s for writing", 
2931                                        val));
2932               }
2933
2934             /*
2935             ** This ensures fstream will be closed on exit.
2936             */
2937
2938             fileTable_addStreamFile (gc.ftab, fstream, cstring_copy (val));
2939             
2940             switch (flag)
2941               {
2942               case FLG_MESSAGESTREAM:
2943                 g_messagestream = fstream; 
2944                 /*@innerbreak@*/ break;
2945               case FLG_WARNINGSTREAM:
2946                 g_warningstream = fstream;
2947                 /*@innerbreak@*/ break;
2948               case FLG_ERRORSTREAM:
2949                 g_errorstream = fstream; 
2950                 /*@innerbreak@*/ break;
2951                 BADDEFAULT;
2952               }
2953             /*@-statetransfer@*/
2954           } /*@=statetransfer@*/ /* fstream not closed, but will be on exit */
2955         break;
2956       }
2957     case FLG_SYSTEMDIRS:
2958       {
2959         llassert (cstring_isDefined (val));
2960         
2961         if (cstring_firstChar (val) == '\"')
2962           {
2963             cstring oval = val;
2964             cstring tval = cstring_copy (cstring_suffix (val, 1));
2965             
2966             if (cstring_lastChar (tval) != '\"')
2967               {
2968                 int n = cstring_length (tval) - 1;
2969                 
2970                 while (isspace ((int) cstring_getChar (tval, size_fromInt (n))))
2971                   {
2972                     n--;
2973                   }
2974                 
2975                 if (cstring_getChar (tval, size_fromInt (n)) != '\"')
2976                   {
2977                     llerror_flagWarning 
2978                       (message ("Setting -systemdirs to string with unmatching quotes: %s", val));
2979                   }
2980                 else
2981                   {
2982                     cstring otval = tval;
2983                     tval = cstring_prefix (tval, size_fromInt (n));
2984                     cstring_free (otval);
2985                   }
2986               }
2987             
2988             val = cstring_copy (cstring_clip (tval, cstring_length (tval) - 1));
2989             DPRINTF (("val = %s", val));
2990             cstring_free (tval);
2991             cstring_free (oval);
2992           }
2993         
2994         break;
2995       }
2996     case FLG_TMPDIR:
2997       {
2998         llassert (cstring_isDefined (val));
2999         
3000         if (cstring_length (val) == 0)
3001           {
3002             cstring_free (val);
3003             val = message (".%s", cstring_makeLiteralTemp (CONNECTSTR));
3004           }
3005         else if (cstring_lastChar (val) != CONNECTCHAR)
3006           {
3007             val = cstring_appendChar (val, CONNECTCHAR);
3008           }
3009         else
3010           {
3011             ;
3012           }
3013         break;
3014       }
3015     default:
3016       {
3017         ; /* Okay not handle everything in this switch */
3018       }
3019   /*@i523@*/ } /* evans 2002-03-24: splintme reports a spurious (I think) warning here...need to look into it */
3020   
3021   if (cstring_length (val) >= 1
3022       && cstring_firstChar (val) == '\"')
3023     {
3024       llerror_flagWarning (message
3025                            ("Setting %s to string beginning with \".  You probably "
3026                             "don't meant to have the \"'s.",
3027                             flagcode_unparse (flag)));
3028     }
3029   
3030   gc.strings[index] = val;
3031 }
3032
3033 static /*@exposed@*/ cstring
3034 context_exposeString (flagcode flag)
3035 {
3036   int index = flagcode_stringIndex (flag);
3037
3038   llassert (index >= 0 && index <= NUMSTRINGFLAGS);
3039   return (gc.strings[index]);
3040 }
3041
3042 cstring
3043 context_getString (flagcode flag)
3044 {
3045   return (context_exposeString (flag));
3046 }
3047
3048 void
3049 context_resetErrors (void)
3050 {
3051   gc.numerrors = 0;
3052 }
3053
3054 void context_initMod (void)
3055    /*@globals undef gc; @*/
3056 {
3057   gc.kind = CX_GLOBAL;
3058
3059   gc.savekind = CX_ERROR;
3060   gc.savecont.glob = FALSE;
3061
3062   gc.instandardlib = FALSE;
3063   gc.numerrors = 0;
3064   gc.neednl = FALSE;
3065   gc.linesprocessed = 0;
3066   gc.speclinesprocessed = 0;
3067   gc.insuppressregion = FALSE;
3068   gc.macroMissingParams = FALSE;
3069   gc.preprocessing = FALSE;
3070   gc.incommandline = FALSE;
3071   gc.mc = macrocache_create ();
3072   gc.nmods = 0;
3073   gc.maxmods = DEFAULTMAXMODS;
3074   gc.moduleaccess = (maccesst *) dmalloc (sizeof (*gc.moduleaccess) * (gc.maxmods));
3075   
3076   gc.library = FLG_ANSILIB;
3077
3078   gc.locstack = filelocStack_new ();
3079   gc.modrecs = sRefSetList_undefined;
3080   gc.anyExports = FALSE;
3081
3082   gc.ftab = fileTable_create ();
3083   gc.msgLog = messageLog_new ();
3084   gc.inimport = FALSE;
3085   gc.inDerivedFile = FALSE;
3086   gc.inheader = FALSE;
3087   gc.markers = flagMarkerList_new ();
3088   gc.cont.glob = TRUE;
3089   gc.showfunction = FALSE;
3090   gc.msgAnnote = cstring_undefined;
3091   gc.aliasAnnote = sRef_undefined;
3092   gc.aliasAnnoteAls = sRef_undefined;
3093   gc.boolType = ctype_bool;
3094   gc.mods = sRefSet_new ();
3095
3096   gc.saveloc = fileloc_undefined;
3097
3098   gc.inmacrocache = FALSE;
3099   gc.inclause = NOCLAUSE;
3100   gc.clauses = clauseStack_new ();
3101   gc.globs = globSet_new ();
3102   gc.nacct = typeIdSet_emptySet ();
3103   gc.acct = typeIdSet_emptySet ();
3104   gc.facct = typeIdSet_emptySet ();
3105   gc.savedFlags = FALSE;
3106   gc.pushloc = fileloc_undefined;
3107   gc.protectVars = FALSE;
3108   gc.justpopped = FALSE;
3109   gc.isNullGuarded = NO;
3110   gc.globs_used = globSet_undefined;
3111   
3112   allFlagCodes (code)
3113     {
3114       gc.setGlobally[code] = FALSE;
3115       gc.setLocally[code] = FALSE;
3116     } 
3117   end_allFlagCodes ;
3118   
3119   usymtab_initMod ();
3120   context_resetAllFlags ();
3121
3122   assertSet (gc.flags); /* Can't use global in defines */
3123   assertSet (gc.saveflags);
3124   assertSet (gc.values);
3125   assertSet (gc.strings);
3126   
3127   conext_resetAllCounters ();
3128   assertSet (gc.counters);
3129
3130   context_setMode (DEFAULT_MODE);
3131
3132   gc.stateTable = metaStateTable_create ();
3133   gc.annotTable = annotationTable_create ();
3134
3135   gc.inFunctionHeader = FALSE;
3136
3137   DPRINTF (("Annotations: \n%s",
3138             cstring_toCharsSafe (annotationTable_unparse (gc.annotTable))));
3139   DPRINTF (("State: \n%s",
3140             cstring_toCharsSafe (metaStateTable_unparse (gc.stateTable))));
3141
3142 }
3143
3144 ctype
3145 context_typeofZero (void)
3146 {
3147   ctype ct = ctype_int;
3148
3149   if (context_getFlag (FLG_ZEROPTR))
3150     {
3151       ct = ctype_makeConj (ct, ctype_voidPointer);
3152     }
3153   
3154   if (context_getFlag (FLG_ZEROBOOL)) {
3155     ct = ctype_makeConj (ct, ctype_bool); 
3156   }
3157
3158   return ct;
3159 }
3160
3161 ctype
3162 context_typeofOne (void)
3163 {
3164   ctype ct = ctype_int;
3165
3166   /* 1 is on longer a bool (was before 2.4)
3167      if (!context_getFlag (FLG_ABSTRACTBOOL))
3168      {
3169      ct = ctype_makeConj (ct, ctype_bool);
3170      }
3171      */
3172
3173   return (ct);
3174 }
3175
3176 /*@only@*/ cstring
3177 context_unparse (void)
3178 {
3179   cstring s;
3180
3181   switch (gc.kind)
3182     {
3183     case CX_LCL:
3184       s = message ("LCL File: %q", fileloc_unparse (g_currentloc));
3185       break;
3186     case CX_LCLLIB:
3187       s = message ("LCL Lib File: %q", fileloc_unparse (g_currentloc));
3188       break;
3189     case CX_GLOBAL:
3190       s = message ("Global Context:%q", fileloc_unparse (g_currentloc));
3191       break;
3192     case CX_INNER:
3193       s = message ("Inner Context [%d] : %q", 
3194                    gc.cont.cdepth,
3195                    fileloc_unparse (g_currentloc));
3196       break;
3197     case CX_FUNCTION:
3198       s = message ("Function %q :%q \n\taccess %q\n\tmodifies %q",
3199                    uentry_unparse (gc.cont.fcn),
3200                    fileloc_unparse (g_currentloc),
3201                    typeIdSet_unparse (gc.acct),
3202                    sRefSet_unparse (gc.mods));
3203       break;
3204     case CX_MACROFCN:
3205       s = message ("Function Macro %q", uentry_unparse (gc.cont.fcn));
3206       break;
3207     case CX_UNKNOWNMACRO:
3208       s = message ("Forward Specified Macro %q", uentry_unparse (gc.cont.fcn));
3209       break;
3210     case CX_MACROCONST:
3211       s = message ("Constant Macro %q", uentry_unparse (gc.cont.fcn));
3212       break;
3213     case CX_ITERDEF:
3214       s = message ("Iter definition %q", uentry_unparse (gc.cont.fcn));
3215       break;
3216     case CX_ITEREND:
3217       s = message ("Iter end %q", uentry_unparse (gc.cont.fcn));
3218       break;
3219     case CX_FCNDECLARATION:
3220       s = message ("Function declaration %q", uentry_unparse (gc.cont.fcn));
3221       break;
3222     default:
3223       s = message ("Un-unparseable context: %d", (int) gc.kind);
3224       break;
3225     }
3226   
3227   s = message ("%q\naccess: %q", s, context_unparseAccess ());
3228   return (s);
3229 }
3230
3231 extern ctype
3232 context_currentFunctionType (void)
3233 {
3234   if (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN)
3235     {
3236             return (uentry_getType (gc.cont.fcn));
3237     }
3238   else if (gc.kind == CX_INNER)
3239     {
3240       llcontbuglit ("context_currentFunctionType: inner context");
3241       do { context_exitInnerPlain (); } while (gc.kind == CX_INNER);
3242       return (context_currentFunctionType ());
3243     }
3244   else
3245     {
3246       llcontbuglit ("context_currentFunctionType: not in function");
3247       return (ctype_undefined);
3248     }
3249 }
3250
3251 void
3252 context_enterInnerContext (void)
3253 {
3254   if (context_getFlag (FLG_GRAMMAR))
3255     {
3256       lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
3257     }
3258
3259   if (gc.kind == CX_GLOBAL)
3260     {
3261       gc.kind = CX_INNER;
3262       gc.cont.cdepth = 1;
3263     }
3264   else if (gc.kind == CX_INNER)
3265     {
3266       gc.cont.cdepth++;
3267     }
3268   else
3269     {
3270       ;
3271     }
3272
3273   usymtab_enterScope ();
3274   pushClause (NOCLAUSE);
3275 }
3276
3277 void
3278 context_exitInnerPlain (void) /*@modifies gc;@*/
3279 {
3280   context_exitInner (exprNode_undefined);
3281 }
3282
3283 void
3284 context_exitInner (exprNode exp)
3285 {
3286    if (context_getFlag (FLG_GRAMMAR))
3287     {
3288       lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
3289     }
3290  
3291   llassertprint (gc.inclause == NOCLAUSE || gc.inclause == CASECLAUSE,
3292                  ("inclause = %s", clause_nameTaken (gc.inclause)));
3293
3294   clauseStack_removeFirst (gc.clauses, NOCLAUSE);
3295   gc.inclause = topClause (gc.clauses);
3296
3297   if (gc.kind == CX_INNER)
3298     {
3299       if (--gc.cont.cdepth == 0)
3300         {
3301           gc.kind = CX_GLOBAL;
3302           gc.cont.glob = TRUE;
3303         }
3304     }
3305   else 
3306     {
3307       if (gc.kind == CX_GLOBAL)
3308         {
3309           llcontbuglit ("Attempt to exit global context");
3310           return;
3311         }
3312     }
3313
3314     usymtab_exitScope (exp);
3315 }
3316
3317
3318 void
3319 context_enterStructInnerContext (void)
3320 {
3321   if (context_getFlag (FLG_GRAMMAR))
3322     {
3323       lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
3324     }
3325
3326   if (gc.kind == CX_GLOBAL)
3327     {
3328       gc.kind = CX_INNER;
3329       gc.cont.cdepth = 1;
3330     }
3331   else if (gc.kind == CX_INNER)
3332     {
3333       gc.cont.cdepth++;
3334     }
3335   else
3336     {
3337       ;
3338     }
3339
3340   usymtab_enterScope ();
3341
3342   if (context_getFlag (FLG_GRAMMAR))
3343     {
3344       lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
3345     }
3346 }
3347
3348 void
3349 context_exitStructInnerContext (void)
3350 {
3351   if (context_getFlag (FLG_GRAMMAR))
3352     {
3353       lldiagmsg (message ("Exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
3354     }
3355
3356   if (gc.kind == CX_INNER)
3357     {
3358       if (gc.cont.cdepth <= 0)
3359         {
3360           llcontbuglit ("Attempt to exit inner context with no depth");
3361           gc.kind = CX_GLOBAL;
3362           gc.cont.glob = TRUE;
3363           gc.cont.cdepth = 0;
3364         }
3365       else {
3366         gc.cont.cdepth--;
3367
3368         if (gc.cont.cdepth == 0)
3369           {
3370             gc.kind = CX_GLOBAL;
3371             gc.cont.glob = TRUE;
3372           }
3373       }
3374     }
3375   else 
3376     {
3377       if (gc.kind == CX_GLOBAL)
3378         {
3379           llcontbuglit ("Attempt to exit global context");
3380           return;
3381         }
3382     }
3383
3384   usymtab_exitScope (exprNode_undefined);
3385
3386   if (context_getFlag (FLG_GRAMMAR))
3387     {
3388       lldiagmsg (message ("After exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
3389     }
3390 }
3391
3392 void
3393 context_exitInnerSafe (void)
3394 {
3395   if (context_getFlag (FLG_GRAMMAR))
3396     {
3397       lldiagmsg (message ("Exit inner safe: %q", context_unparse ()));
3398     }
3399
3400   if (gc.kind == CX_INNER)
3401     {
3402       if (--gc.cont.cdepth <= 0)
3403         {
3404           gc.cont.cdepth = 0;
3405         }
3406     }
3407   else if (gc.kind == CX_GLOBAL)
3408     {
3409       llcontbuglit ("Attempt to exit global context");
3410       return;
3411     }
3412   else
3413     {
3414       if (usymtab_inDeepScope ())
3415         {
3416           usymtab_exitScope (exprNode_undefined);
3417         }
3418     }
3419 }
3420
3421 static
3422 void setModuleAccess (void)
3423 {
3424   gc.facct = typeIdSet_emptySet ();
3425
3426   if (fileId_isValid (currentFile ()))
3427     {
3428       cstring baseName = fileloc_getBase (g_currentloc);
3429       
3430       if (context_getFlag (FLG_ACCESSFILE))
3431         {
3432           if (usymtab_existsType (baseName))
3433             {
3434               gc.facct = typeIdSet_insert (gc.facct, 
3435                                            usymtab_getTypeId (baseName));
3436             }
3437           else 
3438             {
3439               ;
3440             }
3441         }
3442       
3443       if (context_getFlag (FLG_ACCESSMODULE))
3444         {
3445           int i;
3446           bool hasaccess = FALSE;
3447           
3448           for (i = 0; i < gc.nmods; i++)
3449             {
3450               if (cstring_equal (baseName, gc.moduleaccess[i].file))
3451                 {
3452                   gc.facct = typeIdSet_union (gc.facct, gc.moduleaccess[i].daccess);
3453
3454                   hasaccess = TRUE;
3455                   break;
3456                 }
3457             }
3458         }
3459       
3460       gc.acct = gc.facct;
3461       gc.inheader = fileId_isHeader (currentFile ());
3462     }
3463   else
3464     {
3465       llcontbuglit ("Current file not defined\n");
3466       gc.facct = typeIdSet_emptySet ();
3467       gc.acct = gc.facct;
3468       gc.inheader = FALSE;
3469     }
3470   
3471   /* 17 Jan 1995: forgot to clear nacct */
3472   
3473   gc.nacct = typeIdSet_emptySet ();
3474 }
3475
3476 static void
3477 context_enterFileAux (void)
3478 {
3479   setModuleAccess ();
3480 }
3481
3482 void
3483 context_enterFile (void)
3484 {
3485   context_enterFileAux ();
3486   usymtab_enterFile ();
3487 }
3488
3489 void
3490 context_enterMacroFile (void)
3491 {
3492   context_enterFileAux ();
3493 }
3494
3495 bool 
3496 context_inFunction (void)
3497 {
3498   kcontext ck = gc.kind;
3499   
3500   return ((ck == CX_FUNCTION) || (ck == CX_MACROFCN) || (ck == CX_INNER));
3501 }
3502
3503 bool 
3504 context_inFunctionLike (void)
3505 {
3506   return (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN 
3507           || gc.kind == CX_FCNDECLARATION
3508           || gc.kind == CX_UNKNOWNMACRO || gc.kind == CX_ITERDEF);
3509 }
3510
3511 bool 
3512 context_inRealFunction (void)
3513 {
3514   kcontext ck = gc.kind;
3515   
3516   return ((ck == CX_FUNCTION) || (ck == CX_MACROFCN));
3517 }
3518   
3519 void
3520 context_processAllMacros (void)
3521 {
3522   usymtab_enterFile ();
3523
3524   gc.inmacrocache = TRUE; 
3525   macrocache_processUndefinedElements (gc.mc);
3526   cleanupMessages ();  
3527   usymtab_exitFile ();
3528
3529   gc.inmacrocache = FALSE;
3530   macrocache_finalize ();
3531 }
3532
3533 /*
3534 ** this happens once at the end of each C file
3535 **
3536 ** check each Macro that was defined in current file.c or current file.h
3537 **
3538 */
3539
3540 static void
3541 context_processMacros (void)
3542 {
3543   if (fileId_isValid (currentFile ()))
3544     {
3545       fileloc lastfl;
3546       cstring cbase = fileLib_removePathFree (fileLib_removeAnyExtension (fileTable_fileName (currentFile ())));
3547       
3548       gc.inmacrocache = TRUE;
3549
3550       DPRINTF (("Processing macros: %s", cbase));
3551       lastfl = macrocache_processFileElements (gc.mc, cbase);
3552       DPRINTF (("Processing macros: %s", fileloc_unparse (lastfl)));
3553
3554       cstring_free (cbase);
3555       
3556       if (fileloc_isDefined (lastfl))
3557         {
3558           g_currentloc = fileloc_update (g_currentloc, lastfl);
3559           cleanupMessages ();
3560         }
3561
3562       gc.inmacrocache = FALSE;
3563     }
3564 }
3565
3566 bool
3567 context_processingMacros (void)
3568 {
3569   return (gc.inmacrocache);
3570 }
3571
3572 void
3573 context_exitCFile (void)
3574 {
3575   if (gc.kind != CX_GLOBAL)
3576     {
3577       llfatalerrorLoc
3578         (cstring_makeLiteral ("File ended outside global scope"));
3579     }
3580
3581   if (gc.insuppressregion)
3582     {
3583      /* gack...don't reverse the order of these lines! ;-> */
3584       gc.insuppressregion = FALSE;
3585       llerrorlit (FLG_SYNTAX, 
3586                   "File ended in ignore errors region, "
3587                   "possible missing /*@end*/");
3588     }
3589
3590   /* fix up parse errors */
3591
3592   while (!usymtab_inFileScope ())
3593     {
3594       usymtab_quietExitScope (g_currentloc);
3595     }
3596
3597   /*
3598   ** Clear the file-specific modifies information.
3599   */
3600   
3601   sRefSetList_elements (gc.modrecs, mods)
3602     {
3603       sRefSet_clearStatics (mods);
3604     } end_sRefSetList_elements ;
3605   
3606   sRefSetList_clear (gc.modrecs);
3607   
3608   context_processMacros ();
3609   cleanupMessages (); 
3610   
3611   usymtab_exitFile ();
3612   
3613   gc.inDerivedFile = FALSE;
3614   filelocStack_clear (gc.locstack);
3615   
3616   gc.nacct = typeIdSet_emptySet (); /* empty noaccess */
3617   
3618   gc.cont.glob = TRUE;
3619   
3620   if (gc.savedFlags)
3621     {
3622       context_restoreFlagSettings ();
3623       gc.savedFlags = FALSE;
3624     }
3625   
3626   /*
3627     DPRINTF (("After exiting file: "));
3628     usymtab_printAll ();
3629   */
3630 }
3631
3632 void
3633 context_exitMacroCache (void)
3634 {
3635   if (gc.kind != CX_GLOBAL)
3636     {
3637       if (context_inMacro ()) 
3638         /* this is okay, file could end without newline in macro */
3639         {
3640           DPRINTF (("Still in macro: %s",
3641                     context_unparse ()));
3642           context_exitFunction ();
3643         }
3644       else
3645         {
3646           llcontbug (message ("context_exitMacroCache: outside global scope: %q", 
3647                               context_unparse ()));
3648           gc.kind = CX_GLOBAL; 
3649         }
3650     }
3651
3652   /*
3653   ** no longer valid here
3654   ** if (gc.insuppressregion)
3655   **   {
3656   **     gc.insuppressregion = FALSE;
3657   **     llerror ("File ended in ignore errors region, possible missing @");
3658   **   }
3659   */
3660
3661   gc.cont.glob = TRUE;
3662 }
3663
3664 void
3665 context_saveLocation (void)
3666 {
3667   /* was llassert (fileloc_isUndefined (gc.saveloc)) */
3668   fileloc_free (gc.saveloc);
3669   gc.saveloc = fileloc_copy (g_currentloc);
3670 }
3671
3672 fileloc
3673 context_getSaveLocation (void)
3674 {
3675   fileloc fl = gc.saveloc;
3676   gc.saveloc = fileloc_undefined;
3677   return fl;
3678 }
3679
3680 /*@observer@*/ cstring
3681 context_inFunctionName (void)
3682 {
3683   if (gc.kind == CX_FUNCTION
3684       || gc.kind == CX_MACROFCN || gc.kind == CX_UNKNOWNMACRO 
3685       || gc.kind == CX_MACROCONST 
3686       || gc.kind == CX_ITERDEF || gc.kind == CX_ITEREND)
3687     {
3688       return (uentry_rawName (gc.cont.fcn));
3689     }
3690   else
3691     {
3692       llcontbuglit ("context_inFunctionName: not in function");
3693       return (cstring_undefined);
3694     }
3695 }
3696
3697 void
3698 context_userSetFlag (flagcode f, bool b)
3699 {
3700   DPRINTF (("set flag: %s / %s", 
3701             flagcode_unparse (f),
3702             bool_unparse (context_getFlag (f))));
3703
3704   if (f == FLG_NEVERINCLUDE && b)
3705     {
3706       if (gc.flags[FLG_EXPORTHEADER])
3707         {
3708           llerror_flagWarning 
3709             (cstring_makeLiteral
3710              ("Setting +neverinclude after +exportheader.  "
3711               "Turning off exportheader, since headers are not checked "
3712               "when +neverinclude is used."));
3713
3714           gc.flags[FLG_EXPORTHEADER] = FALSE;
3715         }
3716     }
3717   else 
3718     {
3719       if (f == FLG_EXPORTHEADER && b)
3720         {
3721           if (gc.flags[FLG_NEVERINCLUDE])
3722             {
3723               llerror_flagWarning
3724                 (cstring_makeLiteral
3725                  ("Setting +exportheader after +neverinclude.  "
3726                   "Not setting exportheader, since headers are not checked "
3727                   "when +neverinclude is used."));
3728               gc.flags[FLG_EXPORTHEADER] = FALSE;
3729               return;
3730             }
3731         }
3732     }
3733   
3734   if (context_getFlag (FLG_WARNFLAGS) && f != FLG_NOF && f != FLG_OPTF)
3735     {
3736       bool lastsetting = context_getFlag (f);
3737       
3738       if (bool_equal (lastsetting, b)
3739           && !flagcode_isSpecialFlag (f) 
3740           && !flagcode_isIdemFlag (f)
3741           && !flagcode_hasArgument (f))
3742         {
3743           llerror_flagWarning 
3744             (message ("Setting %s%s redundant with current value", 
3745                       cstring_makeLiteralTemp (b ? "+" : "-"),
3746                       flagcode_unparse (f)));
3747         }
3748     }
3749
3750   if (flagcode_isWarnUseFlag (f) && b)
3751     {
3752       if (!context_getFlag (FLG_WARNUSE))
3753         {
3754           llerror_flagWarning
3755             (message ("Flag +%s is canceled by -warnuse",
3756                       flagcode_unparse (f)));
3757         }
3758     }
3759
3760
3761   if (flagcode_isLibraryFlag (f)) 
3762     {
3763       if (gc.library != FLG_ANSILIB
3764           && gc.library != f)
3765         {
3766           llerror_flagWarning 
3767             (message ("Selecting library %s after library %s was "
3768                       "selected (only one library may be used)",
3769                       flagcode_unparse (f),
3770                       flagcode_unparse (gc.library)));
3771         }
3772       
3773       if (f == FLG_UNIXLIB)
3774         {
3775           if (context_getFlag (FLG_WARNUNIXLIB))
3776             {
3777               llerror_flagWarning
3778                 (cstring_makeLiteral
3779                  ("Selecting unix library.  Unix library is "
3780                   "ad hoc addition to POSIX library.  Recommend "
3781                   "use +posixlib to select POSIX library instead. "
3782                   "Use -warnunixlib to suppress this message."));
3783             }
3784         }
3785       
3786       gc.library = f;
3787     }
3788   
3789   if (flagcode_isNameChecksFlag (f) && b && !context_maybeSet (FLG_NAMECHECKS))
3790     {
3791       llerror_flagWarning
3792         (message
3793          ("Setting +%s will not produce warnings with -namechecks. "
3794           "Must set +namechecks also.",
3795           flagcode_unparse (f)));
3796     }
3797   
3798   gc.setGlobally[f] = TRUE;
3799   context_setFlag (f, b, g_currentloc);
3800 }
3801
3802 void
3803 context_fileSetFlag (flagcode f, ynm set, fileloc loc)
3804 {
3805   if (!gc.savedFlags)
3806     {
3807       context_saveFlagSettings ();
3808     }
3809
3810   if (ynm_isOff (set))
3811     {
3812       context_setFlagAux (f, FALSE, TRUE, FALSE, loc);
3813     }
3814   else if (ynm_isOn (set))
3815     {
3816       context_setFlagAux (f, TRUE, TRUE, FALSE, loc);
3817       gc.setLocally[f] = TRUE;
3818     }
3819   else
3820     {
3821       context_restoreFlag (f, loc);
3822     }
3823 }
3824
3825 static void
3826 context_restoreFlag (flagcode f, fileloc loc)
3827 {
3828   if (!gc.savedFlags)
3829     {
3830       voptgenerror 
3831         (FLG_SYNTAX,
3832          message ("Attempt to restore flag %s when no file scope flags "
3833                   "have been set.",
3834                   flagcode_unparse (f)),
3835          loc);
3836     }
3837   else
3838     {
3839       context_addFlagMarker (f, MAYBE, loc);
3840       context_setFlagAux (f, gc.saveflags[f], FALSE, TRUE, loc);
3841     }
3842
3843   }
3844
3845 static void
3846 context_setFlag (flagcode f, bool b, fileloc loc)
3847 {
3848   context_setFlagAux (f, b, FALSE, FALSE, loc);
3849 }
3850
3851 void
3852 context_setFlagTemp (flagcode f, bool b)
3853 {
3854   DPRINTF (("Set flag temp: %s / %s", flagcode_unparse (f), bool_unparse (b)));
3855   gc.flags[f] = b;
3856 }
3857
3858 /*@notfunction@*/
3859 # define DOSET(ff,b) \
3860    do { if (inFile) { gc.setLocally[ff] = TRUE; \
3861                       context_addFlagMarker (ff, ynm_fromBool (b), loc); } \
3862         DPRINTF (("set flag: %s / %s", flagcode_unparse (ff), bool_unparse (b))); \
3863         gc.flags[ff] = b; } while (FALSE)
3864
3865 static void
3866 context_setFlagAux (flagcode f, bool b, bool inFile, 
3867                     /*@unused@*/ bool isRestore, fileloc loc)
3868 {
3869   DPRINTF (("Set flag: %s / %s", flagcode_unparse (f), bool_unparse (b)));
3870
3871   /*
3872   ** Removed test for special flags.
3873   */
3874
3875   if (flagcode_isIdemFlag (f))
3876     {
3877       DOSET (f, TRUE);
3878     }
3879   else
3880     {
3881       DOSET (f, b);
3882     }
3883
3884   if (f >= FLG_ITS4MOSTRISKY && f <= FLG_ITS4LOWRISK)
3885     {
3886       if (b) /* Turing higher level on, turns on all lower levels */
3887         {
3888           switch (f)
3889             {
3890             case FLG_ITS4MOSTRISKY:
3891               DOSET (FLG_ITS4VERYRISKY, b);
3892               /*@fallthrough@*/ 
3893             case FLG_ITS4VERYRISKY:
3894               DOSET (FLG_ITS4RISKY, b);
3895               /*@fallthrough@*/ 
3896             case FLG_ITS4RISKY:
3897               DOSET (FLG_ITS4MODERATERISK, b);
3898               /*@fallthrough@*/ 
3899             case FLG_ITS4MODERATERISK:
3900               DOSET (FLG_ITS4LOWRISK, b);
3901               /*@fallthrough@*/ 
3902             case FLG_ITS4LOWRISK:
3903               break;
3904               BADDEFAULT;
3905             }
3906         }
3907       else /* Turning level off, turns off all higher levels */
3908         {
3909           switch (f)
3910             {
3911             case FLG_ITS4LOWRISK:
3912               DOSET (FLG_ITS4MODERATERISK, b);
3913               /*@fallthrough@*/ 
3914             case FLG_ITS4MODERATERISK:
3915               DOSET (FLG_ITS4RISKY, b);
3916               /*@fallthrough@*/ 
3917             case FLG_ITS4RISKY:
3918               DOSET (FLG_ITS4VERYRISKY, b);
3919               /*@fallthrough@*/ 
3920             case FLG_ITS4VERYRISKY:
3921               DOSET (FLG_ITS4MOSTRISKY, b);
3922               /*@fallthrough@*/ 
3923             case FLG_ITS4MOSTRISKY:
3924               break;
3925               BADDEFAULT;
3926             }
3927         }
3928     }
3929   
3930   switch (f)
3931     {     
3932     case FLG_MESSAGESTREAMSTDOUT:
3933       g_messagestream = stdout;
3934       break;
3935     case FLG_MESSAGESTREAMSTDERR:
3936       g_messagestream = stderr;
3937       break;
3938     case FLG_WARNINGSTREAMSTDOUT:
3939       g_warningstream = stdout;
3940       break;
3941     case FLG_WARNINGSTREAMSTDERR:
3942       g_warningstream = stderr;
3943       break;
3944     case FLG_ERRORSTREAMSTDOUT:
3945       g_errorstream = stdout;
3946       break;
3947     case FLG_ERRORSTREAMSTDERR:
3948       g_errorstream = stderr;
3949       break;
3950     case FLG_ALLEMPTY:
3951       DOSET (FLG_ALLEMPTY, b);
3952       DOSET (FLG_IFEMPTY, b);
3953       DOSET (FLG_WHILEEMPTY, b);
3954       DOSET (FLG_FOREMPTY, b);
3955       break;
3956     case FLG_PREDBOOL:
3957       DOSET (FLG_PREDBOOL, b);
3958       DOSET (FLG_PREDBOOLINT, b);
3959       DOSET (FLG_PREDBOOLPTR, b);
3960       DOSET (FLG_PREDBOOLOTHERS, b);
3961       break;
3962     case FLG_GLOBALIAS:
3963       DOSET (FLG_CHECKSTRICTGLOBALIAS, b);
3964       DOSET (FLG_CHECKEDGLOBALIAS, b);
3965       DOSET (FLG_CHECKMODGLOBALIAS, b);
3966       DOSET (FLG_UNCHECKEDGLOBALIAS, b);
3967       break;
3968     case FLG_ALLBLOCK:
3969       DOSET (FLG_ALLBLOCK, b);
3970       DOSET (FLG_IFBLOCK, b);
3971       DOSET (FLG_WHILEBLOCK, b);
3972       DOSET (FLG_FORBLOCK, b);
3973       break;
3974     case FLG_GRAMMAR:
3975       if (b)
3976         {
3977           yydebug = 1;
3978           mtdebug = 1;
3979         }
3980       else
3981         {
3982           yydebug = 0;
3983           mtdebug = 0;
3984         }
3985       
3986       DOSET (FLG_GRAMMAR, b);
3987       break;
3988     case FLG_CODEIMPONLY:
3989       DOSET (FLG_CODEIMPONLY, b);
3990       DOSET (FLG_GLOBIMPONLY, b);
3991       DOSET (FLG_RETIMPONLY, b);
3992       DOSET (FLG_STRUCTIMPONLY, b);
3993       break;
3994     case FLG_SPECALLIMPONLY:
3995       DOSET (FLG_SPECALLIMPONLY, b);
3996       DOSET (FLG_SPECGLOBIMPONLY, b);
3997       DOSET (FLG_SPECRETIMPONLY, b);
3998       DOSET (FLG_SPECSTRUCTIMPONLY, b);
3999       break;
4000     case FLG_ALLIMPONLY:
4001       DOSET (FLG_ALLIMPONLY, b);
4002       DOSET (FLG_GLOBIMPONLY, b);
4003       DOSET (FLG_RETIMPONLY, b);
4004       DOSET (FLG_STRUCTIMPONLY, b);
4005       DOSET (FLG_SPECGLOBIMPONLY, b);
4006       DOSET (FLG_SPECRETIMPONLY, b);
4007       DOSET (FLG_SPECSTRUCTIMPONLY, b);
4008       break;
4009     case FLG_ANSI89LIMITS: 
4010       DOSET (FLG_ANSI89LIMITS, b);
4011       DOSET (FLG_CONTROLNESTDEPTH, b);
4012       DOSET (FLG_STRINGLITERALLEN, b);
4013       DOSET (FLG_INCLUDENEST, b);
4014       DOSET (FLG_NUMSTRUCTFIELDS, b);
4015       DOSET (FLG_NUMENUMMEMBERS, b);
4016       
4017       if (b)
4018         {
4019           context_setValue (FLG_CONTROLNESTDEPTH, ANSI89_CONTROLNESTDEPTH);
4020           context_setValue (FLG_STRINGLITERALLEN, ANSI89_STRINGLITERALLEN);
4021           context_setValue (FLG_INCLUDENEST, ANSI89_INCLUDENEST);
4022           context_setValue (FLG_NUMSTRUCTFIELDS, ANSI89_NUMSTRUCTFIELDS);
4023           context_setValue (FLG_NUMENUMMEMBERS, ANSI89_NUMENUMMEMBERS);
4024           context_setValue (FLG_EXTERNALNAMELEN, ANSI89_EXTERNALNAMELEN);
4025           context_setValue (FLG_INTERNALNAMELEN, ANSI89_INTERNALNAMELEN);
4026         }
4027       break;
4028     case FLG_ISO99LIMITS: 
4029       DOSET (FLG_ISO99LIMITS, b);
4030       DOSET (FLG_CONTROLNESTDEPTH, b);
4031       DOSET (FLG_STRINGLITERALLEN, b);
4032       DOSET (FLG_INCLUDENEST, b);
4033       DOSET (FLG_NUMSTRUCTFIELDS, b);
4034       DOSET (FLG_NUMENUMMEMBERS, b);
4035       
4036       if (b)
4037         {
4038           context_setValue (FLG_CONTROLNESTDEPTH, ISO99_CONTROLNESTDEPTH);
4039           context_setValue (FLG_STRINGLITERALLEN, ISO99_STRINGLITERALLEN);
4040           context_setValue (FLG_INCLUDENEST, ISO99_INCLUDENEST);
4041           context_setValue (FLG_NUMSTRUCTFIELDS, ISO99_NUMSTRUCTFIELDS);
4042           context_setValue (FLG_NUMENUMMEMBERS, ISO99_NUMENUMMEMBERS);
4043           context_setValue (FLG_EXTERNALNAMELEN, ISO99_EXTERNALNAMELEN);
4044           context_setValue (FLG_INTERNALNAMELEN, ISO99_INTERNALNAMELEN);
4045         }
4046       break;
4047     case FLG_EXTERNALNAMELEN:
4048       DOSET (FLG_DISTINCTEXTERNALNAMES, TRUE);
4049       DOSET (FLG_EXTERNALNAMELEN, TRUE);
4050       break;
4051     case FLG_INTERNALNAMELEN:
4052       DOSET (FLG_DISTINCTINTERNALNAMES, TRUE);
4053       DOSET (FLG_INTERNALNAMELEN, TRUE);
4054       break;
4055     case FLG_EXTERNALNAMECASEINSENSITIVE:
4056       DOSET (FLG_EXTERNALNAMECASEINSENSITIVE, b);
4057       
4058       if (b && !gc.flags[FLG_DISTINCTEXTERNALNAMES])
4059         {
4060           DOSET (FLG_DISTINCTEXTERNALNAMES, TRUE);
4061           context_setValue (FLG_EXTERNALNAMELEN, 0);
4062         }
4063       break;
4064     case FLG_INTERNALNAMECASEINSENSITIVE:
4065       DOSET (FLG_INTERNALNAMECASEINSENSITIVE, b);
4066       
4067       if (b && !gc.flags[FLG_DISTINCTINTERNALNAMES])
4068         {
4069           DOSET (FLG_DISTINCTINTERNALNAMES, TRUE);
4070           context_setValue (FLG_INTERNALNAMELEN, 0);
4071         }
4072       break;
4073     case FLG_INTERNALNAMELOOKALIKE:
4074       DOSET (FLG_INTERNALNAMELOOKALIKE, b);
4075       
4076       if (b && !gc.flags[FLG_DISTINCTINTERNALNAMES])
4077         {
4078           DOSET (FLG_DISTINCTINTERNALNAMES, TRUE);
4079           context_setValue (FLG_INTERNALNAMELEN, 0);
4080         }
4081       break;
4082     case FLG_MODUNSPEC:
4083       DOSET (FLG_MODNOMODS, b);
4084       DOSET (FLG_MODGLOBSUNSPEC, b);
4085       DOSET (FLG_MODSTRICTGLOBSUNSPEC, b);
4086       break;
4087     case FLG_EXPORTANY: 
4088       DOSET (FLG_EXPORTVAR, b);
4089       DOSET (FLG_EXPORTFCN, b);
4090       DOSET (FLG_EXPORTTYPE, b);
4091       DOSET (FLG_EXPORTMACRO, b);
4092       DOSET (FLG_EXPORTCONST, b);
4093       gc.anyExports = TRUE;
4094       break;
4095     case FLG_REPEXPOSE:
4096       DOSET (FLG_RETEXPOSE, b); 
4097       DOSET (FLG_ASSIGNEXPOSE, b); 
4098       DOSET (FLG_CASTEXPOSE, b); 
4099       break;
4100     case FLG_RETVAL:
4101       DOSET (FLG_RETVALBOOL, b);
4102       DOSET (FLG_RETVALINT, b);
4103       DOSET (FLG_RETVALOTHER, b);
4104       break;
4105     case FLG_PARTIAL:
4106       if (b)
4107         {
4108           DOSET (FLG_EXPORTLOCAL, FALSE);
4109           DOSET (FLG_DECLUNDEF, FALSE);
4110           DOSET (FLG_SPECUNDEF, FALSE);
4111           DOSET (FLG_TOPUNUSED, FALSE);
4112         }
4113       break;
4114     case FLG_DEEPBREAK:
4115       DOSET (FLG_LOOPLOOPBREAK, b);
4116       DOSET (FLG_LOOPSWITCHBREAK, b);
4117       DOSET (FLG_SWITCHLOOPBREAK, b);
4118       DOSET (FLG_SWITCHSWITCHBREAK, b);
4119       DOSET (FLG_LOOPLOOPCONTINUE, b);
4120       DOSET (FLG_DEEPBREAK, b);
4121       break;
4122     case FLG_LOOPEXEC:
4123       DOSET (FLG_FORLOOPEXEC, b);
4124       DOSET (FLG_WHILELOOPEXEC, b);
4125       DOSET (FLG_ITERLOOPEXEC, b);
4126       break;
4127     case FLG_ACCESSALL:
4128       DOSET (FLG_ACCESSMODULE, b);
4129       DOSET (FLG_ACCESSFILE, b);
4130       DOSET (FLG_ACCESSCZECH, b);
4131       break;
4132     case FLG_ALLMACROS:
4133       DOSET (FLG_ALLMACROS, b);
4134       DOSET (FLG_FCNMACROS, b);
4135       DOSET (FLG_CONSTMACROS, b);
4136       break;
4137     case FLG_BOUNDS:
4138       DOSET (FLG_BOUNDSREAD, b);
4139       DOSET (FLG_BOUNDSWRITE, b);
4140       break;
4141     case FLG_CZECH:
4142       if (b) { DOSET (FLG_ACCESSCZECH, b); }
4143       DOSET (FLG_CZECHFUNCTIONS, b);
4144       DOSET (FLG_CZECHVARS, b);
4145       DOSET (FLG_CZECHCONSTANTS, b);
4146       DOSET (FLG_CZECHTYPES, b);
4147       break;
4148     case FLG_SLOVAK:
4149       if (b) { DOSET (FLG_ACCESSSLOVAK, b); }
4150       DOSET (FLG_SLOVAKFUNCTIONS, b);
4151       DOSET (FLG_SLOVAKVARS, b);
4152       DOSET (FLG_SLOVAKCONSTANTS, b);
4153       DOSET (FLG_SLOVAKTYPES, b);
4154       break;
4155     case FLG_CZECHOSLOVAK:
4156       if (b) { DOSET (FLG_ACCESSCZECHOSLOVAK, b); }
4157       DOSET (FLG_CZECHOSLOVAKFUNCTIONS, b);
4158       DOSET (FLG_CZECHOSLOVAKVARS, b);
4159       DOSET (FLG_CZECHOSLOVAKCONSTANTS, b);
4160       DOSET (FLG_CZECHOSLOVAKTYPES, b);
4161       break;
4162     case FLG_NULL:
4163       DOSET (FLG_NULLSTATE, b);
4164       DOSET (FLG_NULLDEREF, b);
4165       DOSET (FLG_NULLASSIGN, b);
4166       DOSET (FLG_NULLPASS, b);
4167       DOSET (FLG_NULLRET, b);
4168       break;
4169     case FLG_MUSTFREE:
4170       DOSET (FLG_MUSTFREEONLY, b);
4171       DOSET (FLG_MUSTFREEFRESH, b);
4172       break;
4173     case FLG_MEMCHECKS:
4174       DOSET (FLG_NULLSTATE, b);
4175       DOSET (FLG_NULLDEREF, b);
4176       DOSET (FLG_NULLASSIGN, b);
4177       DOSET (FLG_NULLPASS, b);
4178       DOSET (FLG_NULLRET, b);
4179       DOSET (FLG_COMPDEF, b);
4180       DOSET (FLG_COMPMEMPASS, b);
4181       DOSET (FLG_UNIONDEF, b);
4182       DOSET (FLG_MEMTRANS, b);
4183       DOSET (FLG_USERELEASED, b);
4184       DOSET (FLG_ALIASUNIQUE, b);
4185       DOSET (FLG_MAYALIASUNIQUE, b);
4186       DOSET (FLG_MUSTFREEONLY, b);
4187       DOSET (FLG_MUSTFREEFRESH, b);
4188       DOSET (FLG_MUSTDEFINE, b);
4189       DOSET (FLG_GLOBSTATE, b); 
4190       DOSET (FLG_COMPDESTROY, b);
4191       DOSET (FLG_MUSTNOTALIAS, b);
4192       DOSET (FLG_MEMIMPLICIT, b);
4193       DOSET (FLG_BRANCHSTATE, b); 
4194       /*@fallthrough@*/ /* also sets memtrans flags */
4195     case FLG_MEMTRANS:
4196       DOSET (FLG_MEMTRANS, b);
4197       DOSET (FLG_EXPOSETRANS, b);
4198       DOSET (FLG_OBSERVERTRANS, b);
4199       DOSET (FLG_DEPENDENTTRANS, b);
4200       DOSET (FLG_NEWREFTRANS, b);
4201       DOSET (FLG_ONLYTRANS, b);
4202       DOSET (FLG_OWNEDTRANS, b);
4203       DOSET (FLG_FRESHTRANS, b);
4204       DOSET (FLG_SHAREDTRANS, b);
4205       DOSET (FLG_TEMPTRANS, b);
4206       DOSET (FLG_KEPTTRANS, b);
4207       DOSET (FLG_REFCOUNTTRANS, b);
4208       DOSET (FLG_STATICTRANS, b);
4209       DOSET (FLG_UNKNOWNTRANS, b);
4210       DOSET (FLG_KEEPTRANS, b);
4211       DOSET (FLG_IMMEDIATETRANS, b);
4212       break;
4213       
4214     default:
4215       break;
4216     }
4217
4218   if (b && !gc.anyExports
4219       && (f == FLG_EXPORTVAR || f == FLG_EXPORTFCN
4220           || f == FLG_EXPORTTYPE || f == FLG_EXPORTMACRO
4221           || f == FLG_EXPORTCONST
4222           || f == FLG_EXPORTANY))
4223     {
4224       gc.anyExports = TRUE;
4225     }
4226 }
4227
4228 bool 
4229 context_maybeSet (flagcode d)
4230 {
4231   return (gc.flags[d] || gc.setLocally[d]);
4232 }
4233
4234 bool
4235 context_getFlag (flagcode d)
4236 {
4237   return (gc.flags[d]);
4238 }
4239
4240 bool
4241 context_flagOn (flagcode f, fileloc loc)
4242 {
4243   return (!context_suppressFlagMsg (f, loc));
4244 }
4245
4246 static void context_saveFlagSettings (void)
4247 {
4248   gc.savedFlags = TRUE;
4249   llassert (sizeof (gc.saveflags) == sizeof (gc.flags));
4250   memcpy (gc.saveflags, gc.flags, sizeof (gc.flags));
4251 }
4252
4253 static void context_restoreFlagSettings (void)
4254 {
4255   llassert (sizeof (gc.saveflags) == sizeof (gc.flags));
4256   memcpy (gc.flags, gc.saveflags, sizeof (gc.flags));
4257   gc.savedFlags = FALSE;
4258 }
4259
4260 void context_setFilename (fileId fid, int lineno) 
4261    /*@globals fileloc g_currentloc;@*/
4262    /*@modifies g_currentloc@*/
4263 {
4264   if (fileId_baseEqual (currentFile (), fid))
4265     {
4266       setLine (lineno);
4267       return;
4268     }
4269   else
4270     {
4271       fileloc_setColumn (g_currentloc, 0);
4272
4273       if (fileloc_isSpecialFile (g_currentloc))
4274         {
4275           gc.inDerivedFile = TRUE;
4276         }
4277
4278       if (filelocStack_popPushFile (gc.locstack, g_currentloc))
4279         {
4280           int maxdepth = context_getValue (FLG_INCLUDENEST);
4281
4282           if (filelocStack_size (gc.locstack) > maxdepth)
4283             {
4284               int depth = filelocStack_includeDepth (gc.locstack);
4285               
4286               if (depth > maxdepth)
4287                 {
4288                   if (optgenerror 
4289                       (FLG_INCLUDENEST,
4290                        message ("Maximum include nesting depth "
4291                                 "(%d, current depth %d) exceeded",
4292                                 maxdepth,
4293                                 depth),
4294                        filelocStack_nextTop (gc.locstack)))
4295                     {
4296                       filelocStack_printIncludes (gc.locstack);
4297                     }
4298                 }
4299             }
4300         }
4301       
4302       g_currentloc = fileloc_create (fid, lineno, 1);
4303       gc.inheader = fileId_isHeader (currentFile ());
4304
4305       context_enterFileAux ();
4306     }
4307 }
4308
4309 void context_enterIterDef (/*@observer@*/ uentry le)
4310 {
4311   context_enterMacro (le);
4312   gc.acct = typeIdSet_subtract (gc.facct, gc.nacct);
4313   gc.kind = CX_ITERDEF;
4314 }
4315
4316 void context_enterIterEnd (/*@observer@*/ uentry le)
4317 {
4318   context_enterMacro (le);
4319   gc.kind = CX_ITEREND;
4320 }
4321
4322 void 
4323 context_destroyMod (void) 
4324    /*@globals killed gc@*/
4325 {
4326   int i;
4327   setCodePoint ();
4328   ctype_destroyMod ();
4329   /*
4330   setCodePoint ();
4331   usymtab_free ();
4332   setCodePoint ();
4333   */
4334
4335   fileTable_free (gc.ftab);
4336   gc.ftab = fileTable_undefined;
4337
4338   filelocStack_free (gc.locstack);
4339   setCodePoint ();
4340
4341   macrocache_free (gc.mc);
4342
4343   /* evans 2002-07-12: not reported because of reldef */
4344   for (i = 0; i < gc.nmods; i++)
4345     {
4346       cstring_free (gc.moduleaccess[i].file);
4347     }
4348
4349   sfree (gc.moduleaccess);
4350   setCodePoint ();
4351
4352   fileloc_free (gc.saveloc); gc.saveloc = fileloc_undefined;
4353   fileloc_free (gc.pushloc); gc.pushloc = fileloc_undefined;
4354
4355   setCodePoint ();
4356   sRefSetList_free (gc.modrecs);
4357   setCodePoint ();
4358   flagMarkerList_free (gc.markers); 
4359   setCodePoint ();
4360   messageLog_free (gc.msgLog);
4361   setCodePoint ();
4362   clauseStack_free (gc.clauses);
4363   setCodePoint ();
4364   
4365   cstring_free (gc.msgAnnote);
4366   globSet_free (gc.globs_used);
4367   metaStateTable_free (gc.stateTable);
4368   annotationTable_free (gc.annotTable);
4369
4370   
4371 }
4372
4373 /*
4374 ** Flag shortcuts.
4375 */
4376
4377 bool context_msgBoolInt (void)
4378 {
4379   return gc.flags [FLG_BOOLINT];
4380 }
4381
4382 bool context_msgCharInt (void)
4383 {
4384   return gc.flags [FLG_CHARINT];
4385 }
4386
4387 bool context_msgEnumInt (void)
4388 {
4389   return gc.flags [FLG_ENUMINT];
4390 }
4391
4392 bool context_msgPointerArith (void) 
4393 {
4394   return gc.flags [FLG_POINTERARITH];
4395 }
4396
4397 bool context_msgStrictOps (void) 
4398 {
4399   return gc.flags [FLG_STRICTOPS];
4400 }
4401
4402 bool context_msgLh (void)           
4403 {
4404   return gc.flags [FLG_DOLH];
4405 }
4406
4407 void context_pushLoc (void) 
4408 {
4409   fileloc_free (gc.pushloc);
4410   gc.pushloc = gc.saveloc;
4411   gc.saveloc = fileloc_undefined;
4412 }
4413
4414 void context_popLoc (void) 
4415 {
4416   gc.saveloc = fileloc_update (gc.saveloc, gc.pushloc);
4417 }
4418
4419 bool context_inGlobalScope (void)
4420 {
4421   return (usymtab_inFileScope() || usymtab_inGlobalScope ());
4422 }
4423
4424 bool context_inInnerScope (void)
4425 {
4426   return (gc.kind == CX_INNER);
4427 }
4428
4429 void context_setProtectVars (void)
4430 {
4431   gc.protectVars = TRUE;
4432 }
4433
4434 bool context_anyErrors (void)
4435 {
4436   return (gc.numerrors > 0);
4437 }
4438
4439 void context_hasError (void)
4440 {
4441   gc.numerrors++;
4442   DPRINTF (("num errors: %d", gc.numerrors));
4443 }
4444
4445 int context_numErrors (void)
4446 {
4447   return gc.numerrors;
4448 }
4449
4450 bool context_neednl (void)
4451 {
4452   return gc.neednl;
4453 }
4454
4455 void context_setNeednl (void)
4456 {
4457   gc.neednl = TRUE;
4458 }
4459
4460 int context_getExpect (void)
4461 {
4462   return (context_getValue (FLG_EXPECT));
4463 }
4464
4465 int context_getLCLExpect (void)
4466 {
4467   return (context_getValue (FLG_LCLEXPECT));
4468 }
4469
4470 int context_getLimit (void)
4471 {
4472   return (context_getValue (FLG_LIMIT));
4473 }
4474
4475 bool context_unlimitedMessages (void)
4476 {
4477   return (context_getLimit () < 0);
4478 }
4479
4480 void context_releaseVars (void)
4481 {
4482   llassert (gc.protectVars);
4483   gc.protectVars = FALSE;
4484 }
4485
4486 void context_sizeofReleaseVars (void)
4487 {
4488   /* If there is a nested sizeof, this might not hold:
4489      llassert (gc.protectVars);
4490      */
4491
4492   gc.protectVars = FALSE;
4493 }
4494
4495 bool context_inProtectVars (void)
4496 {
4497   return (gc.protectVars);
4498 }
4499
4500 void context_hideShowscan (void) 
4501 {
4502   gc.flags[FLG_SHOWSCAN] = FALSE;
4503 }
4504
4505 void context_unhideShowscan (void)
4506 {
4507   gc.flags[FLG_SHOWSCAN] = TRUE;
4508 }
4509
4510 bool context_inHeader (void)
4511 {
4512   return (gc.inheader);
4513 }
4514
4515 fileTable context_fileTable (void)
4516 {
4517   return gc.ftab;
4518 }
4519
4520 cstring context_tmpdir (void)
4521 {
4522   return (context_getString (FLG_TMPDIR));
4523 }
4524
4525 messageLog context_messageLog (void)
4526 {
4527   return gc.msgLog;
4528 }
4529
4530 bool context_inMacroFunction (void)
4531 {
4532   return (gc.kind == CX_MACROFCN);
4533 }
4534
4535 bool context_inMacroConstant (void)
4536 {   
4537   return (gc.kind == CX_MACROCONST);
4538 }
4539
4540 bool context_inUnknownMacro (void)
4541 {   
4542   return (gc.kind == CX_UNKNOWNMACRO);
4543 }
4544
4545 void context_setShownFunction (void)
4546 {
4547   gc.showfunction = FALSE;
4548 }
4549
4550 bool context_doDump (void)
4551 {   
4552   return cstring_isNonEmpty (context_getString (FLG_DUMP));
4553 }
4554
4555 bool context_doMerge (void)
4556 {
4557   return cstring_isNonEmpty (context_getString (FLG_MERGE));
4558 }
4559
4560 cstring context_getDump (void)
4561 {           
4562   return context_getString (FLG_DUMP);
4563 }
4564
4565 cstring context_getMerge (void)
4566 {
4567   return context_getString (FLG_MERGE);
4568 }
4569
4570 bool context_inLCLLib (void)
4571 {   
4572   return (gc.kind == CX_LCLLIB);
4573 }
4574
4575 bool context_inImport (void)
4576 {
4577   return (gc.inimport);
4578 }
4579
4580 void context_enterImport (void)
4581
4582   gc.inimport = TRUE;
4583 }
4584
4585 void context_leaveImport (void)
4586
4587   gc.inimport = FALSE;
4588 }
4589
4590 bool context_inMacro (void) 
4591 {
4592   return (gc.kind == CX_MACROFCN || gc.kind == CX_MACROCONST 
4593           || gc.kind == CX_UNKNOWNMACRO
4594           || gc.kind == CX_ITERDEF || gc.kind == CX_ITEREND);
4595 }
4596
4597 bool context_inIterDef (void)
4598 {
4599   return (gc.kind == CX_ITERDEF);
4600 }
4601
4602 bool context_inIterEnd (void)
4603 {
4604   return (gc.kind == CX_ITEREND);
4605 }
4606
4607 int context_getLinesProcessed (void)    
4608 {
4609   return (gc.linesprocessed);
4610 }
4611
4612 int context_getSpecLinesProcessed (void)    
4613 {
4614   return (gc.speclinesprocessed);
4615 }
4616
4617 void context_processedSpecLine (void)
4618 {
4619   gc.speclinesprocessed++;
4620 }
4621
4622 void context_resetSpecLines (void)    
4623 {
4624   gc.speclinesprocessed = 0;
4625
4626 }
4627
4628 bool context_inGlobalContext (void)
4629 {
4630   return (gc.kind == CX_GLOBAL);
4631 }
4632
4633 static void context_quietExitScopes (void)
4634 {
4635   /*
4636   ** Try to restore the global scope (after an error).
4637   */
4638
4639   while (!usymtab_inFileScope ())
4640     {
4641       usymtab_quietExitScope (g_currentloc);
4642     }
4643
4644   gc.cont.glob = TRUE;
4645   gc.kind = CX_GLOBAL;
4646 }
4647
4648 void context_checkGlobalScope (void)
4649 {
4650   if (gc.kind != CX_GLOBAL)
4651     {
4652       if (context_inMacro ())
4653         {
4654           ; /* evans 2001-10-14: Okay to be in a macro here! */ 
4655         }
4656       else
4657         {
4658           llcontbug (message ("Not in global scope as expected: %q", context_unparse ()));
4659           context_quietExitScopes ();
4660         }
4661     }
4662 }
4663
4664 void context_setFileId (fileId s)
4665 {
4666   g_currentloc = fileloc_updateFileId (g_currentloc, s); 
4667 }
4668
4669 bool context_setBoolName (void)
4670 {
4671   return (!cstring_equalLit (context_getString (FLG_BOOLTYPE),
4672                              DEFAULT_BOOLTYPE));
4673 }
4674
4675 cstring context_printBoolName (void)
4676 {
4677   if (context_setBoolName ()) 
4678     {
4679       return context_getBoolName ();
4680     }
4681   else
4682     {
4683       return cstring_makeLiteralTemp ("boolean");
4684     }
4685 }
4686
4687 cstring context_getBoolName (void)
4688 {
4689   return (context_getString (FLG_BOOLTYPE));
4690 }
4691
4692 cstring context_getFalseName (void)
4693 {
4694   return (context_getString (FLG_BOOLFALSE));
4695 }
4696
4697 cstring context_getTrueName (void)
4698 {
4699   return (context_getString (FLG_BOOLTRUE));
4700 }
4701
4702 cstring context_getLarchPath (void)
4703 {
4704   return (context_getString (FLG_LARCHPATH));
4705 }
4706
4707 cstring context_getLCLImportDir (void)
4708 {
4709   return (context_getString (FLG_LCLIMPORTDIR));
4710 }
4711
4712 static void context_setJustPopped (void)
4713 {
4714   gc.justpopped = TRUE;
4715 }
4716
4717 void context_clearJustPopped (void)
4718 {
4719   gc.justpopped = FALSE;
4720 }
4721
4722 bool context_justPopped (void)
4723 {
4724   return (gc.justpopped);
4725 }
4726
4727 void context_setMacroMissingParams (void)
4728 {
4729   gc.macroMissingParams = TRUE;
4730 }
4731
4732 void context_resetMacroMissingParams (void)
4733 {
4734   gc.macroMissingParams = FALSE;
4735 }
4736
4737 bool context_isMacroMissingParams (void)
4738 {
4739   return (gc.macroMissingParams);
4740 }
4741
4742 void context_showFilelocStack (void) 
4743 {
4744   filelocStack_printIncludes (gc.locstack);
4745 }
4746
4747 metaStateTable context_getMetaStateTable (void) 
4748 {
4749   return gc.stateTable;
4750 }
4751
4752 metaStateInfo context_lookupMetaStateInfo (cstring key)
4753 {
4754   return metaStateTable_lookup (gc.stateTable, key);
4755 }
4756
4757 /*@null@*/ annotationInfo context_lookupAnnotation (cstring annot) 
4758 {
4759   annotationInfo ainfo;
4760
4761   ainfo = annotationTable_lookup (gc.annotTable, annot);
4762
4763   return ainfo;
4764 }
4765
4766 void context_addAnnotation (annotationInfo ainfo)
4767 {
4768   if (annotationTable_contains (gc.annotTable, annotationInfo_getName (ainfo)))
4769     {
4770       voptgenerror 
4771         (FLG_SYNTAX,
4772          message ("Duplicate annotation declaration: %s", annotationInfo_getName (ainfo)),
4773          annotationInfo_getLoc (ainfo));
4774
4775       annotationInfo_free (ainfo);
4776     }
4777   else
4778     {
4779       annotationTable_insert (gc.annotTable, ainfo);
4780     }
4781 }
4782
4783 void context_addMetaState (cstring mname, metaStateInfo msinfo)
4784 {
4785   if (metaStateTable_contains (gc.stateTable, mname))
4786     {
4787       voptgenerror 
4788         (FLG_SYNTAX,
4789          message ("Duplicate metastate declaration: %s", mname),
4790          metaStateInfo_getLoc (msinfo));
4791       cstring_free (mname);
4792       metaStateInfo_free (msinfo);
4793     }
4794   else
4795     {
4796       DPRINTF (("Adding meta state: %s", mname));
4797       metaStateTable_insert (gc.stateTable, mname, msinfo); 
4798     }
4799 }
4800
4801 valueTable context_createValueTable (sRef s, stateInfo sinfo)
4802 {
4803   if (metaStateTable_size (gc.stateTable) > 0)
4804     {
4805       valueTable res = valueTable_create (metaStateTable_size (gc.stateTable));
4806       /*@i32 should use smaller value... */
4807       DPRINTF (("Value table for: %s", sRef_unparse (s)));
4808       
4809       metaStateTable_elements (gc.stateTable, msname, msi)
4810         {
4811           mtContextNode context = metaStateInfo_getContext (msi);
4812
4813           if (mtContextNode_matchesRefStrict (context, s))
4814             {
4815               DPRINTF (("Create: %s", metaStateInfo_unparse (msi)));
4816               llassert (cstring_equal (msname, metaStateInfo_getName (msi)));
4817               
4818               valueTable_insert 
4819                 (res,
4820                  cstring_copy (metaStateInfo_getName (msi)),
4821                  stateValue_createImplicit (metaStateInfo_getDefaultValue (msi, s), 
4822                                             stateInfo_copy (sinfo)));
4823             }
4824           else
4825             {
4826               DPRINTF (("No match: %s", metaStateInfo_unparse (msi)));
4827             }
4828         } 
4829       end_metaStateTable_elements ;
4830       
4831       stateInfo_free (sinfo);
4832       DPRINTF (("Value table: %s", valueTable_unparse (res)));
4833       return res;
4834     }
4835   else
4836     {
4837       stateInfo_free (sinfo);
4838       return valueTable_undefined;
4839     }
4840 }
4841
4842 valueTable context_createGlobalMarkerValueTable (stateInfo sinfo)
4843 {
4844   if (metaStateTable_size (gc.stateTable) > 0)
4845     {
4846       valueTable res = valueTable_create (metaStateTable_size (gc.stateTable));
4847       /*@i32 should use smaller value... */
4848       
4849       metaStateTable_elements (gc.stateTable, msname, msi)
4850         {
4851           /*@i23 only add global...*/
4852           DPRINTF (("Create: %s", metaStateInfo_unparse (msi)));
4853           llassert (cstring_equal (msname, metaStateInfo_getName (msi)));
4854           
4855           valueTable_insert (res,
4856                              cstring_copy (metaStateInfo_getName (msi)),
4857                              stateValue_create (metaStateInfo_getDefaultGlobalValue (msi),
4858                                                 stateInfo_copy (sinfo)));
4859         } 
4860       end_metaStateTable_elements ;
4861       
4862       stateInfo_free (sinfo);
4863       DPRINTF (("Value table: %s", valueTable_unparse (res)));
4864       return res;
4865     }
4866   else
4867     {
4868       stateInfo_free (sinfo);
4869       return valueTable_undefined;
4870     }
4871 }
4872
4873
4874 /*drl 12/30/01 these are some ugly functions that were added to facilitate struct annotations */
4875
4876
4877 /*drl added */
4878 static ctype lastStruct;
4879
4880 ctype context_setLastStruct (/*@returned@*/ ctype s) /*@globals lastStruct@*/
4881 {
4882   lastStruct = s;
4883   return s;
4884 }
4885
4886 ctype context_getLastStruct (/*@returned@*/ /*ctype s*/) /*@globals lastStruct@*/
4887 {
4888   return lastStruct;
4889 }
4890
4891 /*
4892 ** Why is this stuff in context.c?
4893 */
4894
4895 /*@unused@*/ static int sInfoNum = 0;
4896
4897
4898 struct getUe {
4899   /*@unused@*/  uentry ue;
4900   /*@unused@*/ sRef s;
4901 };
4902
4903 struct sInfo {
4904   /*@unused@*/ ctype ct;
4905   /*@unused@*/ constraintList inv;
4906  /*@unused@*/ int ngetUe;
4907  /*@unused@*/ struct getUe * t ;
4908 };
4909
4910
4911 static struct sInfo globalStructInfo;
4912
4913
4914 /*drl 1/6/2001: I didn't think these functions were solid enough to include in the
4915   stable  release of splint.  I coomented them out so that they won't break anything
4916   but didn't delete them because they will be fixed and included later
4917
4918
4919 */
4920
4921 /*@-paramuse@*/
4922
4923 void  setGlobalStructInfo(ctype ct, constraintList list)
4924 {
4925 # if 0
4926   /* int i;
4927   uentryList f;
4928
4929   f =  ctype_getFields (ct);
4930   
4931   if (constraintList_isDefined(list) )
4932     {
4933       globalStructInfo.ct = ct;
4934       globalStructInfo.inv = list;
4935
4936       globalStructInfo.ngetUe = 0;
4937       
4938       /* abstraction violation fix it * /
4939       globalStructInfo.t   = dmalloc(f->nelements * sizeof(struct getUe) );
4940
4941       globalStructInfo.ngetUe = f->nelements;
4942
4943       i = 0;
4944       
4945       uentryList_elements(f, ue)
4946         {
4947           globalStructInfo.t[i].ue = ue;
4948           globalStructInfo.t[i].s = uentry_getSref(ue);
4949           TPRINTF(( message(" setGlobalStructInfo:: adding ue=%s and sRef=%s",
4950                             uentry_unparse(ue), sRef_unparse( uentry_getSref(ue) )
4951                             )
4952                     ));
4953           i++;
4954         }
4955       end_uentryList_elements;
4956     }
4957   */
4958 # endif
4959 }
4960
4961 # if 0
4962 /*
4963
4964 bool hasInvariants (ctype ct) /*@* /
4965 {
4966   if ( ctype_sameName(globalStructInfo.ct, ct) )
4967
4968     return TRUE;
4969
4970   else
4971     
4972     return FALSE;
4973   
4974 }
4975 */
4976 # endif
4977
4978 /*@=paramuse@*/
4979
4980
4981
4982
This page took 0.567949 seconds and 5 git commands to generate.