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