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