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