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