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