]> andersk Git - splint.git/blob - src/context.c
fa1d64d4a0c3950557acca24cef93fb4c42b70e5
[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     case FLG_MESSAGESTREAM:
2902     case FLG_WARNINGSTREAM:
2903     case FLG_ERRORSTREAM:
2904       {
2905         if (cstring_isDefined (val))
2906           {
2907             FILE *fstream;
2908
2909             if (osd_fileExists (val))
2910               {
2911                 if (context_getFlag (FLG_STREAMOVERWRITE))
2912                   {
2913                     llfatalerror (message 
2914                                   ("Output stream file %s would overwrite existing file. "
2915                                    "Use -streamoverwrite if you want to allow this.", 
2916                                    val));
2917                   }
2918               }
2919             
2920             fstream = fopen (cstring_toCharsSafe (val), "w");
2921
2922             if (fstream == NULL)
2923               {
2924                 llfatalerror (message ("Unable to open output stream file %s for writing", 
2925                                        val));
2926               }
2927
2928             /*
2929             ** This ensures fstream will be closed on exit.
2930             */
2931
2932             fileTable_addStreamFile (gc.ftab, fstream, cstring_copy (val));
2933             
2934             switch (flag)
2935               {
2936               case FLG_MESSAGESTREAM:
2937                 g_messagestream = fstream; 
2938                 /*@innerbreak@*/ break;
2939               case FLG_WARNINGSTREAM:
2940                 g_warningstream = fstream;
2941                 /*@innerbreak@*/ break;
2942               case FLG_ERRORSTREAM:
2943                 g_errorstream = fstream; 
2944                 /*@innerbreak@*/ break;
2945                 BADDEFAULT;
2946               }
2947             /*@-statetransfer@*/
2948           } /*@=statetransfer@*/ /* fstream not closed, but will be on exit */
2949         break;
2950       }
2951     case FLG_SYSTEMDIRS:
2952       {
2953         llassert (cstring_isDefined (val));
2954         
2955         if (cstring_firstChar (val) == '\"')
2956           {
2957             cstring oval = val;
2958             cstring tval = cstring_copy (cstring_suffix (val, 1));
2959             
2960             if (cstring_lastChar (tval) != '\"')
2961               {
2962                 int n = size_toInt (cstring_length (tval) - 1);
2963                 
2964                 while (isspace ((int) cstring_getChar (tval, size_fromInt (n))))
2965                   {
2966                     n--;
2967                   }
2968                 
2969                 if (cstring_getChar (tval, size_fromInt (n)) != '\"')
2970                   {
2971                     llerror_flagWarning 
2972                       (message ("Setting -systemdirs to string with unmatching quotes: %s", val));
2973                   }
2974                 else
2975                   {
2976                     cstring otval = tval;
2977                     tval = cstring_prefix (tval, size_fromInt (n));
2978                     cstring_free (otval);
2979                   }
2980               }
2981             
2982             val = cstring_copy (cstring_clip (tval, cstring_length (tval) - 1));
2983             DPRINTF (("val = %s", val));
2984             cstring_free (tval);
2985             cstring_free (oval);
2986           }
2987         
2988         break;
2989       }
2990     case FLG_TMPDIR:
2991       {
2992         llassert (cstring_isDefined (val));
2993         
2994         if (cstring_length (val) == 0)
2995           {
2996             cstring_free (val);
2997             val = message (".%s", cstring_makeLiteralTemp (CONNECTSTR));
2998           }
2999         else if (cstring_lastChar (val) != CONNECTCHAR)
3000           {
3001             val = cstring_appendChar (val, CONNECTCHAR);
3002           }
3003         else
3004           {
3005             ;
3006           }
3007         break;
3008       }
3009     default:
3010       {
3011         ; /* Okay not handle everything in this switch */
3012       }
3013       /*@-branchstate@*/
3014     } /* evans 2002-03-24: splintme reports a spurious (I think) warning here...need to look into it */
3015   /*@=branchstate@*/ 
3016
3017   if (cstring_length (val) >= 1
3018       && cstring_firstChar (val) == '\"')
3019     {
3020       llerror_flagWarning (message
3021                            ("Setting %s to string beginning with \".  You probably "
3022                             "don't meant to have the \"'s.",
3023                             flagcode_unparse (flag)));
3024     }
3025   
3026   gc.strings[index] = val;
3027 }
3028
3029 static /*@exposed@*/ cstring
3030 context_exposeString (flagcode flag)
3031 {
3032   int index = flagcode_stringIndex (flag);
3033
3034   llassert (index >= 0 && index <= NUMSTRINGFLAGS);
3035   return (gc.strings[index]);
3036 }
3037
3038 cstring
3039 context_getString (flagcode flag)
3040 {
3041   return (context_exposeString (flag));
3042 }
3043
3044 void
3045 context_resetErrors (void)
3046 {
3047   gc.numerrors = 0;
3048 }
3049
3050 void context_initMod (void)
3051    /*@globals undef gc; @*/
3052 {
3053   gc.kind = CX_GLOBAL;
3054
3055   gc.savekind = CX_ERROR;
3056   gc.savecont.glob = FALSE;
3057
3058   gc.instandardlib = FALSE;
3059   gc.numerrors = 0;
3060   gc.neednl = FALSE;
3061   gc.linesprocessed = 0;
3062   gc.speclinesprocessed = 0;
3063   gc.insuppressregion = FALSE;
3064   gc.macroMissingParams = FALSE;
3065   gc.preprocessing = FALSE;
3066   gc.incommandline = FALSE;
3067   gc.mc = macrocache_create ();
3068   gc.nmods = 0;
3069   gc.maxmods = DEFAULTMAXMODS;
3070   gc.moduleaccess = (maccesst *) dmalloc (sizeof (*gc.moduleaccess) * (gc.maxmods));
3071   
3072   gc.library = FLG_ANSILIB;
3073
3074   gc.locstack = filelocStack_new ();
3075   gc.modrecs = sRefSetList_undefined;
3076   gc.anyExports = FALSE;
3077
3078   gc.ftab = fileTable_create ();
3079   gc.msgLog = messageLog_new ();
3080   gc.inimport = FALSE;
3081   gc.inDerivedFile = FALSE;
3082   gc.inheader = FALSE;
3083   gc.markers = flagMarkerList_new ();
3084   gc.cont.glob = TRUE;
3085   gc.showfunction = FALSE;
3086   gc.msgAnnote = cstring_undefined;
3087   gc.aliasAnnote = sRef_undefined;
3088   gc.aliasAnnoteAls = sRef_undefined;
3089   gc.boolType = ctype_bool;
3090   gc.mods = sRefSet_new ();
3091
3092   gc.saveloc = fileloc_undefined;
3093
3094   gc.inmacrocache = FALSE;
3095   gc.inclause = NOCLAUSE;
3096   gc.clauses = clauseStack_new ();
3097   gc.globs = globSet_new ();
3098   gc.nacct = typeIdSet_emptySet ();
3099   gc.acct = typeIdSet_emptySet ();
3100   gc.facct = typeIdSet_emptySet ();
3101   gc.savedFlags = FALSE;
3102   gc.pushloc = fileloc_undefined;
3103   gc.protectVars = FALSE;
3104   gc.justpopped = FALSE;
3105   gc.isNullGuarded = NO;
3106   gc.globs_used = globSet_undefined;
3107   
3108   allFlagCodes (code)
3109     {
3110       gc.setGlobally[code] = FALSE;
3111       gc.setLocally[code] = FALSE;
3112     } 
3113   end_allFlagCodes ;
3114   
3115   usymtab_initMod ();
3116   context_resetAllFlags ();
3117
3118   assertSet (gc.flags); /* Can't use global in defines */
3119   assertSet (gc.saveflags);
3120   assertSet (gc.values);
3121   assertSet (gc.strings);
3122   
3123   conext_resetAllCounters ();
3124   assertSet (gc.counters);
3125
3126   context_setMode (DEFAULT_MODE);
3127
3128   gc.stateTable = metaStateTable_create ();
3129   gc.annotTable = annotationTable_create ();
3130
3131   gc.inFunctionHeader = FALSE;
3132
3133   DPRINTF (("Annotations: \n%s",
3134             cstring_toCharsSafe (annotationTable_unparse (gc.annotTable))));
3135   DPRINTF (("State: \n%s",
3136             cstring_toCharsSafe (metaStateTable_unparse (gc.stateTable))));
3137
3138 }
3139
3140 ctype
3141 context_typeofZero (void)
3142 {
3143   ctype ct = ctype_int;
3144
3145   if (context_getFlag (FLG_ZEROPTR))
3146     {
3147       ct = ctype_makeConj (ct, ctype_voidPointer);
3148     }
3149   
3150   if (context_getFlag (FLG_ZEROBOOL)) {
3151     ct = ctype_makeConj (ct, ctype_bool); 
3152   }
3153
3154   return ct;
3155 }
3156
3157 ctype
3158 context_typeofOne (void)
3159 {
3160   ctype ct = ctype_int;
3161
3162   /* 1 is on longer a bool (was before 2.4)
3163      if (!context_getFlag (FLG_ABSTRACTBOOL))
3164      {
3165      ct = ctype_makeConj (ct, ctype_bool);
3166      }
3167      */
3168
3169   return (ct);
3170 }
3171
3172 /*@only@*/ cstring
3173 context_unparse (void)
3174 {
3175   cstring s;
3176
3177   switch (gc.kind)
3178     {
3179     case CX_LCL:
3180       s = message ("LCL File: %q", fileloc_unparse (g_currentloc));
3181       break;
3182     case CX_LCLLIB:
3183       s = message ("LCL Lib File: %q", fileloc_unparse (g_currentloc));
3184       break;
3185     case CX_GLOBAL:
3186       s = message ("Global Context:%q", fileloc_unparse (g_currentloc));
3187       break;
3188     case CX_INNER:
3189       s = message ("Inner Context [%d] : %q", 
3190                    gc.cont.cdepth,
3191                    fileloc_unparse (g_currentloc));
3192       break;
3193     case CX_FUNCTION:
3194       s = message ("Function %q :%q \n\taccess %q\n\tmodifies %q",
3195                    uentry_unparse (gc.cont.fcn),
3196                    fileloc_unparse (g_currentloc),
3197                    typeIdSet_unparse (gc.acct),
3198                    sRefSet_unparse (gc.mods));
3199       break;
3200     case CX_MACROFCN:
3201       s = message ("Function Macro %q", uentry_unparse (gc.cont.fcn));
3202       break;
3203     case CX_UNKNOWNMACRO:
3204       s = message ("Forward Specified Macro %q", uentry_unparse (gc.cont.fcn));
3205       break;
3206     case CX_MACROCONST:
3207       s = message ("Constant Macro %q", uentry_unparse (gc.cont.fcn));
3208       break;
3209     case CX_ITERDEF:
3210       s = message ("Iter definition %q", uentry_unparse (gc.cont.fcn));
3211       break;
3212     case CX_ITEREND:
3213       s = message ("Iter end %q", uentry_unparse (gc.cont.fcn));
3214       break;
3215     case CX_FCNDECLARATION:
3216       s = message ("Function declaration %q", uentry_unparse (gc.cont.fcn));
3217       break;
3218     default:
3219       s = message ("Un-unparseable context: %d", (int) gc.kind);
3220       break;
3221     }
3222   
3223   s = message ("%q\naccess: %q", s, context_unparseAccess ());
3224   return (s);
3225 }
3226
3227 extern ctype
3228 context_currentFunctionType (void)
3229 {
3230   if (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN)
3231     {
3232             return (uentry_getType (gc.cont.fcn));
3233     }
3234   else if (gc.kind == CX_INNER)
3235     {
3236       llcontbuglit ("context_currentFunctionType: inner context");
3237       do { context_exitInnerPlain (); } while (gc.kind == CX_INNER);
3238       return (context_currentFunctionType ());
3239     }
3240   else
3241     {
3242       llcontbuglit ("context_currentFunctionType: not in function");
3243       return (ctype_undefined);
3244     }
3245 }
3246
3247 void
3248 context_enterInnerContext (void)
3249 {
3250   if (context_getFlag (FLG_GRAMMAR))
3251     {
3252       lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
3253     }
3254
3255   if (gc.kind == CX_GLOBAL)
3256     {
3257       gc.kind = CX_INNER;
3258       gc.cont.cdepth = 1;
3259     }
3260   else if (gc.kind == CX_INNER)
3261     {
3262       gc.cont.cdepth++;
3263     }
3264   else
3265     {
3266       ;
3267     }
3268
3269   usymtab_enterScope ();
3270   pushClause (NOCLAUSE);
3271 }
3272
3273 void
3274 context_exitInnerPlain (void) /*@modifies gc;@*/
3275 {
3276   context_exitInner (exprNode_undefined);
3277 }
3278
3279 void
3280 context_exitInner (exprNode exp)
3281 {
3282    if (context_getFlag (FLG_GRAMMAR))
3283     {
3284       lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
3285     }
3286  
3287   llassertprint (gc.inclause == NOCLAUSE || gc.inclause == CASECLAUSE,
3288                  ("inclause = %s", clause_nameTaken (gc.inclause)));
3289
3290   clauseStack_removeFirst (gc.clauses, NOCLAUSE);
3291   gc.inclause = topClause (gc.clauses);
3292
3293   if (gc.kind == CX_INNER)
3294     {
3295       if (--gc.cont.cdepth == 0)
3296         {
3297           gc.kind = CX_GLOBAL;
3298           gc.cont.glob = TRUE;
3299         }
3300     }
3301   else 
3302     {
3303       if (gc.kind == CX_GLOBAL)
3304         {
3305           llcontbuglit ("Attempt to exit global context");
3306           return;
3307         }
3308     }
3309
3310     usymtab_exitScope (exp);
3311 }
3312
3313
3314 void
3315 context_enterStructInnerContext (void)
3316 {
3317   if (context_getFlag (FLG_GRAMMAR))
3318     {
3319       lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
3320     }
3321
3322   if (gc.kind == CX_GLOBAL)
3323     {
3324       gc.kind = CX_INNER;
3325       gc.cont.cdepth = 1;
3326     }
3327   else if (gc.kind == CX_INNER)
3328     {
3329       gc.cont.cdepth++;
3330     }
3331   else
3332     {
3333       ;
3334     }
3335
3336   usymtab_enterScope ();
3337
3338   if (context_getFlag (FLG_GRAMMAR))
3339     {
3340       lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
3341     }
3342 }
3343
3344 void
3345 context_exitStructInnerContext (void)
3346 {
3347   if (context_getFlag (FLG_GRAMMAR))
3348     {
3349       lldiagmsg (message ("Exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
3350     }
3351
3352   if (gc.kind == CX_INNER)
3353     {
3354       if (gc.cont.cdepth <= 0)
3355         {
3356           llcontbuglit ("Attempt to exit inner context with no depth");
3357           gc.kind = CX_GLOBAL;
3358           gc.cont.glob = TRUE;
3359           gc.cont.cdepth = 0;
3360         }
3361       else {
3362         gc.cont.cdepth--;
3363
3364         if (gc.cont.cdepth == 0)
3365           {
3366             gc.kind = CX_GLOBAL;
3367             gc.cont.glob = TRUE;
3368           }
3369       }
3370     }
3371   else 
3372     {
3373       if (gc.kind == CX_GLOBAL)
3374         {
3375           llcontbuglit ("Attempt to exit global context");
3376           return;
3377         }
3378     }
3379
3380   usymtab_exitScope (exprNode_undefined);
3381
3382   if (context_getFlag (FLG_GRAMMAR))
3383     {
3384       lldiagmsg (message ("After exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
3385     }
3386 }
3387
3388 void
3389 context_exitInnerSafe (void)
3390 {
3391   if (context_getFlag (FLG_GRAMMAR))
3392     {
3393       lldiagmsg (message ("Exit inner safe: %q", context_unparse ()));
3394     }
3395
3396   if (gc.kind == CX_INNER)
3397     {
3398       if (--gc.cont.cdepth <= 0)
3399         {
3400           gc.cont.cdepth = 0;
3401         }
3402     }
3403   else if (gc.kind == CX_GLOBAL)
3404     {
3405       llcontbuglit ("Attempt to exit global context");
3406       return;
3407     }
3408   else
3409     {
3410       if (usymtab_inDeepScope ())
3411         {
3412           usymtab_exitScope (exprNode_undefined);
3413         }
3414     }
3415 }
3416
3417 static
3418 void setModuleAccess (void)
3419 {
3420   gc.facct = typeIdSet_emptySet ();
3421
3422   if (fileId_isValid (currentFile ()))
3423     {
3424       cstring baseName = fileloc_getBase (g_currentloc);
3425       
3426       if (context_getFlag (FLG_ACCESSFILE))
3427         {
3428           if (usymtab_existsType (baseName))
3429             {
3430               gc.facct = typeIdSet_insert (gc.facct, 
3431                                            usymtab_getTypeId (baseName));
3432             }
3433           else 
3434             {
3435               ;
3436             }
3437         }
3438       
3439       if (context_getFlag (FLG_ACCESSMODULE))
3440         {
3441           int i;
3442           bool hasaccess = FALSE;
3443           
3444           for (i = 0; i < gc.nmods; i++)
3445             {
3446               if (cstring_equal (baseName, gc.moduleaccess[i].file))
3447                 {
3448                   gc.facct = typeIdSet_union (gc.facct, gc.moduleaccess[i].daccess);
3449
3450                   hasaccess = TRUE;
3451                   break;
3452                 }
3453             }
3454         }
3455       
3456       gc.acct = gc.facct;
3457       gc.inheader = fileId_isHeader (currentFile ());
3458     }
3459   else
3460     {
3461       llcontbuglit ("Current file not defined\n");
3462       gc.facct = typeIdSet_emptySet ();
3463       gc.acct = gc.facct;
3464       gc.inheader = FALSE;
3465     }
3466   
3467   /* 17 Jan 1995: forgot to clear nacct */
3468   
3469   gc.nacct = typeIdSet_emptySet ();
3470 }
3471
3472 static void
3473 context_enterFileAux (void)
3474 {
3475   setModuleAccess ();
3476 }
3477
3478 void
3479 context_enterFile (void)
3480 {
3481   context_enterFileAux ();
3482   usymtab_enterFile ();
3483 }
3484
3485 void
3486 context_enterMacroFile (void)
3487 {
3488   context_enterFileAux ();
3489 }
3490
3491 bool 
3492 context_inFunction (void)
3493 {
3494   kcontext ck = gc.kind;
3495   
3496   return ((ck == CX_FUNCTION) || (ck == CX_MACROFCN) || (ck == CX_INNER));
3497 }
3498
3499 bool 
3500 context_inFunctionLike (void)
3501 {
3502   return (gc.kind == CX_FUNCTION || gc.kind == CX_MACROFCN 
3503           || gc.kind == CX_FCNDECLARATION
3504           || gc.kind == CX_UNKNOWNMACRO || gc.kind == CX_ITERDEF);
3505 }
3506
3507 bool 
3508 context_inRealFunction (void)
3509 {
3510   kcontext ck = gc.kind;
3511   
3512   return ((ck == CX_FUNCTION) || (ck == CX_MACROFCN));
3513 }
3514   
3515 void
3516 context_processAllMacros (void)
3517 {
3518   usymtab_enterFile ();
3519
3520   gc.inmacrocache = TRUE; 
3521   macrocache_processUndefinedElements (gc.mc);
3522   cleanupMessages ();  
3523   usymtab_exitFile ();
3524
3525   gc.inmacrocache = FALSE;
3526   macrocache_finalize ();
3527 }
3528
3529 /*
3530 ** this happens once at the end of each C file
3531 **
3532 ** check each Macro that was defined in current file.c or current file.h
3533 **
3534 */
3535
3536 static void
3537 context_processMacros (void)
3538 {
3539   if (fileId_isValid (currentFile ()))
3540     {
3541       fileloc lastfl;
3542       cstring cbase = fileLib_removePathFree (fileLib_removeAnyExtension (fileTable_fileName (currentFile ())));
3543       
3544       gc.inmacrocache = TRUE;
3545
3546       DPRINTF (("Processing macros: %s", cbase));
3547       lastfl = macrocache_processFileElements (gc.mc, cbase);
3548       DPRINTF (("Processing macros: %s", fileloc_unparse (lastfl)));
3549
3550       cstring_free (cbase);
3551       
3552       if (fileloc_isDefined (lastfl))
3553         {
3554           g_currentloc = fileloc_update (g_currentloc, lastfl);
3555           cleanupMessages ();
3556         }
3557
3558       gc.inmacrocache = FALSE;
3559     }
3560 }
3561
3562 bool
3563 context_processingMacros (void)
3564 {
3565   return (gc.inmacrocache);
3566 }
3567
3568 void
3569 context_exitCFile (void)
3570 {
3571   if (gc.kind != CX_GLOBAL)
3572     {
3573       llfatalerrorLoc
3574         (cstring_makeLiteral ("File ended outside global scope"));
3575     }
3576
3577   if (gc.insuppressregion)
3578     {
3579      /* gack...don't reverse the order of these lines! ;-> */
3580       gc.insuppressregion = FALSE;
3581       llerrorlit (FLG_SYNTAX, 
3582                   "File ended in ignore errors region, "
3583                   "possible missing /*@end*/");
3584     }
3585
3586   /* fix up parse errors */
3587
3588   while (!usymtab_inFileScope ())
3589     {
3590       usymtab_quietExitScope (g_currentloc);
3591     }
3592
3593   /*
3594   ** Clear the file-specific modifies information.
3595   */
3596   
3597   sRefSetList_elements (gc.modrecs, mods)
3598     {
3599       sRefSet_clearStatics (mods);
3600     } end_sRefSetList_elements ;
3601   
3602   sRefSetList_clear (gc.modrecs);
3603   
3604   context_processMacros ();
3605   cleanupMessages (); 
3606   
3607   usymtab_exitFile ();
3608   
3609   gc.inDerivedFile = FALSE;
3610   filelocStack_clear (gc.locstack);
3611   
3612   gc.nacct = typeIdSet_emptySet (); /* empty noaccess */
3613   
3614   gc.cont.glob = TRUE;
3615   
3616   if (gc.savedFlags)
3617     {
3618       context_restoreFlagSettings ();
3619       gc.savedFlags = FALSE;
3620     }
3621   
3622   /*
3623     DPRINTF (("After exiting file: "));
3624     usymtab_printAll ();
3625   */
3626 }
3627
3628 void
3629 context_exitMacroCache (void)
3630 {
3631   if (gc.kind != CX_GLOBAL)
3632     {
3633       if (context_inMacro ()) 
3634         /* this is okay, file could end without newline in macro */
3635         {
3636           DPRINTF (("Still in macro: %s",
3637                     context_unparse ()));
3638           context_exitFunction ();
3639         }
3640       else
3641         {
3642           llcontbug (message ("context_exitMacroCache: outside global scope: %q", 
3643                               context_unparse ()));
3644           gc.kind = CX_GLOBAL; 
3645         }
3646     }
3647
3648   /*
3649   ** no longer valid here
3650   ** if (gc.insuppressregion)
3651   **   {
3652   **     gc.insuppressregion = FALSE;
3653   **     llerror ("File ended in ignore errors region, possible missing @");
3654   **   }
3655   */
3656
3657   gc.cont.glob = TRUE;
3658 }
3659
3660 void
3661 context_saveLocation (void)
3662 {
3663   /* was llassert (fileloc_isUndefined (gc.saveloc)) */
3664   fileloc_free (gc.saveloc);
3665   gc.saveloc = fileloc_copy (g_currentloc);
3666 }
3667
3668 fileloc
3669 context_getSaveLocation (void)
3670 {
3671   fileloc fl = gc.saveloc;
3672   gc.saveloc = fileloc_undefined;
3673   return fl;
3674 }
3675
3676 /*@observer@*/ cstring
3677 context_inFunctionName (void)
3678 {
3679   if (gc.kind == CX_FUNCTION
3680       || gc.kind == CX_MACROFCN || gc.kind == CX_UNKNOWNMACRO 
3681       || gc.kind == CX_MACROCONST 
3682       || gc.kind == CX_ITERDEF || gc.kind == CX_ITEREND)
3683     {
3684       return (uentry_rawName (gc.cont.fcn));
3685     }
3686   else
3687     {
3688       llcontbuglit ("context_inFunctionName: not in function");
3689       return (cstring_undefined);
3690     }
3691 }
3692
3693 void
3694 context_userSetFlag (flagcode f, bool b)
3695 {
3696   DPRINTF (("set flag: %s / %s", 
3697             flagcode_unparse (f),
3698             bool_unparse (context_getFlag (f))));
3699
3700   if (f == FLG_NEVERINCLUDE && b)
3701     {
3702       if (gc.flags[FLG_EXPORTHEADER])
3703         {
3704           llerror_flagWarning 
3705             (cstring_makeLiteral
3706              ("Setting +neverinclude after +exportheader.  "
3707               "Turning off exportheader, since headers are not checked "
3708               "when +neverinclude is used."));
3709
3710           gc.flags[FLG_EXPORTHEADER] = FALSE;
3711         }
3712     }
3713   else 
3714     {
3715       if (f == FLG_EXPORTHEADER && b)
3716         {
3717           if (gc.flags[FLG_NEVERINCLUDE])
3718             {
3719               llerror_flagWarning
3720                 (cstring_makeLiteral
3721                  ("Setting +exportheader after +neverinclude.  "
3722                   "Not setting exportheader, since headers are not checked "
3723                   "when +neverinclude is used."));
3724               gc.flags[FLG_EXPORTHEADER] = FALSE;
3725               return;
3726             }
3727         }
3728     }
3729   
3730   if (context_getFlag (FLG_WARNFLAGS) && f != FLG_NOF && f != FLG_OPTF)
3731     {
3732       bool lastsetting = context_getFlag (f);
3733       
3734       if (bool_equal (lastsetting, b)
3735           && !flagcode_isSpecialFlag (f) 
3736           && !flagcode_isIdemFlag (f)
3737           && !flagcode_hasArgument (f))
3738         {
3739           llerror_flagWarning 
3740             (message ("Setting %s%s redundant with current value", 
3741                       cstring_makeLiteralTemp (b ? "+" : "-"),
3742                       flagcode_unparse (f)));
3743         }
3744     }
3745
3746   if (flagcode_isWarnUseFlag (f) && b)
3747     {
3748       if (!context_getFlag (FLG_WARNUSE))
3749         {
3750           llerror_flagWarning
3751             (message ("Flag +%s is canceled by -warnuse",
3752                       flagcode_unparse (f)));
3753         }
3754     }
3755
3756
3757   if (flagcode_isLibraryFlag (f)) 
3758     {
3759       if (gc.library != FLG_ANSILIB
3760           && gc.library != f)
3761         {
3762           llerror_flagWarning 
3763             (message ("Selecting library %s after library %s was "
3764                       "selected (only one library may be used)",
3765                       flagcode_unparse (f),
3766                       flagcode_unparse (gc.library)));
3767         }
3768       
3769       if (f == FLG_UNIXLIB)
3770         {
3771           if (context_getFlag (FLG_WARNUNIXLIB))
3772             {
3773               llerror_flagWarning
3774                 (cstring_makeLiteral
3775                  ("Selecting unix library.  Unix library is "
3776                   "based on the Single Unix Specification, Version 2.  Not all "
3777                   "Unix implementations are consistend with this specification. "
3778                   "Use -warnunixlib to suppress this message."));
3779             }
3780         }
3781       
3782       gc.library = f;
3783     }
3784   
3785   if (flagcode_isNameChecksFlag (f) && b && !context_maybeSet (FLG_NAMECHECKS))
3786     {
3787       llerror_flagWarning
3788         (message
3789          ("Setting +%s will not produce warnings with -namechecks. "
3790           "Must set +namechecks also.",
3791           flagcode_unparse (f)));
3792     }
3793   
3794   gc.setGlobally[f] = TRUE;
3795   context_setFlag (f, b, g_currentloc);
3796 }
3797
3798 void
3799 context_fileSetFlag (flagcode f, ynm set, fileloc loc)
3800 {
3801   if (!gc.savedFlags)
3802     {
3803       context_saveFlagSettings ();
3804     }
3805
3806   if (ynm_isOff (set))
3807     {
3808       context_setFlagAux (f, FALSE, TRUE, FALSE, loc);
3809     }
3810   else if (ynm_isOn (set))
3811     {
3812       context_setFlagAux (f, TRUE, TRUE, FALSE, loc);
3813       gc.setLocally[f] = TRUE;
3814     }
3815   else
3816     {
3817       context_restoreFlag (f, loc);
3818     }
3819 }
3820
3821 static void
3822 context_restoreFlag (flagcode f, fileloc loc)
3823 {
3824   if (!gc.savedFlags)
3825     {
3826       voptgenerror 
3827         (FLG_SYNTAX,
3828          message ("Attempt to restore flag %s when no file scope flags "
3829                   "have been set.",
3830                   flagcode_unparse (f)),
3831          loc);
3832     }
3833   else
3834     {
3835       context_addFlagMarker (f, MAYBE, loc);
3836       context_setFlagAux (f, gc.saveflags[f], FALSE, TRUE, loc);
3837     }
3838
3839   }
3840
3841 static void
3842 context_setFlag (flagcode f, bool b, fileloc loc)
3843 {
3844   context_setFlagAux (f, b, FALSE, FALSE, loc);
3845 }
3846
3847 void
3848 context_setFlagTemp (flagcode f, bool b)
3849 {
3850   DPRINTF (("Set flag temp: %s / %s", flagcode_unparse (f), bool_unparse (b)));
3851   gc.flags[f] = b;
3852 }
3853
3854 /*@notfunction@*/
3855 # define DOSET(ff,b) \
3856    do { if (inFile) { gc.setLocally[ff] = TRUE; \
3857                       context_addFlagMarker (ff, ynm_fromBool (b), loc); } \
3858         DPRINTF (("set flag: %s / %s", flagcode_unparse (ff), bool_unparse (b))); \
3859         gc.flags[ff] = b; } while (FALSE)
3860
3861 static void
3862 context_setFlagAux (flagcode f, bool b, bool inFile, 
3863                     /*@unused@*/ bool isRestore, fileloc loc)
3864 {
3865   DPRINTF (("Set flag: %s / %s", flagcode_unparse (f), bool_unparse (b)));
3866
3867   /*
3868   ** Removed test for special flags.
3869   */
3870
3871   if (flagcode_isIdemFlag (f))
3872     {
3873       DOSET (f, TRUE);
3874     }
3875   else
3876     {
3877       DOSET (f, b);
3878     }
3879
3880   if (f >= FLG_ITS4MOSTRISKY && f <= FLG_ITS4LOWRISK)
3881     {
3882       if (b) /* Turing higher level on, turns on all lower levels */
3883         {
3884           switch (f)
3885             {
3886             case FLG_ITS4MOSTRISKY:
3887               DOSET (FLG_ITS4VERYRISKY, b);
3888               /*@fallthrough@*/ 
3889             case FLG_ITS4VERYRISKY:
3890               DOSET (FLG_ITS4RISKY, b);
3891               /*@fallthrough@*/ 
3892             case FLG_ITS4RISKY:
3893               DOSET (FLG_ITS4MODERATERISK, b);
3894               /*@fallthrough@*/ 
3895             case FLG_ITS4MODERATERISK:
3896               DOSET (FLG_ITS4LOWRISK, b);
3897               /*@fallthrough@*/ 
3898             case FLG_ITS4LOWRISK:
3899               break;
3900               BADDEFAULT;
3901             }
3902         }
3903       else /* Turning level off, turns off all higher levels */
3904         {
3905           switch (f)
3906             {
3907             case FLG_ITS4LOWRISK:
3908               DOSET (FLG_ITS4MODERATERISK, b);
3909               /*@fallthrough@*/ 
3910             case FLG_ITS4MODERATERISK:
3911               DOSET (FLG_ITS4RISKY, b);
3912               /*@fallthrough@*/ 
3913             case FLG_ITS4RISKY:
3914               DOSET (FLG_ITS4VERYRISKY, b);
3915               /*@fallthrough@*/ 
3916             case FLG_ITS4VERYRISKY:
3917               DOSET (FLG_ITS4MOSTRISKY, b);
3918               /*@fallthrough@*/ 
3919             case FLG_ITS4MOSTRISKY:
3920               break;
3921               BADDEFAULT;
3922             }
3923         }
3924     }
3925   
3926   switch (f)
3927     {     
3928     case FLG_MESSAGESTREAMSTDOUT:
3929       g_messagestream = stdout;
3930       break;
3931     case FLG_MESSAGESTREAMSTDERR:
3932       g_messagestream = stderr;
3933       break;
3934     case FLG_WARNINGSTREAMSTDOUT:
3935       g_warningstream = stdout;
3936       break;
3937     case FLG_WARNINGSTREAMSTDERR:
3938       g_warningstream = stderr;
3939       break;
3940     case FLG_ERRORSTREAMSTDOUT:
3941       g_errorstream = stdout;
3942       break;
3943     case FLG_ERRORSTREAMSTDERR:
3944       g_errorstream = stderr;
3945       break;
3946     case FLG_ALLEMPTY:
3947       DOSET (FLG_ALLEMPTY, b);
3948       DOSET (FLG_IFEMPTY, b);
3949       DOSET (FLG_WHILEEMPTY, b);
3950       DOSET (FLG_FOREMPTY, b);
3951       break;
3952     case FLG_PREDBOOL:
3953       DOSET (FLG_PREDBOOL, b);
3954       DOSET (FLG_PREDBOOLINT, b);
3955       DOSET (FLG_PREDBOOLPTR, b);
3956       DOSET (FLG_PREDBOOLOTHERS, b);
3957       break;
3958     case FLG_GLOBALIAS:
3959       DOSET (FLG_CHECKSTRICTGLOBALIAS, b);
3960       DOSET (FLG_CHECKEDGLOBALIAS, b);
3961       DOSET (FLG_CHECKMODGLOBALIAS, b);
3962       DOSET (FLG_UNCHECKEDGLOBALIAS, b);
3963       break;
3964     case FLG_ALLBLOCK:
3965       DOSET (FLG_ALLBLOCK, b);
3966       DOSET (FLG_IFBLOCK, b);
3967       DOSET (FLG_WHILEBLOCK, b);
3968       DOSET (FLG_FORBLOCK, b);
3969       break;
3970     case FLG_GRAMMAR:
3971       if (b)
3972         {
3973           yydebug = 1;
3974           mtdebug = 1;
3975         }
3976       else
3977         {
3978           yydebug = 0;
3979           mtdebug = 0;
3980         }
3981       
3982       DOSET (FLG_GRAMMAR, b);
3983       break;
3984     case FLG_CODEIMPONLY:
3985       DOSET (FLG_CODEIMPONLY, b);
3986       DOSET (FLG_GLOBIMPONLY, b);
3987       DOSET (FLG_RETIMPONLY, b);
3988       DOSET (FLG_STRUCTIMPONLY, b);
3989       break;
3990     case FLG_SPECALLIMPONLY:
3991       DOSET (FLG_SPECALLIMPONLY, b);
3992       DOSET (FLG_SPECGLOBIMPONLY, b);
3993       DOSET (FLG_SPECRETIMPONLY, b);
3994       DOSET (FLG_SPECSTRUCTIMPONLY, b);
3995       break;
3996     case FLG_ALLIMPONLY:
3997       DOSET (FLG_ALLIMPONLY, b);
3998       DOSET (FLG_GLOBIMPONLY, b);
3999       DOSET (FLG_RETIMPONLY, b);
4000       DOSET (FLG_STRUCTIMPONLY, b);
4001       DOSET (FLG_SPECGLOBIMPONLY, b);
4002       DOSET (FLG_SPECRETIMPONLY, b);
4003       DOSET (FLG_SPECSTRUCTIMPONLY, b);
4004       break;
4005     case FLG_ANSI89LIMITS: 
4006       DOSET (FLG_ANSI89LIMITS, b);
4007       DOSET (FLG_CONTROLNESTDEPTH, b);
4008       DOSET (FLG_STRINGLITERALLEN, b);
4009       DOSET (FLG_INCLUDENEST, b);
4010       DOSET (FLG_NUMSTRUCTFIELDS, b);
4011       DOSET (FLG_NUMENUMMEMBERS, b);
4012       
4013       if (b)
4014         {
4015           context_setValue (FLG_CONTROLNESTDEPTH, ANSI89_CONTROLNESTDEPTH);
4016           context_setValue (FLG_STRINGLITERALLEN, ANSI89_STRINGLITERALLEN);
4017           context_setValue (FLG_INCLUDENEST, ANSI89_INCLUDENEST);
4018           context_setValue (FLG_NUMSTRUCTFIELDS, ANSI89_NUMSTRUCTFIELDS);
4019           context_setValue (FLG_NUMENUMMEMBERS, ANSI89_NUMENUMMEMBERS);
4020           context_setValue (FLG_EXTERNALNAMELEN, ANSI89_EXTERNALNAMELEN);
4021           context_setValue (FLG_INTERNALNAMELEN, ANSI89_INTERNALNAMELEN);
4022         }
4023       break;
4024     case FLG_ISO99LIMITS: 
4025       DOSET (FLG_ISO99LIMITS, b);
4026       DOSET (FLG_CONTROLNESTDEPTH, b);
4027       DOSET (FLG_STRINGLITERALLEN, b);
4028       DOSET (FLG_INCLUDENEST, b);
4029       DOSET (FLG_NUMSTRUCTFIELDS, b);
4030       DOSET (FLG_NUMENUMMEMBERS, b);
4031       
4032       if (b)
4033         {
4034           context_setValue (FLG_CONTROLNESTDEPTH, ISO99_CONTROLNESTDEPTH);
4035           context_setValue (FLG_STRINGLITERALLEN, ISO99_STRINGLITERALLEN);
4036           context_setValue (FLG_INCLUDENEST, ISO99_INCLUDENEST);
4037           context_setValue (FLG_NUMSTRUCTFIELDS, ISO99_NUMSTRUCTFIELDS);
4038           context_setValue (FLG_NUMENUMMEMBERS, ISO99_NUMENUMMEMBERS);
4039           context_setValue (FLG_EXTERNALNAMELEN, ISO99_EXTERNALNAMELEN);
4040           context_setValue (FLG_INTERNALNAMELEN, ISO99_INTERNALNAMELEN);
4041         }
4042       break;
4043     case FLG_EXTERNALNAMELEN:
4044       DOSET (FLG_DISTINCTEXTERNALNAMES, TRUE);
4045       DOSET (FLG_EXTERNALNAMELEN, TRUE);
4046       break;
4047     case FLG_INTERNALNAMELEN:
4048       DOSET (FLG_DISTINCTINTERNALNAMES, TRUE);
4049       DOSET (FLG_INTERNALNAMELEN, TRUE);
4050       break;
4051     case FLG_EXTERNALNAMECASEINSENSITIVE:
4052       DOSET (FLG_EXTERNALNAMECASEINSENSITIVE, b);
4053       
4054       if (b && !gc.flags[FLG_DISTINCTEXTERNALNAMES])
4055         {
4056           DOSET (FLG_DISTINCTEXTERNALNAMES, TRUE);
4057           context_setValue (FLG_EXTERNALNAMELEN, 0);
4058         }
4059       break;
4060     case FLG_INTERNALNAMECASEINSENSITIVE:
4061       DOSET (FLG_INTERNALNAMECASEINSENSITIVE, b);
4062       
4063       if (b && !gc.flags[FLG_DISTINCTINTERNALNAMES])
4064         {
4065           DOSET (FLG_DISTINCTINTERNALNAMES, TRUE);
4066           context_setValue (FLG_INTERNALNAMELEN, 0);
4067         }
4068       break;
4069     case FLG_INTERNALNAMELOOKALIKE:
4070       DOSET (FLG_INTERNALNAMELOOKALIKE, b);
4071       
4072       if (b && !gc.flags[FLG_DISTINCTINTERNALNAMES])
4073         {
4074           DOSET (FLG_DISTINCTINTERNALNAMES, TRUE);
4075           context_setValue (FLG_INTERNALNAMELEN, 0);
4076         }
4077       break;
4078     case FLG_MODUNSPEC:
4079       DOSET (FLG_MODNOMODS, b);
4080       DOSET (FLG_MODGLOBSUNSPEC, b);
4081       DOSET (FLG_MODSTRICTGLOBSUNSPEC, b);
4082       break;
4083     case FLG_EXPORTANY: 
4084       DOSET (FLG_EXPORTVAR, b);
4085       DOSET (FLG_EXPORTFCN, b);
4086       DOSET (FLG_EXPORTTYPE, b);
4087       DOSET (FLG_EXPORTMACRO, b);
4088       DOSET (FLG_EXPORTCONST, b);
4089       gc.anyExports = TRUE;
4090       break;
4091     case FLG_REPEXPOSE:
4092       DOSET (FLG_RETEXPOSE, b); 
4093       DOSET (FLG_ASSIGNEXPOSE, b); 
4094       DOSET (FLG_CASTEXPOSE, b); 
4095       break;
4096     case FLG_RETVAL:
4097       DOSET (FLG_RETVALBOOL, b);
4098       DOSET (FLG_RETVALINT, b);
4099       DOSET (FLG_RETVALOTHER, b);
4100       break;
4101     case FLG_PARTIAL:
4102       if (b)
4103         {
4104           DOSET (FLG_EXPORTLOCAL, FALSE);
4105           DOSET (FLG_DECLUNDEF, FALSE);
4106           DOSET (FLG_SPECUNDEF, FALSE);
4107           DOSET (FLG_TOPUNUSED, FALSE);
4108         }
4109       break;
4110     case FLG_DEEPBREAK:
4111       DOSET (FLG_LOOPLOOPBREAK, b);
4112       DOSET (FLG_LOOPSWITCHBREAK, b);
4113       DOSET (FLG_SWITCHLOOPBREAK, b);
4114       DOSET (FLG_SWITCHSWITCHBREAK, b);
4115       DOSET (FLG_LOOPLOOPCONTINUE, b);
4116       DOSET (FLG_DEEPBREAK, b);
4117       break;
4118     case FLG_LOOPEXEC:
4119       DOSET (FLG_FORLOOPEXEC, b);
4120       DOSET (FLG_WHILELOOPEXEC, b);
4121       DOSET (FLG_ITERLOOPEXEC, b);
4122       break;
4123     case FLG_ACCESSALL:
4124       DOSET (FLG_ACCESSMODULE, b);
4125       DOSET (FLG_ACCESSFILE, b);
4126       DOSET (FLG_ACCESSCZECH, b);
4127       break;
4128     case FLG_ALLMACROS:
4129       DOSET (FLG_ALLMACROS, b);
4130       DOSET (FLG_FCNMACROS, b);
4131       DOSET (FLG_CONSTMACROS, b);
4132       break;      
4133     case FLG_BOUNDS:
4134       DOSET (FLG_BOUNDSREAD, b);
4135       DOSET (FLG_BOUNDSWRITE, b);
4136       DOSET (FLG_LIKELYBOUNDSREAD, b);
4137       DOSET (FLG_LIKELYBOUNDSWRITE, b);
4138       break;
4139     case FLG_BOUNDSREAD:
4140       DOSET (FLG_LIKELYBOUNDSREAD, b);
4141       break;
4142     case FLG_BOUNDSWRITE:
4143       DOSET (FLG_LIKELYBOUNDSWRITE, b);
4144       break;
4145     case FLG_LIKELYBOUNDS:
4146       DOSET (FLG_LIKELYBOUNDSREAD, b);
4147       DOSET (FLG_LIKELYBOUNDSWRITE, b);
4148       break;
4149       
4150     case FLG_CZECH:
4151       if (b) { DOSET (FLG_ACCESSCZECH, b); }
4152       DOSET (FLG_CZECHFUNCTIONS, b);
4153       DOSET (FLG_CZECHVARS, b);
4154       DOSET (FLG_CZECHCONSTANTS, b);
4155       DOSET (FLG_CZECHTYPES, b);
4156       break;
4157     case FLG_SLOVAK:
4158       if (b) { DOSET (FLG_ACCESSSLOVAK, b); }
4159       DOSET (FLG_SLOVAKFUNCTIONS, b);
4160       DOSET (FLG_SLOVAKVARS, b);
4161       DOSET (FLG_SLOVAKCONSTANTS, b);
4162       DOSET (FLG_SLOVAKTYPES, b);
4163       break;
4164     case FLG_CZECHOSLOVAK:
4165       if (b) { DOSET (FLG_ACCESSCZECHOSLOVAK, b); }
4166       DOSET (FLG_CZECHOSLOVAKFUNCTIONS, b);
4167       DOSET (FLG_CZECHOSLOVAKVARS, b);
4168       DOSET (FLG_CZECHOSLOVAKCONSTANTS, b);
4169       DOSET (FLG_CZECHOSLOVAKTYPES, b);
4170       break;
4171     case FLG_NULL:
4172       DOSET (FLG_NULLSTATE, b);
4173       DOSET (FLG_NULLDEREF, b);
4174       DOSET (FLG_NULLASSIGN, b);
4175       DOSET (FLG_NULLPASS, b);
4176       DOSET (FLG_NULLRET, b);
4177       break;
4178     case FLG_MUSTFREE:
4179       DOSET (FLG_MUSTFREEONLY, b);
4180       DOSET (FLG_MUSTFREEFRESH, b);
4181       break;
4182     case FLG_MEMCHECKS:
4183       DOSET (FLG_NULLSTATE, b);
4184       DOSET (FLG_NULLDEREF, b);
4185       DOSET (FLG_NULLASSIGN, b);
4186       DOSET (FLG_NULLPASS, b);
4187       DOSET (FLG_NULLRET, b);
4188       DOSET (FLG_COMPDEF, b);
4189       DOSET (FLG_COMPMEMPASS, b);
4190       DOSET (FLG_UNIONDEF, b);
4191       DOSET (FLG_MEMTRANS, b);
4192       DOSET (FLG_USERELEASED, b);
4193       DOSET (FLG_ALIASUNIQUE, b);
4194       DOSET (FLG_MAYALIASUNIQUE, b);
4195       DOSET (FLG_MUSTFREEONLY, b);
4196       DOSET (FLG_MUSTFREEFRESH, b);
4197       DOSET (FLG_MUSTDEFINE, b);
4198       DOSET (FLG_GLOBSTATE, b); 
4199       DOSET (FLG_COMPDESTROY, b);
4200       DOSET (FLG_MUSTNOTALIAS, b);
4201       DOSET (FLG_MEMIMPLICIT, b);
4202       DOSET (FLG_BRANCHSTATE, b); 
4203       /*@fallthrough@*/ /* also sets memtrans flags */
4204     case FLG_MEMTRANS:
4205       DOSET (FLG_MEMTRANS, b);
4206       DOSET (FLG_EXPOSETRANS, b);
4207       DOSET (FLG_OBSERVERTRANS, b);
4208       DOSET (FLG_DEPENDENTTRANS, b);
4209       DOSET (FLG_NEWREFTRANS, b);
4210       DOSET (FLG_ONLYTRANS, b);
4211       DOSET (FLG_OWNEDTRANS, b);
4212       DOSET (FLG_FRESHTRANS, b);
4213       DOSET (FLG_SHAREDTRANS, b);
4214       DOSET (FLG_TEMPTRANS, b);
4215       DOSET (FLG_KEPTTRANS, b);
4216       DOSET (FLG_REFCOUNTTRANS, b);
4217       DOSET (FLG_STATICTRANS, b);
4218       DOSET (FLG_UNKNOWNTRANS, b);
4219       DOSET (FLG_KEEPTRANS, b);
4220       DOSET (FLG_IMMEDIATETRANS, b);
4221       break;
4222       
4223     default:
4224       break;
4225     }
4226
4227   if (b && !gc.anyExports
4228       && (f == FLG_EXPORTVAR || f == FLG_EXPORTFCN
4229           || f == FLG_EXPORTTYPE || f == FLG_EXPORTMACRO
4230           || f == FLG_EXPORTCONST
4231           || f == FLG_EXPORTANY))
4232     {
4233       gc.anyExports = TRUE;
4234     }
4235 }
4236
4237 bool 
4238 context_maybeSet (flagcode d)
4239 {
4240   return (gc.flags[d] || gc.setLocally[d]);
4241 }
4242
4243 bool
4244 context_getFlag (flagcode d)
4245 {
4246   return (gc.flags[d]);
4247 }
4248
4249 bool
4250 context_flagOn (flagcode f, fileloc loc)
4251 {
4252   return (!context_suppressFlagMsg (f, loc));
4253 }
4254
4255 static void context_saveFlagSettings (void)
4256 {
4257   gc.savedFlags = TRUE;
4258   llassert (sizeof (gc.saveflags) == sizeof (gc.flags));
4259   memcpy (gc.saveflags, gc.flags, sizeof (gc.flags));
4260 }
4261
4262 static void context_restoreFlagSettings (void)
4263 {
4264   llassert (sizeof (gc.saveflags) == sizeof (gc.flags));
4265   memcpy (gc.flags, gc.saveflags, sizeof (gc.flags));
4266   gc.savedFlags = FALSE;
4267 }
4268
4269 void context_setFilename (fileId fid, int lineno) 
4270    /*@globals fileloc g_currentloc;@*/
4271    /*@modifies g_currentloc@*/
4272 {
4273   if (fileId_baseEqual (currentFile (), fid))
4274     {
4275       setLine (lineno);
4276       return;
4277     }
4278   else
4279     {
4280       fileloc_setColumn (g_currentloc, 0);
4281
4282       if (fileloc_isSpecialFile (g_currentloc))
4283         {
4284           gc.inDerivedFile = TRUE;
4285         }
4286
4287       if (filelocStack_popPushFile (gc.locstack, g_currentloc))
4288         {
4289           int maxdepth = context_getValue (FLG_INCLUDENEST);
4290
4291           if (filelocStack_size (gc.locstack) > maxdepth)
4292             {
4293               int depth = filelocStack_includeDepth (gc.locstack);
4294               
4295               if (depth > maxdepth)
4296                 {
4297                   if (optgenerror 
4298                       (FLG_INCLUDENEST,
4299                        message ("Maximum include nesting depth "
4300                                 "(%d, current depth %d) exceeded",
4301                                 maxdepth,
4302                                 depth),
4303                        filelocStack_nextTop (gc.locstack)))
4304                     {
4305                       filelocStack_printIncludes (gc.locstack);
4306                     }
4307                 }
4308             }
4309         }
4310       
4311       g_currentloc = fileloc_create (fid, lineno, 1);
4312       gc.inheader = fileId_isHeader (currentFile ());
4313
4314       context_enterFileAux ();
4315     }
4316 }
4317
4318 void context_enterIterDef (/*@observer@*/ uentry le)
4319 {
4320   context_enterMacro (le);
4321   gc.acct = typeIdSet_subtract (gc.facct, gc.nacct);
4322   gc.kind = CX_ITERDEF;
4323 }
4324
4325 void context_enterIterEnd (/*@observer@*/ uentry le)
4326 {
4327   context_enterMacro (le);
4328   gc.kind = CX_ITEREND;
4329 }
4330
4331 void 
4332 context_destroyMod (void) 
4333    /*@globals killed gc@*/
4334 {
4335   int i;
4336   setCodePoint ();
4337   ctype_destroyMod ();
4338   /*
4339   setCodePoint ();
4340   usymtab_free ();
4341   setCodePoint ();
4342   */
4343
4344   fileTable_free (gc.ftab);
4345   gc.ftab = fileTable_undefined;
4346
4347   filelocStack_free (gc.locstack);
4348   setCodePoint ();
4349
4350   macrocache_free (gc.mc);
4351
4352   /* evans 2002-07-12: not reported because of reldef */
4353   for (i = 0; i < gc.nmods; i++)
4354     {
4355       cstring_free (gc.moduleaccess[i].file);
4356     }
4357
4358   sfree (gc.moduleaccess);
4359   setCodePoint ();
4360
4361   fileloc_free (gc.saveloc); gc.saveloc = fileloc_undefined;
4362   fileloc_free (gc.pushloc); gc.pushloc = fileloc_undefined;
4363
4364   setCodePoint ();
4365   sRefSetList_free (gc.modrecs);
4366   setCodePoint ();
4367   flagMarkerList_free (gc.markers); 
4368   setCodePoint ();
4369   messageLog_free (gc.msgLog);
4370   setCodePoint ();
4371   clauseStack_free (gc.clauses);
4372   setCodePoint ();
4373   
4374   cstring_free (gc.msgAnnote);
4375   globSet_free (gc.globs_used);
4376   metaStateTable_free (gc.stateTable);
4377   annotationTable_free (gc.annotTable);
4378
4379   
4380 }
4381
4382 /*
4383 ** Flag shortcuts
4384 */
4385
4386 bool context_msgBoolInt (void)
4387 {
4388   return context_flagOn (FLG_BOOLINT, g_currentloc);
4389 }
4390
4391 bool context_msgCharInt (void)
4392 {
4393   return context_flagOn (FLG_CHARINT, g_currentloc);
4394 }
4395
4396 bool context_msgEnumInt (void)
4397 {
4398   return context_flagOn (FLG_ENUMINT, g_currentloc);
4399 }
4400
4401 bool context_msgLongInt (void)
4402 {
4403   return context_flagOn (FLG_LONGINT, g_currentloc);
4404 }
4405
4406 bool context_msgShortInt (void)
4407 {
4408   return context_flagOn (FLG_SHORTINT, g_currentloc);
4409 }
4410
4411 bool context_msgPointerArith (void) 
4412 {
4413   return context_flagOn (FLG_POINTERARITH, g_currentloc);
4414 }
4415
4416 bool context_msgStrictOps (void) 
4417 {
4418   return context_flagOn (FLG_STRICTOPS, g_currentloc);
4419 }
4420
4421 bool context_msgLh (void)           
4422 {
4423   return gc.flags [FLG_DOLH];
4424 }
4425
4426 void context_pushLoc (void) 
4427 {
4428   fileloc_free (gc.pushloc);
4429   gc.pushloc = gc.saveloc;
4430   gc.saveloc = fileloc_undefined;
4431 }
4432
4433 void context_popLoc (void) 
4434 {
4435   gc.saveloc = fileloc_update (gc.saveloc, gc.pushloc);
4436 }
4437
4438 bool context_inGlobalScope (void)
4439 {
4440   return (usymtab_inFileScope() || usymtab_inGlobalScope ());
4441 }
4442
4443 bool context_inInnerScope (void)
4444 {
4445   return (gc.kind == CX_INNER);
4446 }
4447
4448 void context_setProtectVars (void)
4449 {
4450   gc.protectVars = TRUE;
4451 }
4452
4453 bool context_anyErrors (void)
4454 {
4455   return (gc.numerrors > 0);
4456 }
4457
4458 void context_hasError (void)
4459 {
4460   gc.numerrors++;
4461   DPRINTF (("num errors: %d", gc.numerrors));
4462 }
4463
4464 int context_numErrors (void)
4465 {
4466   return gc.numerrors;
4467 }
4468
4469 bool context_neednl (void)
4470 {
4471   return gc.neednl;
4472 }
4473
4474 void context_setNeednl (void)
4475 {
4476   gc.neednl = TRUE;
4477 }
4478
4479 int context_getExpect (void)
4480 {
4481   return (context_getValue (FLG_EXPECT));
4482 }
4483
4484 int context_getLCLExpect (void)
4485 {
4486   return (context_getValue (FLG_LCLEXPECT));
4487 }
4488
4489 int context_getLimit (void)
4490 {
4491   return (context_getValue (FLG_LIMIT));
4492 }
4493
4494 bool context_unlimitedMessages (void)
4495 {
4496   return (context_getLimit () < 0);
4497 }
4498
4499 void context_releaseVars (void)
4500 {
4501   llassert (gc.protectVars);
4502   gc.protectVars = FALSE;
4503 }
4504
4505 void context_sizeofReleaseVars (void)
4506 {
4507   /* If there is a nested sizeof, this might not hold:
4508      llassert (gc.protectVars);
4509      */
4510
4511   gc.protectVars = FALSE;
4512 }
4513
4514 bool context_inProtectVars (void)
4515 {
4516   return (gc.protectVars);
4517 }
4518
4519 void context_hideShowscan (void) 
4520 {
4521   gc.flags[FLG_SHOWSCAN] = FALSE;
4522 }
4523
4524 void context_unhideShowscan (void)
4525 {
4526   gc.flags[FLG_SHOWSCAN] = TRUE;
4527 }
4528
4529 bool context_inHeader (void)
4530 {
4531   return (gc.inheader);
4532 }
4533
4534 fileTable context_fileTable (void)
4535 {
4536   return gc.ftab;
4537 }
4538
4539 cstring context_tmpdir (void)
4540 {
4541   return (context_getString (FLG_TMPDIR));
4542 }
4543
4544 messageLog context_messageLog (void)
4545 {
4546   return gc.msgLog;
4547 }
4548
4549 bool context_inMacroFunction (void)
4550 {
4551   return (gc.kind == CX_MACROFCN);
4552 }
4553
4554 bool context_inMacroConstant (void)
4555 {   
4556   return (gc.kind == CX_MACROCONST);
4557 }
4558
4559 bool context_inUnknownMacro (void)
4560 {   
4561   return (gc.kind == CX_UNKNOWNMACRO);
4562 }
4563
4564 void context_setShownFunction (void)
4565 {
4566   gc.showfunction = FALSE;
4567 }
4568
4569 bool context_doDump (void)
4570 {   
4571   return cstring_isNonEmpty (context_getString (FLG_DUMP));
4572 }
4573
4574 bool context_doMerge (void)
4575 {
4576   return cstring_isNonEmpty (context_getString (FLG_MERGE));
4577 }
4578
4579 cstring context_getDump (void)
4580 {           
4581   return context_getString (FLG_DUMP);
4582 }
4583
4584 cstring context_getMerge (void)
4585 {
4586   return context_getString (FLG_MERGE);
4587 }
4588
4589 bool context_inLCLLib (void)
4590 {   
4591   return (gc.kind == CX_LCLLIB);
4592 }
4593
4594
4595 /*drl add these 3/5/2003*/
4596 static bool inSizeof = FALSE;
4597
4598 bool context_inSizeof (void)
4599 {
4600   return (inSizeof);
4601 }
4602
4603 void context_enterSizeof (void)
4604 {
4605   DPRINTF((message("context_enterSizeof ") ) );
4606   inSizeof = TRUE;
4607 }
4608
4609 void context_leaveSizeof (void)
4610
4611   DPRINTF((message("context_leaveSizeof ") ));
4612   inSizeof = FALSE;
4613 }
4614 /*end function added 3/5/2003*/
4615
4616
4617 bool context_inImport (void)
4618 {
4619   return (gc.inimport);
4620 }
4621
4622 void context_enterImport (void)
4623
4624   gc.inimport = TRUE;
4625 }
4626
4627 void context_leaveImport (void)
4628
4629   gc.inimport = FALSE;
4630 }
4631
4632 bool context_inMacro (void) 
4633 {
4634   return (gc.kind == CX_MACROFCN || gc.kind == CX_MACROCONST 
4635           || gc.kind == CX_UNKNOWNMACRO
4636           || gc.kind == CX_ITERDEF || gc.kind == CX_ITEREND);
4637 }
4638
4639 bool context_inIterDef (void)
4640 {
4641   return (gc.kind == CX_ITERDEF);
4642 }
4643
4644 bool context_inIterEnd (void)
4645 {
4646   return (gc.kind == CX_ITEREND);
4647 }
4648
4649 int context_getLinesProcessed (void)    
4650 {
4651   return (gc.linesprocessed);
4652 }
4653
4654 int context_getSpecLinesProcessed (void)    
4655 {
4656   return (gc.speclinesprocessed);
4657 }
4658
4659 void context_processedSpecLine (void)
4660 {
4661   gc.speclinesprocessed++;
4662 }
4663
4664 void context_resetSpecLines (void)    
4665 {
4666   gc.speclinesprocessed = 0;
4667
4668 }
4669
4670 bool context_inGlobalContext (void)
4671 {
4672   return (gc.kind == CX_GLOBAL);
4673 }
4674
4675 static void context_quietExitScopes (void)
4676 {
4677   /*
4678   ** Try to restore the global scope (after an error).
4679   */
4680
4681   while (!usymtab_inFileScope ())
4682     {
4683       usymtab_quietExitScope (g_currentloc);
4684     }
4685
4686   gc.cont.glob = TRUE;
4687   gc.kind = CX_GLOBAL;
4688 }
4689
4690 void context_checkGlobalScope (void)
4691 {
4692   if (gc.kind != CX_GLOBAL)
4693     {
4694       if (context_inMacro ())
4695         {
4696           ; /* evans 2001-10-14: Okay to be in a macro here! */ 
4697         }
4698       else
4699         {
4700           llcontbug (message ("Not in global scope as expected: %q", context_unparse ()));
4701           context_quietExitScopes ();
4702         }
4703     }
4704 }
4705
4706 void context_setFileId (fileId s)
4707 {
4708   g_currentloc = fileloc_updateFileId (g_currentloc, s); 
4709 }
4710
4711 bool context_setBoolName (void)
4712 {
4713   return (!cstring_equalLit (context_getString (FLG_BOOLTYPE),
4714                              DEFAULT_BOOLTYPE));
4715 }
4716
4717 cstring context_printBoolName (void)
4718 {
4719   if (context_setBoolName ()) 
4720     {
4721       return context_getBoolName ();
4722     }
4723   else
4724     {
4725       return cstring_makeLiteralTemp ("boolean");
4726     }
4727 }
4728
4729 cstring context_getBoolName (void)
4730 {
4731   return (context_getString (FLG_BOOLTYPE));
4732 }
4733
4734 cstring context_getFalseName (void)
4735 {
4736   return (context_getString (FLG_BOOLFALSE));
4737 }
4738
4739 cstring context_getTrueName (void)
4740 {
4741   return (context_getString (FLG_BOOLTRUE));
4742 }
4743
4744 cstring context_getLarchPath (void)
4745 {
4746   return (context_getString (FLG_LARCHPATH));
4747 }
4748
4749 cstring context_getLCLImportDir (void)
4750 {
4751   return (context_getString (FLG_LCLIMPORTDIR));
4752 }
4753
4754 static void context_setJustPopped (void)
4755 {
4756   gc.justpopped = TRUE;
4757 }
4758
4759 void context_clearJustPopped (void)
4760 {
4761   gc.justpopped = FALSE;
4762 }
4763
4764 bool context_justPopped (void)
4765 {
4766   return (gc.justpopped);
4767 }
4768
4769 void context_setMacroMissingParams (void)
4770 {
4771   gc.macroMissingParams = TRUE;
4772 }
4773
4774 void context_resetMacroMissingParams (void)
4775 {
4776   gc.macroMissingParams = FALSE;
4777 }
4778
4779 bool context_isMacroMissingParams (void)
4780 {
4781   return (gc.macroMissingParams);
4782 }
4783
4784 void context_showFilelocStack (void) 
4785 {
4786   filelocStack_printIncludes (gc.locstack);
4787 }
4788
4789 metaStateTable context_getMetaStateTable (void) 
4790 {
4791   return gc.stateTable;
4792 }
4793
4794 metaStateInfo context_lookupMetaStateInfo (cstring key)
4795 {
4796   return metaStateTable_lookup (gc.stateTable, key);
4797 }
4798
4799 /*@null@*/ annotationInfo context_lookupAnnotation (cstring annot) 
4800 {
4801   annotationInfo ainfo;
4802
4803   ainfo = annotationTable_lookup (gc.annotTable, annot);
4804
4805   return ainfo;
4806 }
4807
4808 void context_addAnnotation (annotationInfo ainfo)
4809 {
4810   if (annotationTable_contains (gc.annotTable, annotationInfo_getName (ainfo)))
4811     {
4812       voptgenerror 
4813         (FLG_SYNTAX,
4814          message ("Duplicate annotation declaration: %s", annotationInfo_getName (ainfo)),
4815          annotationInfo_getLoc (ainfo));
4816
4817       annotationInfo_free (ainfo);
4818     }
4819   else
4820     {
4821       annotationTable_insert (gc.annotTable, ainfo);
4822     }
4823 }
4824
4825 void context_addMetaState (cstring mname, metaStateInfo msinfo)
4826 {
4827   if (metaStateTable_contains (gc.stateTable, mname))
4828     {
4829       voptgenerror 
4830         (FLG_SYNTAX,
4831          message ("Duplicate metastate declaration: %s", mname),
4832          metaStateInfo_getLoc (msinfo));
4833       cstring_free (mname);
4834       metaStateInfo_free (msinfo);
4835     }
4836   else
4837     {
4838       DPRINTF (("Adding meta state: %s", mname));
4839       metaStateTable_insert (gc.stateTable, mname, msinfo); 
4840     }
4841 }
4842
4843 valueTable context_createValueTable (sRef s, stateInfo sinfo)
4844 {
4845   if (metaStateTable_size (gc.stateTable) > 0)
4846     {
4847       valueTable res = valueTable_create (metaStateTable_size (gc.stateTable));
4848       /* should use smaller value... */
4849       DPRINTF (("Value table for: %s", sRef_unparse (s)));
4850       
4851       metaStateTable_elements (gc.stateTable, msname, msi)
4852         {
4853           mtContextNode context = metaStateInfo_getContext (msi);
4854
4855           if (mtContextNode_matchesRefStrict (context, s))
4856             {
4857               DPRINTF (("Create: %s", metaStateInfo_unparse (msi)));
4858               llassert (cstring_equal (msname, metaStateInfo_getName (msi)));
4859               
4860               valueTable_insert 
4861                 (res,
4862                  cstring_copy (metaStateInfo_getName (msi)),
4863                  stateValue_createImplicit (metaStateInfo_getDefaultValue (msi, s), 
4864                                             stateInfo_copy (sinfo)));
4865             }
4866           else
4867             {
4868               DPRINTF (("No match: %s", metaStateInfo_unparse (msi)));
4869             }
4870         } 
4871       end_metaStateTable_elements ;
4872       
4873       stateInfo_free (sinfo);
4874       DPRINTF (("Value table: %s", valueTable_unparse (res)));
4875       return res;
4876     }
4877   else
4878     {
4879       stateInfo_free (sinfo);
4880       return valueTable_undefined;
4881     }
4882 }
4883
4884 valueTable context_createGlobalMarkerValueTable (stateInfo sinfo)
4885 {
4886   if (metaStateTable_size (gc.stateTable) > 0)
4887     {
4888       valueTable res = valueTable_create (metaStateTable_size (gc.stateTable));
4889       /* should use smaller value... */
4890       
4891       metaStateTable_elements (gc.stateTable, msname, msi)
4892         {
4893           /* only add global...*/
4894           DPRINTF (("Create: %s", metaStateInfo_unparse (msi)));
4895           llassert (cstring_equal (msname, metaStateInfo_getName (msi)));
4896           
4897           valueTable_insert (res,
4898                              cstring_copy (metaStateInfo_getName (msi)),
4899                              stateValue_create (metaStateInfo_getDefaultGlobalValue (msi),
4900                                                 stateInfo_copy (sinfo)));
4901         } 
4902       end_metaStateTable_elements ;
4903       
4904       stateInfo_free (sinfo);
4905       DPRINTF (("Value table: %s", valueTable_unparse (res)));
4906       return res;
4907     }
4908   else
4909     {
4910       stateInfo_free (sinfo);
4911       return valueTable_undefined;
4912     }
4913 }
4914
4915
4916 /*drl 12/30/01 these are some ugly functions that were added to facilitate struct annotations */
4917
4918
4919 /*drl added */
4920 static ctype lastStruct;
4921
4922 ctype context_setLastStruct (/*@returned@*/ ctype s) /*@globals lastStruct@*/
4923 {
4924   lastStruct = s;
4925   return s;
4926 }
4927
4928 ctype context_getLastStruct (/*@returned@*/ /*ctype s*/) /*@globals lastStruct@*/
4929 {
4930   return lastStruct;
4931 }
4932
4933 /*
4934 ** Why is this stuff in context.c?
4935 */
4936
4937 /*@unused@*/ static int sInfoNum = 0;
4938
4939
4940 struct getUe {
4941   /*@unused@*/  uentry ue;
4942   /*@unused@*/ sRef s;
4943 };
4944
4945 struct sInfo {
4946   /*@unused@*/ ctype ct;
4947   /*@unused@*/ constraintList inv;
4948  /*@unused@*/ int ngetUe;
4949  /*@unused@*/ struct getUe * t ;
4950 };
4951
4952 /* unused: static struct sInfo globalStructInfo; */
4953
4954 /*drl 1/6/2001: I didn't think these functions were solid enough to include in the
4955   stable  release of splint.  I coomented them out so that they won't break anything
4956   but didn't delete them because they will be fixed and included later
4957
4958
4959 */
4960
4961 /*@-paramuse@*/
4962
4963 void context_setGlobalStructInfo (ctype ct, constraintList list)
4964 {
4965 # if 0
4966   /* int i;
4967   uentryList f;
4968
4969   f =  ctype_getFields (ct);
4970   
4971   if (constraintList_isDefined(list) )
4972     {
4973       globalStructInfo.ct = ct;
4974       globalStructInfo.inv = list;
4975
4976       globalStructInfo.ngetUe = 0;
4977       
4978       /* abstraction violation fix it * /
4979       globalStructInfo.t   = dmalloc(f->nelements * sizeof(struct getUe) );
4980
4981       globalStructInfo.ngetUe = f->nelements;
4982
4983       i = 0;
4984       
4985       uentryList_elements(f, ue)
4986         {
4987           globalStructInfo.t[i].ue = ue;
4988           globalStructInfo.t[i].s = uentry_getSref(ue);
4989           TPRINTF(( message(" setGlobalStructInfo:: adding ue=%s and sRef=%s",
4990                             uentry_unparse(ue), sRef_unparse( uentry_getSref(ue) )
4991                             )
4992                     ));
4993           i++;
4994         }
4995       end_uentryList_elements;
4996     }
4997   */
4998 # endif
4999 }
5000
5001 # if 0
5002 /*
5003
5004 bool hasInvariants (ctype ct) /*@* /
5005 {
5006   if ( ctype_sameName(globalStructInfo.ct, ct) )
5007
5008     return TRUE;
5009
5010   else
5011     
5012     return FALSE;
5013   
5014 }
5015 */
5016 # endif
5017
5018 /*@=paramuse@*/
5019
5020
5021
5022
This page took 0.40269 seconds and 3 git commands to generate.