]> andersk Git - splint.git/blob - src/llmain.c
Added in test case files. (Merge should be complete now.)
[splint.git] / src / llmain.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
23 */
24 /*
25 ** llmain.c
26 **
27 ** Main module for LCLint checker
28 */
29
30 # include <signal.h>
31
32 /*
33 ** Ensure that WIN32 and _WIN32 are both defined or both undefined.
34 */
35
36 # ifdef WIN32
37 # ifndef _WIN32
38 # error "Inconsistent definitions."
39 # endif
40 # else
41 # ifdef _WIN32
42 # error "Inconsistent definitions."
43 # endif
44 # endif
45
46 # ifdef WIN32
47 # include <windows.h>
48 # include <process.h>
49 # endif
50
51 # include "lclintMacros.nf"
52 # include "llbasic.h"
53 # include "osd.h"
54
55 # ifndef NOLCL
56 # include "gram.h"
57 # include "lclscan.h"
58 # include "scanline.h"
59 # include "lclscanline.h"
60 # include "lclsyntable.h"
61 # include "lcltokentable.h"
62 # include "lslparse.h"
63 # include "scan.h"
64 # include "syntable.h"
65 # include "tokentable.h"
66 # include "lslinit.h"
67 # include "lclinit.h"
68 # include "lh.h"
69 # include "imports.h"
70 # endif
71
72 # include "version.h"
73 # include "herald.h"
74 # include "fileIdList.h"
75 # include "lcllib.h"
76 # include "cgrammar.h"
77 # include "llmain.h"
78 # include "portab.h"
79 # include "cpp.h"
80 # include <time.h>
81
82 extern /*@external@*/ int yydebug;
83
84 static void printMail (void);
85 static void printMaintainer (void);
86 static void printReferences (void);
87 static void printFlags (void);
88 static void printAnnotations (void);
89 static void printParseErrors (void);
90 static void printComments (void);
91 static void describePrefixCodes (void);
92 static void cleanupFiles (void);
93 static void showHelp (void);
94 static void interrupt (int p_i);
95 static void loadrc (FILE *p_rcfile, cstringSList *p_passThroughArgs);
96 static void describeVars (void);
97 static bool specialFlagsHelp (char *p_next);
98 static bool hasShownHerald = FALSE;
99
100 static bool anylcl = FALSE;
101 static clock_t inittime;
102
103 static /*@only@*/ /*@null@*/ tsource *initFile = (tsource *) 0;
104
105 static fileIdList preprocessFiles (fileIdList)
106   /*@modifies fileSystem@*/ ;
107
108 # ifndef NOLCL
109
110 static
111 void lslCleanup (void)
112    /*@globals killed g_symtab@*/
113    /*@modifies internalState, g_symtab@*/
114 {
115   /*
116   ** Cleanup all the LCL/LSL.
117   */
118
119   static bool didCleanup = FALSE;
120
121   llassert (!didCleanup);
122   llassert (anylcl);
123
124   didCleanup = TRUE;
125
126   lsymbol_destroyMod ();
127   LCLSynTableCleanup ();
128   LCLTokenTableCleanup ();
129   LCLScanLineCleanup ();
130   LCLScanCleanup ();
131
132   /* clean up LSL parsing */
133
134   lsynTableCleanup ();
135   ltokenTableCleanup ();
136   lscanLineCleanup ();
137   LSLScanCleanup ();
138
139   symtable_free (g_symtab);
140   sort_destroyMod (); 
141 }
142
143 static
144   void lslInit (void)
145   /*@globals undef g_symtab; @*/
146   /*@modifies g_symtab, internalState, fileSystem; @*/
147 {
148   /*
149   ** Open init file provided by user, or use the default LCL init file 
150   */
151   
152   cstring larchpath = context_getLarchPath ();
153   tsource *LSLinitFile = (tsource *) 0;
154
155   setCodePoint ();
156
157   if (initFile == (tsource *) 0)
158     {
159       initFile = tsource_create (INITFILENAME, LCLINIT_SUFFIX, FALSE);
160       
161       if (!tsource_getPath (cstring_toCharsSafe (larchpath), initFile))
162         {
163           lldiagmsg (message ("Continuing without LCL init file: %s",
164                               cstring_fromChars (tsource_fileName (initFile))));
165         }
166       else 
167         {
168           if (!tsource_open (initFile))
169             {
170               lldiagmsg (message ("Continuing without LCL init file: %s",
171                                   cstring_fromChars (tsource_fileName (initFile))));
172             }
173         }
174     }
175   else 
176     {
177       if (!tsource_open (initFile))
178         {
179           lldiagmsg (message ("Continuing without LCL init file: %s",
180                               cstring_fromChars (tsource_fileName (initFile))));
181         }
182     }
183
184   /* Initialize checker */
185
186   lsymbol_initMod ();
187   LCLSynTableInit ();
188
189   setCodePoint ();
190
191   LCLSynTableReset ();
192   LCLTokenTableInit ();
193
194   setCodePoint ();
195
196   LCLScanLineInit ();
197   setCodePoint ();
198   LCLScanLineReset ();
199   setCodePoint ();
200   LCLScanInit ();
201
202   setCodePoint ();
203
204   /* need this to initialize LCL checker */
205   llassert (initFile != NULL);
206       
207   if (tsource_isOpen (initFile))
208     {
209       setCodePoint ();
210
211       LCLScanReset (initFile);
212       LCLProcessInitFileInit ();
213       LCLProcessInitFileReset ();
214
215       setCodePoint ();
216       LCLProcessInitFile ();
217       LCLProcessInitFileCleanup ();
218
219       setCodePoint ();
220       check (tsource_close (initFile));
221     }
222   
223   /* Initialize LSL init files, for parsing LSL signatures from LSL */
224   
225   LSLinitFile = tsource_create ("lslinit.lsi", ".lsi", FALSE);
226   
227   if (!tsource_getPath (cstring_toCharsSafe (larchpath), LSLinitFile))
228     {
229       lldiagmsg (message ("Continuing without LSL init file: %s",
230                           cstring_fromChars (tsource_fileName (LSLinitFile))));
231     }
232   else 
233     {
234       if (!tsource_open (LSLinitFile))
235         {
236           lldiagmsg (message ("Continuing without LSL init file: %s",
237                               cstring_fromChars (tsource_fileName (LSLinitFile))));
238         }
239     }
240       
241   setCodePoint ();
242   lsynTableInit ();
243   lsynTableReset ();
244
245   setCodePoint ();
246   ltokenTableInit ();
247
248   setCodePoint ();
249   lscanLineInit ();
250   lscanLineReset ();
251   LSLScanInit ();
252
253   if (tsource_isOpen (LSLinitFile))
254     {
255       setCodePoint ();
256       LSLScanReset (LSLinitFile);
257       LSLProcessInitFileInit ();
258       setCodePoint ();
259       LSLProcessInitFile ();
260       setCodePoint ();
261       check (tsource_close (LSLinitFile));
262     }
263       
264   tsource_free (LSLinitFile);
265   
266   if (lclHadError ())
267     {
268       lclplainerror 
269         (cstring_makeLiteral ("LSL init file error.  Attempting to continue."));
270     }
271   
272   setCodePoint ();
273   g_symtab = symtable_new ();
274   
275   /* 
276   ** sort_init must come after symtab has been initialized 
277   */
278   sort_init ();
279   abstract_init ();
280   setCodePoint ();
281   
282   inittime = clock ();
283   
284   /* 
285   ** Equivalent to importing old spec_csupport.lcl
286   ** define immutable LCL type "bool" and bool constants TRUE and FALSE
287   ** and initialized them to be equal to LSL's "true" and "false".
288   **
289   ** Reads in CTrait.syms (derived from CTrait.lsl) on LARCH_PATH.
290   */
291       
292   LCLBuiltins (); 
293   LCLReportEolTokens (FALSE);
294 }
295
296 static void
297 lslProcess (fileIdList lclfiles)
298    /*@globals undef g_currentSpec, undef g_currentSpecName, g_currentloc,
299               undef killed g_symtab; @*/
300    /*@modifies g_currentSpec, g_currentSpecName, g_currentloc, internalState, fileSystem; @*/
301 {
302   char *path = NULL;
303   bool parser_status = FALSE;
304   bool overallStatus = FALSE;
305   
306   lslInit ();
307   
308   context_resetSpecLines ();
309
310   fileIdList_elements (lclfiles, fid)
311     {
312       char *actualName = (char *) dmalloc (sizeof (*actualName));
313       char *oactualName = actualName;
314       char *fname = cstring_toCharsSafe (fileName (fid));
315       
316       if (osd_getPath (g_localSpecPath, fname, &actualName) == OSD_FILENOTFOUND)
317         {
318           if (mstring_equal (g_localSpecPath, "."))
319             {
320               lldiagmsg (message ("Spec file not found: %s",
321                                   cstring_fromChars (fname)));
322             }
323           else
324             {
325               lldiagmsg (message ("Spec file not found: %s (on %s)", 
326                                   cstring_fromChars (fname), 
327                                   cstring_fromChars (g_localSpecPath)));
328             }
329         }
330       else
331         {
332           tsource *specFile;
333           
334           while (*actualName == '.' && *(actualName + 1) == CONNECTCHAR) 
335             {
336               actualName += 2;
337             }
338           
339           specFile = tsource_create (actualName, LCL_SUFFIX, TRUE);
340           llassert (specFile != (tsource *) 0);
341           
342           g_currentSpec = cstring_fromChars (mstring_copy (actualName));
343
344           g_currentSpecName = specFullName 
345             (cstring_toCharsSafe (g_currentSpec),
346              &path);
347
348           setSpecFileId (fid);
349                   
350           if (context_getFlag (FLG_SHOWSCAN))
351             {
352               lldiagmsg (message ("< reading spec %s >", g_currentSpec));
353             }
354           
355           /* Open source file */
356           
357           if (!tsource_open (specFile))
358             {
359               lldiagmsg (message ("Cannot open file: %s",
360                                   cstring_fromChars (tsource_fileName (specFile))));
361               tsource_free (specFile);
362             }
363           else
364             {
365               scopeInfo dummy_scope = (scopeInfo) dmalloc (sizeof (*dummy_scope));
366               dummy_scope->kind = SPE_INVALID;
367               
368               lhInit (specFile);
369               LCLScanReset (specFile);
370               
371               /* 
372               ** Minor hacks to allow more than one LCL file to
373               ** be scanned, while keeping initializations
374               */
375               
376               symtable_enterScope (g_symtab, dummy_scope);
377               resetImports (cstring_fromChars (g_currentSpecName));
378               context_enterLCLfile ();
379               (void) lclHadNewError ();
380               
381               parser_status = (ylparse () != 0);
382               context_exitLCLfile ();
383               lhCleanup ();
384               overallStatus = parser_status || lclHadNewError (); 
385
386               if (context_getFlag (FLG_DOLCS))
387                 {
388                   if (overallStatus)
389                     {
390                       outputLCSFile (path, "%%FAILED Output from ",
391                                      g_currentSpecName);
392                     }
393                   else
394                     {
395                       outputLCSFile (path, "%%PASSED Output from ", 
396                                      g_currentSpecName);
397                     }
398                 }
399
400               (void) tsource_close (specFile);
401               tsource_free (specFile);
402
403               symtable_exitScope (g_symtab);
404             }
405         }
406       
407       sfree (oactualName);
408     } end_fileIdList_elements; 
409   
410     /* Can cleanup lsl stuff right away */
411
412       lslCleanup ();
413   
414   g_currentSpec = cstring_undefined;
415   g_currentSpecName = NULL;
416 }
417 # endif
418
419 static void handlePassThroughFlag (char *arg)
420 {
421   char *curarg = arg;
422   char *quotechar = strchr (curarg, '\"');
423   int offset = 0;
424   bool open = FALSE;
425
426   while (quotechar != NULL)
427     {
428       if (*(quotechar - 1) == '\\')
429         {
430           char *tp = quotechar - 2;
431           bool escape = TRUE;
432
433           while (*tp == '\\')
434             {
435               escape = !escape;
436               tp--;
437             }
438           
439           if (escape)
440             {
441               curarg = quotechar + 1;
442               quotechar = strchr (curarg, '\"');
443               continue;
444             }
445         }
446       
447       *quotechar = '\0';
448       offset = (quotechar - arg) + 2;
449       
450       if (open)
451         {
452           arg = cstring_toCharsSafe
453             (message ("%s\"\'%s", 
454                       cstring_fromChars (arg), 
455                       cstring_fromChars (quotechar + 1))); 
456           open = FALSE;
457         }
458       else
459         {
460           arg = cstring_toCharsSafe
461             (message ("%s\'\"%s", 
462                       cstring_fromChars (arg), 
463                       cstring_fromChars (quotechar + 1)));
464           open = TRUE;
465         }
466       
467       curarg = arg + offset;
468       quotechar = strchr (curarg, '\"');
469     }
470
471   if (open)
472     {
473       showHerald ();
474       llerror (FLG_BADFLAG,
475                message ("Unclosed quote in flag: %s",
476                         cstring_fromChars (arg)));
477     }
478   else
479     {
480       if (arg[0] == 'D') {
481         cstring def;
482         
483         /* 
484         ** If the value is surrounded by single quotes ('), remove
485         ** them.  This is an artifact of UNIX command line?
486         */
487
488         def = osd_fixDefine (arg + 1);
489         DPRINTF (("Do define: %s", def));
490         cppDoDefine (def);
491         DPRINTF (("After define"));
492         cstring_free (def);
493       } else if (arg[0] == 'U') {
494         cppDoUndefine (cstring_fromChars (arg + 1));
495       } else {
496         BADBRANCH;
497       }
498     }
499 }
500
501 void showHerald (void)
502 {
503   if (hasShownHerald || context_getFlag (FLG_QUIET)) return;
504
505   else
506     {
507       fprintf (g_msgstream, "%s\n\n", LCL_VERSION);
508       hasShownHerald = TRUE;
509       llflush ();
510     }
511 }
512
513 static void addFile (fileIdList files, /*@only@*/ cstring s)
514 {
515   if (fileTable_exists (context_fileTable (), s))
516     {
517       showHerald ();
518       lldiagmsg (message ("File listed multiple times: %s", s));
519       cstring_free (s);
520     }
521   else
522     {
523       fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
524     }
525 }
526
527 /*
528 ** Disable MSVC++ warning about return value.  Methinks humbly lclint control
529 ** comments are a mite more legible.
530 */
531
532 # ifdef WIN32
533 # pragma warning (disable:4035) 
534 # endif
535
536 int main (int argc, char *argv[])
537 # ifdef NOLCL
538   /*@globals killed undef g_currentloc,
539              killed undef yyin,
540                     undef g_msgstream;
541    @*/
542   /*@modifies g_currentloc, fileSystem,
543               yyin; 
544   @*/
545 # else
546   /*@globals killed undef g_currentloc,
547              killed undef initFile,
548              killed       g_localSpecPath,  
549              killed undef g_currentSpec,
550              killed undef g_currentSpecName,
551              killed undef yyin,
552                     undef g_msgstream;
553    @*/
554   /*@modifies g_currentloc, initFile, 
555               g_localSpecPath, g_currentSpec, g_currentSpecName, fileSystem,
556               yyin; 
557   @*/
558 # endif
559 {
560   bool first_time = TRUE;
561   bool showhelp = FALSE;
562   bool allhelp = TRUE;
563   tsource *sourceFile = (tsource *) 0;
564  
565   fileIdList dercfiles;
566   cstringSList fl = cstringSList_undefined;
567   cstringSList passThroughArgs = cstringSList_undefined;
568   fileIdList cfiles;
569   fileIdList lclfiles;
570   clock_t before, lcltime, libtime, pptime, cptime, rstime;
571   int i = 0;
572
573   g_msgstream = stdout;
574
575   (void) signal (SIGINT, interrupt);
576   (void) signal (SIGSEGV, interrupt); 
577
578   cfiles = fileIdList_create ();
579   lclfiles = fileIdList_create ();
580
581   flags_initMod ();
582   typeIdSet_initMod ();
583   cppReader_initMod ();
584
585   setCodePoint ();
586
587   g_currentloc = fileloc_createBuiltin ();
588
589   before = clock ();
590   context_initMod ();
591   context_setInCommandLine ();
592
593   if (argc <= 1)
594     {
595       showHelp ();
596       llexit (LLGIVEUP);
597     }
598
599   setCodePoint ();
600   yydebug = 0;
601
602   /*
603   ** Add include directories from environment.
604   */
605
606   {
607     char *incval = mstring_copy (osd_getEnvironmentVariable (INCLUDE_VAR));
608
609     if (incval != NULL)
610       {
611         /*
612         ** Each directory on the include path is a system include directory.
613         */
614
615         DPRINTF (("include: %s", incval));
616         context_setString (FLG_SYSTEMDIRS, cstring_fromCharsNew (incval));
617
618         while (incval != NULL)
619           {
620             char *nextsep = strchr (incval, SEPCHAR);
621
622             if (nextsep != NULL)
623               {
624                 cstring dir;
625                 *nextsep = '\0';
626                 dir = cstring_fromCharsNew (incval);
627
628                 if (cstring_length (dir) == 0
629                     || !isalpha ((int) cstring_firstChar (dir)))
630                   {
631                     /* 
632                     ** win32 environment values can have special values,
633                     ** ignore them
634                     */
635                   }
636                 else
637                   {
638                     DPRINTF (("Add include: %s", dir));
639                     cppAddIncludeDir (dir);
640                   }
641
642                 *nextsep = SEPCHAR;
643                 incval = nextsep + 1;
644                 cstring_free (dir);
645               }
646             else
647               {
648                 break;
649               }
650           }
651       }
652   }
653
654   /*
655   ** check RCFILE for default flags
656   */
657
658   {
659     cstring home = cstring_fromChars (osd_getHomeDir ());
660     char *fname  = NULL;
661     FILE *rcfile;
662     bool defaultf = TRUE;
663     bool nof = FALSE;
664
665     for (i = 1; i < argc; i++)
666       {
667         char *thisarg;
668         thisarg = argv[i];
669         
670         if (*thisarg == '-' || *thisarg == '+')
671           {
672             thisarg++;
673
674             if (mstring_equal (thisarg, "nof"))
675               {
676                 nof = TRUE;
677               }
678             else if (mstring_equal (thisarg, "f"))
679               {
680                 if (++i < argc)
681                   {
682                     defaultf = FALSE;
683                     fname = argv[i];
684                     rcfile = fopen (fname, "r");
685
686                     if (rcfile != NULL)
687                       {
688                         fileloc oloc = g_currentloc;
689                         
690                         g_currentloc = fileloc_createRc (cstring_fromChars (fname));
691                         loadrc (rcfile, &passThroughArgs);
692                         fileloc_reallyFree (g_currentloc); 
693                         g_currentloc = oloc;
694                       }
695                     else 
696                       {
697                         showHerald ();
698                         lldiagmsg (message ("Options file not found: %s", 
699                                             cstring_fromChars (fname)));
700                       }
701                   }
702                 else
703                   llfatalerror
704                     (cstring_makeLiteral ("Flag f to select options file "
705                                           "requires an argument"));
706               }
707             else
708               {
709                 ; /* wait to process later */
710               }
711           }
712       }
713     
714     if (fname == NULL)
715       {
716         if (!cstring_isEmpty (home)) {
717           fname = cstring_toCharsSafe (message ("%s%h%s", home, CONNECTCHAR,
718                                                 cstring_fromChars (RCFILE)));
719           mstring_markFree (fname);
720         }
721       }
722
723     setCodePoint ();
724
725     if (!nof && defaultf)
726       {
727         if (!mstring_isEmpty (fname)) {
728           rcfile = fopen (fname, "r");
729           
730           if (rcfile != NULL)
731             {
732               fileloc oloc = g_currentloc;
733               
734               g_currentloc = fileloc_createRc (cstring_fromChars (fname));
735               loadrc (rcfile, &passThroughArgs);
736               fileloc_reallyFree (g_currentloc);
737               g_currentloc = oloc;
738             }
739         }
740
741 # if defined(MSDOS) || defined(OS2)
742         fname = cstring_toCharsSafe (message ("%s",
743                                               cstring_fromChars (RCFILE)));
744 # else
745         fname = cstring_toCharsSafe (message ("./%s", 
746                                               cstring_fromChars (RCFILE)));
747 # endif
748
749         rcfile = fopen (fname, "r");
750
751         if (rcfile != NULL)
752           {
753             fileloc oloc = g_currentloc;
754
755             g_currentloc = fileloc_createRc (cstring_fromChars (fname));
756             loadrc (rcfile, &passThroughArgs);
757             fileloc_reallyFree (g_currentloc);
758             g_currentloc = oloc;
759           }
760
761         sfree (fname); 
762       }
763   }
764   
765   setCodePoint ();
766   
767   for (i = 1; i < argc; i++)
768     {
769       char *thisarg;
770       flagcode opt;
771       
772       thisarg = argv[i];
773       
774       if (showhelp)
775         {
776           if (allhelp)
777             {
778               showHerald ();
779             }
780           
781           allhelp = FALSE;
782           
783           if (*thisarg == '-' || *thisarg == '+')
784             {
785               thisarg++;        /* skip '-' */
786             }
787           if (mstring_equal (thisarg, "modes"))
788             {
789               llmsg (describeModes ());
790             }
791           else if (mstring_equal (thisarg, "vars")
792                    || mstring_equal (thisarg, "env"))
793             {
794               describeVars ();
795             }
796           else if (mstring_equal (thisarg, "annotations"))
797             {
798               printAnnotations ();
799             }
800           else if (mstring_equal (thisarg, "parseerrors"))
801             {
802               printParseErrors ();
803             }
804           else if (mstring_equal (thisarg, "comments"))
805             {
806               printComments ();
807             }
808           else if (mstring_equal (thisarg, "prefixcodes"))
809             {
810               describePrefixCodes ();
811             }
812           else if (mstring_equal (thisarg, "references") 
813                    || mstring_equal (thisarg, "refs"))
814             {
815               printReferences ();
816             }
817           else if (mstring_equal (thisarg, "mail"))
818             {
819               printMail ();
820             }
821           else if (mstring_equal (thisarg, "maintainer")
822                    || mstring_equal (thisarg, "version"))
823             {
824               printMaintainer ();
825             }
826           else if (mstring_equal (thisarg, "flags"))
827             {
828               if (i + 1 < argc)
829                 {
830                   char *next = argv[i + 1];
831                   
832                   if (specialFlagsHelp (next))
833                     {
834                       i++;
835                     }
836                   else
837                     {
838                       flagkind k = identifyCategory (cstring_fromChars (next));
839                       
840                       if (k != FK_NONE)
841                         {
842                           printCategory (k);
843                           i++;
844                         }
845                     }
846                 }
847               else
848                 {
849                   printFlags ();
850                 }
851             }
852           else
853             {
854               cstring s = describeFlag (cstring_fromChars (thisarg));
855               
856               if (cstring_isDefined (s))
857                 {
858                   llmsg (s);
859                 }
860             }
861         }
862       else
863         {
864           if (*thisarg == '-' || *thisarg == '+')
865             {
866               bool set = (*thisarg == '+');
867               cstring flagname;
868               
869               thisarg++;        /* skip '-' */
870               flagname = cstring_fromChars (thisarg);
871               
872               opt = identifyFlag (flagname);
873               
874               if (flagcode_isSkip (opt))
875                 {
876                   ;
877                 }
878               else if (flagcode_isInvalid (opt))
879                 {
880                   if (isMode (flagname))
881                     {
882                       context_setMode (flagname);
883                     }
884                   else
885                     {
886                       llgloberror (message ("Unrecognized option: %s", 
887                                             cstring_fromChars (thisarg)));
888                     }
889                 }
890               else
891                 {
892                   context_userSetFlag (opt, set);
893                   
894                   if (flagcode_hasArgument (opt))
895                     {
896                       if (opt == FLG_HELP)
897                         {
898                           showhelp = TRUE;
899                         }
900                       else if (flagcode_isPassThrough (opt)) /* -D or -U */
901                         { 
902                           passThroughArgs = cstringSList_add 
903                             (passThroughArgs, cstring_fromChars (thisarg));
904                         }
905                       else if (flagcode_hasValue (opt))
906                         {
907                           if (++i < argc)
908                             {
909                               setValueFlag (opt, cstring_fromChars (argv[i]));
910                             }
911                           else
912                             {
913                               llfatalerror 
914                                 (message
915                                  ("Flag %s must be followed by a number",
916                                   flagcode_unparse (opt)));
917                             }
918                         } 
919                       else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
920                         {
921                           cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */
922                           
923                           switch (opt)
924                             {
925                             case FLG_INCLUDEPATH:
926                               cppAddIncludeDir (dir);
927                               /*@switchbreak@*/ break;
928                             case FLG_SPECPATH:
929                               /*@-mustfree@*/
930                               g_localSpecPath = cstring_toCharsSafe
931                                 (message ("%s%h%s", 
932                                           cstring_fromChars (g_localSpecPath), 
933                                           SEPCHAR,
934                                           dir));
935                               /*@=mustfree@*/
936                               /*@switchbreak@*/ break;
937                               BADDEFAULT;
938                             }
939                         }
940                       else if (flagcode_hasString (opt)
941                                || opt == FLG_INIT || opt == FLG_OPTF)
942                         {
943                           if (++i < argc)
944                             {
945                               cstring arg = cstring_fromChars (argv[i]);
946                               
947                               if (opt == FLG_OPTF)
948                                 {
949                                   ; /* -f already processed */
950                                 }
951                               else if (opt == FLG_INIT)
952                                 {
953 # ifndef NOLCL
954                                   initFile = tsource_create 
955                                     (cstring_toCharsSafe (arg), 
956                                      LCLINIT_SUFFIX, FALSE);
957 # endif
958                                   break;
959                                 }
960                               else
961                                 {
962                                   setStringFlag (opt, arg);
963                                 }
964                             }
965                           else
966                             {
967                               llfatalerror 
968                                 (message
969                                  ("Flag %s must be followed by a string",
970                                   flagcode_unparse (opt)));
971                             }
972                         }
973                       else
974                         {
975                           /* no argument */
976                         }
977                     }
978                 }
979             }
980           else /* its a filename */
981             {
982               fl = cstringSList_add (fl, cstring_fromChars (thisarg));
983             }
984         }
985     }
986
987   setCodePoint ();  
988
989   /*
990   ** create lists of C and LCL files
991   */
992
993   cstringSList_elements (fl, current)
994     {
995       char *fname = cstring_toCharsSafe (current);
996       char *ext = strrchr (fname, '.');
997
998       if (ext == NULL)
999         {
1000           /* no extension --- both C and LCL with default extensions */
1001           
1002           addFile (cfiles, message ("%s.c", cstring_fromChars (fname)));
1003           addFile (lclfiles, message ("%s.lcl", cstring_fromChars (fname)));
1004         }
1005       else if (isCext (ext))
1006         {
1007           addFile (cfiles, cstring_fromCharsNew (fname));
1008         }
1009       else 
1010         {
1011           if (!mstring_equal (ext, ".lcl"))
1012             {
1013               lldiagmsg (message ("Unrecognized file extension: %s (assuming lcl)", 
1014                                   cstring_fromChars (ext)));
1015             }
1016
1017           addFile (lclfiles, cstring_fromCharsNew (fname));
1018         }
1019     } end_cstringSList_elements;
1020   
1021   
1022   showHerald ();
1023
1024   
1025   if (showhelp)
1026     {
1027       if (allhelp)
1028         {
1029           showHelp ();
1030         }
1031       fprintf (g_msgstream, "\n");
1032
1033       fileIdList_free (cfiles);
1034       fileIdList_free (lclfiles);
1035       
1036       llexit (LLSUCCESS);
1037     }
1038
1039 # ifdef DOANNOTS
1040   initAnnots ();
1041 # endif
1042
1043   inittime = clock ();
1044
1045   context_resetErrors ();
1046   context_clearInCommandLine ();
1047
1048   anylcl = !fileIdList_isEmpty (lclfiles);
1049
1050   if (context_doMerge ())
1051     {
1052       cstring m = context_getMerge ();
1053
1054       if (context_getFlag (FLG_SHOWSCAN))
1055         {
1056           fprintf (g_msgstream, "< loading %s ", cstring_toCharsSafe (m));
1057         }
1058
1059       loadState (m);
1060
1061       if (context_getFlag (FLG_SHOWSCAN))
1062         {
1063           fprintf (g_msgstream, " >\n");
1064         }
1065
1066       if (!usymtab_existsType (context_getBoolName ()))
1067         {
1068           usymtab_initBool (); 
1069         }
1070     }
1071   else
1072     {
1073       if (!context_getFlag (FLG_NOLIB) && loadStandardState ())
1074         {
1075           ;
1076         }
1077       else
1078         {
1079           ctype_initTable ();
1080         }
1081
1082       /* setup bool type and constants */
1083       usymtab_initBool (); 
1084     }
1085
1086   fileloc_free (g_currentloc);
1087   g_currentloc = fileloc_createBuiltin ();
1088
1089   libtime = clock ();
1090   
1091   if (anylcl)
1092     {
1093 # ifdef NOLCL
1094       llfatalerror (cstring_makeLiteral ("This version of LCLint does not handle LCL files."));
1095 # else
1096       lslProcess (lclfiles);
1097 # endif
1098     }
1099
1100   /*
1101   ** pre-processing
1102   **
1103   ** call the pre-preprocessor and /lib/cpp to generate appropriate
1104   ** files
1105   **
1106   */
1107
1108   context_setInCommandLine ();
1109
1110   cppReader_initialize ();
1111
1112   DPRINTF (("Pass through: %s", cstringSList_unparse (passThroughArgs)));
1113   
1114   cstringSList_elements (passThroughArgs, thisarg) {
1115     handlePassThroughFlag (cstring_toCharsSafe (thisarg));
1116   } end_cstringSList_elements;
1117
1118   cstringSList_free (passThroughArgs);
1119
1120   cleanupMessages ();
1121
1122   cppReader_saveDefinitions ();
1123   
1124   context_clearInCommandLine ();
1125
1126   if (!context_getFlag (FLG_NOPP))
1127     {
1128       llflush ();
1129
1130       if (context_getFlag (FLG_SHOWSCAN))
1131         {
1132           fprintf (stderr, "< preprocessing"); 
1133         }
1134       
1135       lcltime = clock ();
1136
1137       context_setPreprocessing ();
1138       dercfiles = preprocessFiles (cfiles);
1139       context_clearPreprocessing ();
1140
1141       fileIdList_free (cfiles);
1142
1143       if (context_getFlag (FLG_SHOWSCAN))
1144         {
1145           fprintf (stderr, " >\n");
1146         }
1147       
1148       pptime = clock ();
1149     }
1150   else
1151     {
1152       lcltime = clock ();
1153       dercfiles = cfiles;
1154       pptime = clock ();
1155     }
1156   
1157   /*
1158   ** now, check all the corresponding C files
1159   **
1160   ** (for now these are just <file>.c, but after pre-processing
1161   **  will be <tmpprefix>.<file>.c)
1162   */
1163
1164   {
1165 # ifdef WIN32
1166     int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
1167
1168     if (nfiles != 0) 
1169       {
1170         llbug (message ("Files unclosed: %d", nfiles));
1171       }
1172 # endif
1173   }
1174
1175   exprNode_initMod ();
1176
1177   fileIdList_elements (dercfiles, fid)
1178     {
1179       sourceFile = tsource_create (cstring_toCharsSafe (fileName (fid)),
1180                                    C_SUFFIX, TRUE);
1181       context_setFileId (fid);
1182       
1183       /* Open source file  */
1184       
1185       if (sourceFile == (tsource *) 0 || (!tsource_open (sourceFile)))
1186         {
1187           /* previously, this was ignored  ?! */
1188           llbug (message ("Could not open temp file: %s", fileName (fid)));
1189         }
1190       else
1191         {
1192           yyin = sourceFile->file; /*< shared <- only */
1193         
1194           llassert (yyin != NULL);
1195
1196           if (context_getFlag (FLG_SHOWSCAN))
1197             {
1198                       lldiagmsg (message ("< checking %s >", rootFileName (fid)));
1199             }
1200           
1201           /*
1202           ** Every time, except the first time, through the loop,
1203           ** need to call yyrestart to clean up the parse buffer.
1204           */
1205
1206           if (!first_time)
1207             {
1208               (void) yyrestart (yyin);  
1209             }
1210           else
1211             {
1212               first_time = FALSE;
1213             }
1214           
1215           context_enterFile ();
1216           (void) yyparse ();
1217           context_exitFile ();
1218                     
1219           (void) tsource_close (sourceFile);
1220         }
1221       
1222     } end_fileIdList_elements;
1223
1224   cptime = clock ();
1225   
1226   /* process any leftover macros */
1227
1228   context_processAllMacros ();
1229   
1230   /* check everything that was specified was defined */
1231   
1232   /* don't check if no c files were processed ?
1233   **   is this correct behaviour?
1234   */
1235   
1236   if (context_getFlag (FLG_SHOWSCAN))
1237     {
1238       lldiagmsg (cstring_makeLiteral ("< global checks >"));
1239     }
1240
1241   cleanupMessages ();
1242   
1243   if (context_getLinesProcessed () > 0)
1244     {
1245       usymtab_allDefined ();
1246     }
1247
1248   if (context_maybeSet (FLG_TOPUNUSED))
1249     {
1250       uentry ue = usymtab_lookupSafe (cstring_makeLiteralTemp ("main"));
1251
1252       if (uentry_isValid (ue))
1253         {
1254           uentry_setUsed (ue, fileloc_observeBuiltin ());
1255         }
1256
1257       usymtab_allUsed ();
1258     }
1259
1260   if (context_maybeSet (FLG_EXPORTLOCAL))
1261     {
1262       usymtab_exportLocal ();
1263     }
1264
1265   
1266   if (context_maybeSet (FLG_EXPORTHEADER))
1267     {
1268       usymtab_exportHeader ();
1269     }
1270
1271   if (context_getFlag (FLG_SHOWUSES))
1272     {
1273       usymtab_displayAllUses ();
1274     }
1275
1276   context_checkSuppressCounts ();
1277
1278   if (context_doDump ())
1279     {
1280       cstring dump = context_getDump ();
1281
1282       dumpState (dump);
1283     }
1284
1285 # ifdef DOANNOTS
1286   printAnnots ();
1287 # endif
1288
1289   cleanupFiles ();
1290
1291   if (context_getFlag (FLG_SHOWSUMMARY))
1292     {
1293       summarizeErrors (); 
1294     }
1295
1296   if (!context_getFlag (FLG_QUIET))
1297     {
1298       cstring specErrors = cstring_undefined;
1299 # ifndef NOLCL
1300       int nspecErrors = lclNumberErrors ();
1301 # endif
1302
1303       if (context_neednl ())
1304         fprintf (g_msgstream, "\n");
1305     
1306 # ifndef NOLCL
1307       if (nspecErrors > 0)
1308         {
1309           if (nspecErrors == context_getLCLExpect ())
1310             {
1311               specErrors = 
1312                 message ("%d spec error%p found, as expected\n       ", 
1313                          nspecErrors);
1314             }
1315           else
1316             {
1317               if (context_getLCLExpect () > 0)
1318                 {
1319                   specErrors = 
1320                     message ("%d spec error%p found, expected %d\n       ", 
1321                              nspecErrors,
1322                              (int) context_getLCLExpect ());
1323                 }
1324               else
1325                 {
1326                   specErrors = message ("%d spec error%p found\n       ",
1327                                         nspecErrors);
1328                 }
1329             }
1330         }
1331       else
1332         {
1333           if (context_getLCLExpect () > 0)
1334             {
1335               specErrors = message ("No spec errors found, expected %d\n       ", 
1336                                     (int) context_getLCLExpect ());
1337             }
1338         }
1339 # endif
1340
1341       if (context_anyErrors ())
1342         {
1343           if (context_numErrors () == context_getExpect ())
1344             {
1345               llmsg (message ("Finished LCLint checking --- "
1346                               "%s%d code error%p found, as expected",
1347                               specErrors, context_numErrors ()));
1348             }
1349           else
1350             {
1351               if (context_getExpect () > 0)
1352                 {
1353                   llmsg (message 
1354                          ("Finished LCLint checking --- "
1355                           "%s%d code error%p found, expected %d",
1356                           specErrors, context_numErrors (), 
1357                           (int) context_getExpect ()));
1358                 }
1359               else
1360                 {
1361                   llmsg (message ("Finished LCLint checking --- "
1362                                   "%s%d code error%p found", 
1363                                   specErrors, context_numErrors ()));
1364                 }
1365             }
1366         }
1367       else
1368         {
1369           if (context_getExpect () > 0)
1370             {
1371               llmsg (message
1372                      ("Finished LCLint checking --- "
1373                       "%sno code errors found, expected %d", 
1374                       specErrors,
1375                       (int) context_getExpect ()));
1376             }
1377           else
1378             {
1379               if (context_getLinesProcessed () > 0)
1380                 {
1381                   llmsg (message ("Finished LCLint checking --- %sno code errors found", 
1382                                       specErrors));
1383                 }
1384               else
1385                 {
1386                   llmsg (message ("Finished LCLint checking --- %sno code processed", 
1387                                       specErrors));
1388                 }
1389             }
1390         }
1391
1392       cstring_free (specErrors);
1393     }
1394
1395   if (context_getFlag (FLG_STATS))
1396     {
1397       clock_t ttime = clock () - before;
1398       int specLines = context_getSpecLinesProcessed ();
1399
1400       rstime = clock ();
1401
1402       if (specLines > 0)
1403         {
1404           fprintf (g_msgstream, "%d spec, ", specLines);
1405         }
1406
1407 # ifndef CLOCKS_PER_SEC
1408       fprintf (g_msgstream, "%d source lines in %ld time steps (steps/sec unknown)\n", 
1409                context_getLinesProcessed (), 
1410                (long) ttime);
1411 # else
1412       fprintf (g_msgstream, "%d source lines in %.2f s.\n", 
1413                context_getLinesProcessed (), 
1414                (double) ttime / CLOCKS_PER_SEC);
1415 # endif
1416     }
1417   else
1418     {
1419       rstime = clock ();
1420     }
1421   
1422   if (context_getFlag (FLG_TIMEDIST))
1423     {
1424       clock_t ttime = clock () - before;
1425
1426       if (ttime > 0)
1427         {
1428           char *msg = (char *) dmalloc (256 * sizeof (*msg));
1429
1430           if (anylcl)
1431             {
1432               sprintf (msg, 
1433                        "Time distribution (percent): initialize %.2f / lcl %.2f / "
1434                        "pre-process %.2f / c check %.2f / finalize %.2f \n", 
1435                        (100.0 * (double) (libtime - before) / ttime),
1436                        (100.0 * (double) (lcltime - libtime) / ttime),
1437                        (100.0 * (double) (pptime - lcltime) / ttime),
1438                        (100.0 * (double) (cptime - pptime) / ttime),
1439                        (100.0 * (double) (rstime - cptime) / ttime));
1440             }
1441           else
1442             {
1443               sprintf (msg, 
1444                        "Time distribution (percent): initialize %.2f / "
1445                        "pre-process %.2f / c check %.2f / finalize %.2f \n", 
1446                        (100.0 * (double) (libtime - before) / ttime),
1447                        (100.0 * (double) (pptime - libtime) / ttime),
1448                        (100.0 * (double) (cptime - pptime) / ttime),
1449                        (100.0 * (double) (rstime - cptime) / ttime));
1450             }
1451
1452           llgenindentmsgnoloc (cstring_fromCharsO (msg));
1453         }
1454     }
1455
1456   llexit (LLSUCCESS);
1457 }
1458
1459 /*
1460 ** Reenable return value warnings.
1461 */
1462
1463 #pragma warning (default:4035)
1464
1465 void
1466 showHelp (void)
1467 {
1468   showHerald ();
1469   
1470   llmsglit ("Source files are .c, .h and .lcl files.  If there is no suffix,");
1471   llmsglit ("   LCLint will look for <file>.c and <file>.lcl.");
1472   llmsglit ("");
1473   llmsglit ("Use lclint -help <topic or flag name> for more information");
1474   llmsglit ("");
1475   llmsglit ("Topics:");
1476   llmsglit ("");
1477   llmsglit ("   annotations (describes source-code annotations)");
1478   llmsglit ("   comments (describes control comments)");
1479   llmsglit ("   flags (describes flag categories)");
1480   llmsglit ("   flags <category> (describes flags in category)");
1481   llmsglit ("   flags all (short description of all flags)");
1482   llmsglit ("   flags alpha (list all flags alphabetically)");
1483   llmsglit ("   flags full (full description of all flags)");
1484   llmsglit ("   mail (information on mailing lists)");
1485   llmsglit ("   modes (show mode settings)");
1486   llmsglit ("   parseerrors (help on handling parser errors)");
1487   llmsglit ("   prefixcodes (character codes in namespace prefixes)");
1488   llmsglit ("   references (sources for more information)");
1489   llmsglit ("   vars (environment variables)"); 
1490   llmsglit ("   version (information on compilation, maintainer)");
1491   llmsglit ("");
1492 }
1493
1494 static bool
1495 specialFlagsHelp (char *next)
1496 {
1497   if ((next != NULL) && (*next != '-') && (*next != '+'))
1498     {
1499       if (mstring_equal (next, "alpha"))
1500         {
1501           printAlphaFlags ();
1502           return TRUE;
1503         }
1504       else if (mstring_equal (next, "all"))
1505         {
1506           printAllFlags (TRUE, FALSE);
1507           return TRUE;
1508         }
1509       else if (mstring_equal (next, "categories")
1510                || mstring_equal (next, "cats"))
1511         {
1512           listAllCategories ();
1513           return TRUE;
1514         }
1515       else if (mstring_equal (next, "full"))
1516         {
1517           printAllFlags (FALSE, TRUE);
1518           return TRUE;
1519         }
1520       else
1521         {
1522           return FALSE;
1523         }
1524     }
1525   else
1526     {
1527       return FALSE;
1528     }
1529 }
1530
1531 void
1532 printParseErrors (void)
1533 {
1534   llmsglit ("Parse Errors");
1535   llmsglit ("------------");
1536   llmsglit ("");
1537   llmsglit ("LCLint will sometimes encounter a parse error for code that "
1538             "can be parsed with a local compiler. There are a few likely "
1539             "causes for this and a number of techniques that can be used "
1540             "to work around the problem.");
1541   llmsglit ("");
1542   llmsglit ("Compiler extensions --- compilers sometimes extend the C "
1543             "language with compiler-specific keywords and syntax. While "
1544             "it is not advisible to use these, oftentimes one has no choice "
1545             "when the system header files use compiler extensions. ");
1546   llmsglit ("");
1547   llmsglit ("LCLint supports some of the GNU (gcc) compiler extensions, "
1548             "if the +gnuextensions flag is set. You may be able to workaround "
1549             "other compiler extensions by using a pre-processor define. "
1550             "Alternately, you can surround the unparseable code with");
1551   llmsglit ("");
1552   llmsglit ("   # ifndef __LCLINT__");
1553   llmsglit ("   ...");
1554   llmsglit ("   # endif");
1555   llmsglit ("");
1556   llmsglit ("Missing type definitions --- an undefined type name will usually "
1557             "lead to a parse error. This ofter occurs when a standard header "
1558             "file defines some type that is not part of the standard library. ");
1559   llmsglit ("By default, LCLint does not process the local files corresponding "
1560             "to standard library headers, but uses a library specification "
1561             "instead so dependencies on local system headers can be detected. "
1562             "If another system header file that does not correspond to a "
1563             "standard library header uses one of these superfluous types, "
1564             "a parse error will result.");
1565   llmsglit ("");
1566   llmsglit ("If the parse error is inside a posix standard header file, the "
1567             "first thing to try is +posixlib. This make LCLint use "
1568             "the posix library specification instead of reading the posix "
1569             "header files.");
1570   llmsglit ("");
1571   llmsglit ("Otherwise, you may need to either manually define the problematic "
1572             "type (e.g., add -Dmlink_t=int to your .lclintrc file) or force "
1573             "lclint to process the header file that defines it. This is done "
1574             "by setting -skipansiheaders or -skipposixheaders before "
1575             "the file that defines the type is #include'd.");
1576   llmsglit ("(See lclint -help "
1577             "skipansiheaders and lclint -help skipposixheaders for a list of "
1578             "standard headers.)  For example, if <sys/local.h> uses a type "
1579             "defined by posix header <sys/types.h> but not defined by the "
1580             "posix library, we might do: ");
1581   llmsglit ("");
1582   llmsglit ("   /*@-skipposixheaders@*/");
1583   llmsglit ("   # include <sys/types.h>");
1584   llmsglit ("   /*@=skipposixheaders@*/");
1585   llmsglit ("   # include <sys/local.h>");
1586   llmsglit ("");
1587   llmsglit ("to force LCLint to process <sys/types.h>.");
1588   llmsglit ("");
1589   llmsglit ("At last resort, +trytorecover can be used to make LCLint attempt "
1590             "to continue after a parse error.  This is usually not successful "
1591             "and the author does not consider assertion failures when +trytorecover "
1592             "is used to be bugs.");
1593 }
1594
1595 void
1596 printAnnotations (void)
1597 {
1598   llmsglit ("Annotations");
1599   llmsglit ("-----------");
1600   llmsglit ("");
1601   llmsglit ("Annotations are stylized comments that document certain "
1602             "assumptions about functions, variables, parameters, and types. ");
1603   llmsglit ("");
1604   llmsglit ("They may be used to indicate where the representation of a "
1605             "user-defined type is hidden, to limit where a global variable may "
1606             "be used or modified, to constrain what a function implementation "
1607             "may do to its parameters, and to express checked assumptions about "
1608             "variables, types, structure fields, function parameters, and "
1609             "function results.");
1610   llmsglit ("");
1611   llmsglit ("Annotations are introduced by \"/*@\". The role of the @ may be "
1612             "played by any printable character, selected using -commentchar <char>.");
1613   llmsglit ("");
1614   llmsglit ("Consult the User's Guide for descriptions of checking associated with each annotation.");
1615   llmsglit ("");
1616   llmsglit ("Globals: (in function declarations)");
1617   llmsglit ("   /*@globals <globitem>,+ @*/");
1618   llmsglit ("      globitem is an identifier, internalState or fileSystem");
1619   llmsglit ("");
1620   llmsglit ("Modifies: (in function declarations)");
1621   llmsglit ("   /*@modifies <moditem>,+ @*/");
1622   llmsglit ("      moditem is an lvalue");
1623   llmsglit ("   /*@modifies nothing @*/");
1624   llmsglit ("   /*@*/   (Abbreviation for no globals and modifies nothing.)");
1625   llmsglit ("");
1626   llmsglit ("Iterators:");
1627   llmsglit ("   /*@iter <identifier> (<parameter-type-list>) @*/ - declare an iterator");
1628   llmsglit ("");
1629   llmsglit ("Constants:");
1630   llmsglit ("   /*@constant <declaration> @*/ - declares a constant");
1631   llmsglit ("");
1632   llmsglit ("Alternate Types:");
1633   llmsglit ("   /*@alt <basic-type>,+ @*/");
1634   llmsglit ("   (e.g., int /*@alt char@*/ is a type matching either int or char)");
1635   llmsglit ("");
1636   llmsglit ("Declarator Annotations");
1637   llmsglit ("");
1638   llmsglit ("Type Definitions:");
1639   llmsglit ("   /*@abstract@*/ - representation is hidden from clients");
1640   llmsglit ("   /*@concrete@*/ - representation is visible to clients");
1641   llmsglit ("   /*@immutable@*/ - instances of the type cannot change value");
1642   llmsglit ("   /*@mutable@*/ - instances of the type can change value");
1643   llmsglit ("   /*@refcounted@*/ - reference counted type");
1644   llmsglit ("");
1645   llmsglit ("Global Variables:");
1646   llmsglit ("   /*@unchecked@*/ - weakest checking for global use");
1647   llmsglit ("   /*@checkmod@*/ - check modification by not use of global");
1648   llmsglit ("   /*@checked@*/ - check use and modification of global");
1649   llmsglit ("   /*@checkedstrict@*/ - check use of global strictly");
1650   llmsglit ("");
1651   llmsglit ("Memory Management:");
1652   llmsglit ("   /*@dependent@*/ - a reference to externally-owned storage");
1653   llmsglit ("   /*@keep@*/ - a parameter that is kept by the called function");
1654   llmsglit ("   /*@killref@*/ - a refcounted parameter, killed by the call");
1655   llmsglit ("   /*@only@*/ - an unshared reference");
1656   llmsglit ("   /*@owned@*/ - owner of storage that may be shared by /*@dependent@*/ references");
1657   llmsglit ("   /*@shared@*/ - shared reference that is never deallocated");
1658   llmsglit ("   /*@temp@*/ - temporary parameter");
1659   llmsglit ("");
1660   llmsglit ("Aliasing:");
1661   llmsglit ("   /*@unique@*/ - may not be aliased by any other visible reference");
1662   llmsglit ("   /*@returned@*/ - may be aliased by the return value");
1663   llmsglit ("");
1664   llmsglit ("Exposure:");
1665   llmsglit ("   /*@observer@*/ - reference that cannot be modified");
1666   llmsglit ("   /*@exposed@*/ - exposed reference to storage in another object");
1667   llmsglit ("");
1668   llmsglit ("Definition State:");
1669   llmsglit ("   /*@out@*/ - storage reachable from reference need not be defined");
1670   llmsglit ("   /*@in@*/ - all storage reachable from reference must be defined");
1671   llmsglit ("   /*@partial@*/ - partially defined, may have undefined fields");
1672   llmsglit ("   /*@reldef@*/ - relax definition checking");
1673   llmsglit ("");
1674   llmsglit ("Global State: (for globals lists, no /*@, since list is already in /*@\'s)");
1675   llmsglit ("   undef - variable is undefined before the call");
1676   llmsglit ("   killed - variable is undefined after the call");
1677   llmsglit ("");
1678   llmsglit ("Null State:");
1679   llmsglit ("   /*@null@*/ - possibly null pointer");
1680   llmsglit ("   /*@notnull@*/ - non-null pointer");
1681   llmsglit ("   /*@relnull@*/ - relax null checking");
1682   llmsglit ("");
1683   llmsglit ("Null Predicates:");
1684   llmsglit ("   /*@truenull@*/ - if result is TRUE, first parameter is NULL");
1685   llmsglit ("   /*@falsenull@*/ - if result is TRUE, first parameter is not NULL");
1686   llmsglit ("");
1687   llmsglit ("Execution:");
1688   llmsglit ("   /*@exits@*/ - function never returns");
1689   llmsglit ("   /*@mayexit@*/ - function may or may not return");
1690   llmsglit ("   /*@trueexit@*/ - function does not return if first parameter is TRUE");
1691   llmsglit ("   /*@falseexit@*/ - function does not return if first parameter if FALSE");
1692   llmsglit ("   /*@neverexit@*/ - function always returns");
1693   llmsglit ("");
1694   llmsglit ("Side-Effects:");
1695   llmsglit ("   /*@sef@*/ - corresponding actual parameter has no side effects");
1696   llmsglit ("");
1697   llmsglit ("Declaration:");
1698   llmsglit ("   /*@unused@*/ - need not be used (no unused errors reported)");
1699   llmsglit ("   /*@external@*/ - defined externally (no undefined error reported)");
1700   llmsglit ("");
1701   llmsglit ("Case:");
1702   llmsglit ("   /*@fallthrough@*/ - fall-through case");
1703   llmsglit ("");
1704   llmsglit ("Break:");
1705   llmsglit ("   /*@innerbreak@*/ - break is breaking an inner loop or switch");
1706   llmsglit ("   /*@loopbreak@*/ - break is breaking a loop");
1707   llmsglit ("   /*@switchbreak@*/ - break is breaking a switch");
1708   llmsglit ("   /*@innercontinue@*/ - continue is continuing an inner loop");
1709   llmsglit ("");
1710   llmsglit ("Unreachable Code:");
1711   llmsglit ("   /*@notreached@*/ - statement may be unreachable.");
1712   llmsglit ("");
1713   llmsglit ("Special Functions:");
1714   llmsglit ("   /*@printflike@*/ - check variable arguments like printf");
1715   llmsglit ("   /*@scanflike@*/ - check variable arguments like scanf");
1716 }
1717
1718 void
1719 printComments (void)
1720 {
1721   llmsglit ("Control Comments");
1722   llmsglit ("----------------");
1723   llmsglit ("");
1724   llmsglit ("Setting Flags");
1725   llmsglit ("");
1726   llmsglit ("Most flags (all except those characterized as \"globally-settable only\") can be set locally using control comments. A control comment can set flags locally to override the command line settings. The original flag settings are restored before processing the next file.");
1727   llmsglit ("");
1728   llmsglit ("The syntax for setting flags in control comments is the same as that of the command line, except that flags may also be preceded by = to restore their setting to the original command-line value. For instance,");
1729   llmsglit ("   /*@+boolint -modifies =showfunc@*/");
1730   llmsglit ("sets boolint on (this makes bool and int indistinguishable types), sets modifies off (this prevents reporting of modification errors), and sets showfunc to its original setting (this controls  whether or not the name of a function is displayed before a message).");
1731   llmsglit ("");
1732   llmsglit ("Error Suppression");
1733   llmsglit ("");
1734   llmsglit ("Several comments are provided for suppressing messages. In general, it is usually better to use specific flags to suppress a particular error permanently, but the general error suppression flags may be more convenient for quickly suppressing messages for code that will be corrected or documented later.");
1735   llmsglit ("");
1736   llmsglit ("/*@ignore@*/ ... /*@end@*/");
1737   llgenindentmsgnoloc
1738     (cstring_makeLiteral 
1739      ("No errors will be reported in code regions between /*@ignore@*/ and /*@end@*/. These comments can be used to easily suppress an unlimited number of messages."));
1740   llmsglit ("/*@i@*/");
1741     llgenindentmsgnoloc
1742     (cstring_makeLiteral 
1743      ("No errors will be reported from an /*@i@*/ comment to the end of the line."));
1744   llmsglit ("/*@i<n>@*/");
1745   llgenindentmsgnoloc
1746     (cstring_makeLiteral 
1747      ("No errors will be reported from an /*@i<n>@*/ (e.g., /*@i3@*/) comment to the end of the line. If there are not exactly n errors suppressed from the comment point to the end of the line, LCLint will report an error."));
1748   llmsglit ("/*@t@*/, /*@t<n>@*/");
1749   llgenindentmsgnoloc
1750     (cstring_makeLiteral 
1751      ("Like i and i<n>, except controlled by +tmpcomments flag. These can be used to temporarily suppress certain errors. Then, -tmpcomments can be set to find them again."));
1752   llmsglit ("");
1753   llmsglit ("Type Access");
1754   llmsglit ("");
1755   llmsglit ("/*@access <type>@*/"); 
1756   llmsglit ("   Allows the following code to access the representation of <type>");
1757   llmsglit ("/*@noaccess <type>@*/");
1758   llmsglit ("   Hides the representation of <type>");
1759   llmsglit ("");
1760   llmsglit ("Macro Expansion");
1761   llmsglit ("");
1762   llmsglit ("/*@notfunction@*/");
1763   llgenindentmsgnoloc 
1764     (cstring_makeLiteral
1765      ("Indicates that the next macro definition is not intended to be a "
1766       "function, and should be expanded in line instead of checked as a "
1767       "macro function definition."));
1768 }
1769
1770   
1771 void
1772 printFlags (void)
1773 {
1774   llmsglit ("Flag Categories");
1775   llmsglit ("---------------");
1776   listAllCategories ();
1777   llmsglit ("\nTo see the flags in a flag category, do\n   lclint -help flags <category>");
1778   llmsglit ("To see a list of all flags in alphabetical order, do\n   lclint -help flags alpha");
1779   llmsglit ("To see a full description of all flags, do\n   lclint -help flags full");
1780 }
1781
1782 void
1783 printMaintainer (void)
1784 {
1785   llmsg (message ("Maintainer: %s", cstring_makeLiteralTemp (LCLINT_MAINTAINER)));
1786   llmsglit (LCL_COMPILE);
1787 }
1788
1789 void
1790 printMail (void)
1791 {
1792   llmsglit ("Mailing Lists");
1793   llmsglit ("-------------");
1794   llmsglit ("");
1795   llmsglit ("There are two mailing lists associated with LCLint: ");
1796   llmsglit ("");
1797   llmsglit ("   lclint-announce@virginia.edu");
1798   llmsglit ("");
1799   llmsglit ("      Reserved for announcements of new releases and bug fixes.");
1800   llmsglit ("      To subscribe, send a message to majordomo@virginia.edu with body: ");
1801   llmsglit ("           subscribe lclint-announce");
1802   llmsglit ("");
1803   llmsglit ("   lclint-interest@virginia.edu");
1804   llmsglit ("");
1805   llmsglit ("      Informal discussions on the use and development of lclint.");
1806   llmsglit ("      To subscribe, send a message to majordomo@virginia.edu with body: ");
1807   llmsglit ("           subscribe lclint-interest");
1808 }
1809
1810 void
1811 printReferences (void)
1812 {
1813   llmsglit ("References");
1814   llmsglit ("----------");
1815   llmsglit ("");
1816   llmsglit ("The LCLint web site is http://lclint.cs.virginia.edu");
1817   llmsglit ("");
1818   llmsglit ("Technical papers relating to LCLint include:");
1819   llmsglit ("");
1820   llmsglit ("   David Evans. \"Static Detection of Dynamic Memory Errors\".");  
1821   llmsglit ("   SIGPLAN Conference on Programming Language Design and ");
1822   llmsglit ("   Implementation (PLDI '96), Philadelphia, PA, May 1996.");
1823   llmsglit ("");
1824   llmsglit ("   David Evans, John Guttag, Jim Horning and Yang Meng Tan. ");
1825   llmsglit ("   \"LCLint: A Tool for Using Specifications to Check Code\".");
1826   llmsglit ("   SIGSOFT Symposium on the Foundations of Software Engineering,");
1827   llmsglit ("   December 1994.");
1828   llmsglit ("");
1829   llmsglit ("A general book on Larch is:");
1830   llmsglit ("");
1831   llmsglit ("   Guttag, John V., Horning, James J., (with Garland, S. J., Jones, ");
1832   llmsglit ("   K. D., Modet, A., and Wing, J. M.), \"Larch: Languages and Tools ");
1833   llmsglit ("   for Formal Specification\", Springer-Verlag, 1993.");
1834 }
1835
1836 void
1837 describePrefixCodes (void)
1838 {
1839   llmsglit ("Prefix Codes");
1840   llmsglit ("------------");
1841   llmsglit ("");
1842   llmsglit ("These characters have special meaning in name prefixes:");
1843   llmsglit ("");
1844   llmsg (message ("   %h  Any uppercase letter [A-Z]", PFX_UPPERCASE));
1845   llmsg (message ("   %h  Any lowercase letter [a-z]", PFX_LOWERCASE));
1846   llmsg (message ("   %h  Any character (valid in a C identifier)", PFX_ANY));
1847   llmsg (message ("   %h  Any digit [0-9]", PFX_DIGIT));
1848   llmsg (message ("   %h  Any non-uppercase letter [a-z0-9_]", PFX_NOTUPPER));
1849   llmsg (message ("   %h  Any non-lowercase letter [A-Z0-9_]", PFX_NOTLOWER));
1850   llmsg (message ("   %h  Any letter [A-Za-z]", PFX_ANYLETTER));
1851   llmsg (message ("   %h  Any letter or digit [A-Za-z0-9]", PFX_ANYLETTERDIGIT));
1852   llmsglit ("   *  Zero or more repetitions of the previous character class until the end of the name");
1853 }
1854
1855 void
1856 describeVars (void)
1857 {
1858   cstring eval;
1859   char *def;
1860
1861   eval = context_getLarchPath ();
1862   def = osd_getEnvironmentVariable (LARCH_PATH);
1863
1864   if (def != NULL || 
1865       !cstring_equal (eval, cstring_fromChars (DEFAULT_LARCHPATH)))
1866     {
1867       llmsg (message ("LARCH_PATH = %s", eval));
1868     }
1869   else
1870     {
1871       llmsg (message ("LARCH_PATH = <not set> (default = %s)",
1872                       cstring_fromChars (DEFAULT_LARCHPATH)));
1873     }
1874   
1875   llmsglit ("   --- path used to find larch initialization files and LSL traits");
1876
1877   eval = context_getLCLImportDir ();
1878   def = osd_getEnvironmentVariable (LCLIMPORTDIR);
1879
1880   if (def != NULL ||
1881       !cstring_equal (eval, cstring_fromChars (DEFAULT_LCLIMPORTDIR)))
1882     {
1883       llmsg (message ("%q = %s", cstring_makeLiteral (LCLIMPORTDIR), eval));
1884     }
1885   else
1886     {
1887       llmsg (message ("%s = <not set, default: %s>", cstring_makeLiteralTemp (LCLIMPORTDIR), 
1888                       cstring_makeLiteralTemp (DEFAULT_LCLIMPORTDIR))); 
1889     }
1890   
1891   llmsglit ("   --- directory containing lcl standard library files "
1892             "(import with < ... >)");;
1893
1894   {
1895     cstring dirs = context_getString (FLG_SYSTEMDIRS);
1896     llmsg (message 
1897            ("systemdirs = %s (set by include envirnoment variable or -systemdirs)",
1898             dirs));
1899
1900   }
1901 }
1902
1903 void
1904 interrupt (int i)
1905 {
1906   switch (i)
1907     {
1908     case SIGINT:
1909       fprintf (stderr, "*** Interrupt\n");
1910       llexit (LLINTERRUPT);
1911     case SIGSEGV:
1912       {
1913         cstring loc;
1914         
1915         /* Cheat when there are parse errors */
1916         checkParseError (); 
1917         
1918         fprintf (stderr, "*** Segmentation Violation\n");
1919         
1920         /* Don't catch it if fileloc_unparse causes a signal */
1921         (void) signal (SIGSEGV, NULL);
1922
1923         loc = fileloc_unparse (g_currentloc);
1924         
1925         fprintf (stderr, "*** Location (not trusted): %s\n", 
1926                  cstring_toCharsSafe (loc));
1927         cstring_free (loc);
1928         printCodePoint ();
1929         fprintf (stderr, "*** Please report bug to %s\n", LCLINT_MAINTAINER);
1930         exit (LLGIVEUP);
1931       }
1932     default:
1933       fprintf (stderr, "*** Signal: %d\n", i);
1934       /*@-mustfree@*/
1935       fprintf (stderr, "*** Location (not trusted): %s\n", 
1936                cstring_toCharsSafe (fileloc_unparse (g_currentloc)));
1937       /*@=mustfree@*/
1938       printCodePoint ();
1939       fprintf (stderr, "*** Please report bug to %s ***\n", LCLINT_MAINTAINER);
1940       exit (LLGIVEUP);
1941     }
1942 }
1943
1944 void
1945 cleanupFiles (void)
1946 {
1947   static bool doneCleanup = FALSE;
1948
1949   /* make sure this is only called once! */
1950
1951   if (doneCleanup) return;
1952
1953   setCodePoint ();
1954
1955   if (context_getFlag (FLG_KEEP))
1956     {
1957       check (fputs ("Temporary files kept:\n", stderr) != EOF);
1958       fileTable_printTemps (context_fileTable ());
1959     }
1960   else
1961     {
1962 # ifdef WIN32
1963       int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
1964       
1965       if (nfiles != 0) 
1966         {
1967           llbug (message ("Files unclosed: %d", nfiles));
1968         }
1969 # endif
1970       fileTable_cleanup (context_fileTable ());
1971     }
1972
1973   doneCleanup = TRUE;
1974 }
1975
1976 /*
1977 ** cleans up temp files (if necessary)
1978 ** exits lclint
1979 */
1980
1981 /*@exits@*/ void
1982 llexit (int status)
1983 {
1984 # ifdef WIN32
1985   if (status == LLFAILURE) 
1986     {
1987       _fcloseall ();
1988     }
1989 # endif
1990
1991   cleanupFiles ();
1992
1993   if (status != LLFAILURE)
1994     {
1995       context_destroyMod ();
1996       exprNode_destroyMod ();
1997       
1998       sRef_destroyMod ();
1999       uentry_destroyMod ();
2000       typeIdSet_destroyMod ();
2001       
2002 # ifdef USEDMALLOC
2003       dmalloc_shutdown ();
2004 # endif
2005     }
2006
2007   exit ((status == LLSUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE);
2008 }
2009
2010 void
2011 loadrc (FILE *rcfile, cstringSList *passThroughArgs)
2012 {
2013   char *s = mstring_create (MAX_LINE_LENGTH);
2014   char *os = s;
2015
2016   DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2017
2018   s = os;
2019
2020   while (fgets (s, MAX_LINE_LENGTH, rcfile) != NULL)
2021     {
2022       char c;
2023       bool set = FALSE;     
2024       char *thisflag;
2025       flagcode opt;
2026
2027       DPRINTF (("Line: %s", s));
2028       DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2029       incLine ();
2030             
2031       while (*s == ' ' || *s == '\t' || *s == '\n') 
2032         {
2033           s++;
2034           incColumn ();
2035         }
2036       
2037       while (*s != '\0')
2038         {
2039           bool escaped = FALSE;
2040           bool quoted = FALSE;
2041           c = *s;
2042
2043           DPRINTF (("Process: %s", s));
2044           DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2045           /* comment characters */
2046           if (c == '#' || c == ';' || c == '\n') 
2047             {
2048               /*@innerbreak@*/
2049               break;
2050             }
2051           
2052           if (c == '-' || c == '+')
2053             {
2054               set = (c == '+');
2055             }
2056           else
2057             {
2058               showHerald ();
2059               llerror (FLG_SYNTAX, 
2060                        message ("Bad flag syntax (+ or - expected, "
2061                                 "+ is assumed): %s", 
2062                                 cstring_fromChars (s)));
2063               s--;
2064               set = TRUE;
2065             }
2066           
2067           s++;
2068           incColumn ();
2069           
2070           thisflag = s;
2071           
2072           while ((c = *s) != '\0')
2073             { /* remember to handle spaces and quotes in -D and -U ... */
2074               if (escaped)
2075                 {
2076                   escaped = FALSE;
2077                 }
2078               else if (quoted)
2079                 {
2080                   if (c == '\\')
2081                     {
2082                       escaped = TRUE;
2083                     }
2084                   else if (c == '\"')
2085                     {
2086                       quoted = FALSE;
2087                     }
2088                   else
2089                     {
2090                       ;
2091                     }
2092                 }
2093               else if (c == '\"')
2094                 {
2095                   quoted = TRUE;
2096                 }
2097               else
2098                 {
2099                  if (c == ' ' || c == '\t' || c == '\n')
2100                    {
2101                      /*@innerbreak@*/ break;
2102                    }
2103                }
2104                   
2105               s++; 
2106               incColumn ();
2107             }
2108
2109           DPRINTF (("Nulling: %c", *s));
2110           *s = '\0';
2111
2112           if (mstring_isEmpty (thisflag))
2113             {
2114               llfatalerror (message ("Missing flag: %s",
2115                                      cstring_fromChars (os)));
2116             }
2117
2118           DPRINTF (("Flag: %s", thisflag));
2119
2120           opt = identifyFlag (cstring_fromChars (thisflag));
2121           
2122           if (flagcode_isSkip (opt))
2123             {
2124               ;
2125             }
2126           else if (flagcode_isInvalid (opt))
2127             {
2128               if (isMode (cstring_fromChars (thisflag)))
2129                 {
2130                   context_setMode (cstring_fromChars (thisflag));
2131                 }
2132               else
2133                 {
2134                   llerror (FLG_BADFLAG,
2135                            message ("Unrecognized option: %s", 
2136                                     cstring_fromChars (thisflag)));
2137                 }
2138             }
2139           else
2140             {
2141               context_userSetFlag (opt, set);
2142
2143               if (flagcode_hasArgument (opt))
2144                 {
2145                   if (opt == FLG_HELP)
2146                     {
2147                       showHerald ();
2148                       llerror (FLG_BADFLAG,
2149                                message ("Cannot use help in rc files"));
2150                     }
2151                   else if (flagcode_isPassThrough (opt)) /* -D or -U */
2152                     {
2153                       cstring arg = cstring_fromCharsNew (thisflag);
2154                       cstring_markOwned (arg);
2155                       *passThroughArgs = cstringSList_add (*passThroughArgs, arg);
2156                       DPRINTF (("Pass through: %s",
2157                                 cstringSList_unparse (*passThroughArgs)));
2158                     }
2159                   else if (opt == FLG_INCLUDEPATH 
2160                            || opt == FLG_SPECPATH)
2161                     {
2162                       cstring dir = cstring_suffix (cstring_fromChars (thisflag), 1); /* skip over I/S */
2163                                       
2164                       switch (opt)
2165                         {
2166                         case FLG_INCLUDEPATH:
2167                           cppAddIncludeDir (dir);
2168                           /*@switchbreak@*/ break;
2169                         case FLG_SPECPATH:
2170                           /*@-mustfree@*/
2171                           g_localSpecPath = cstring_toCharsSafe
2172                             (message ("%s:%s", cstring_fromChars (g_localSpecPath), dir));
2173                           /*@=mustfree@*/
2174                           /*@switchbreak@*/ break;
2175                           BADDEFAULT;
2176                         }
2177                     }
2178                   else if (flagcode_hasString (opt)
2179                            || flagcode_hasValue (opt)
2180                            || opt == FLG_INIT || opt == FLG_OPTF)
2181                     {
2182                       cstring extra = cstring_undefined;
2183                       char *rest, *orest;
2184                       char rchar;
2185                       
2186                       *s = c;
2187                       rest = mstring_copy (s);
2188                       DPRINTF (("Here: rest = %s", rest));
2189                       orest = rest;
2190                       *s = '\0';
2191                       
2192                       while ((rchar = *rest) != '\0'
2193                              && (isspace ((int) rchar)))
2194                         {
2195                           rest++;
2196                           s++;
2197                         }
2198                       
2199                       DPRINTF (("Yo: %s", rest));
2200
2201                       while ((rchar = *rest) != '\0' 
2202                              && !isspace ((int) rchar))
2203                         {
2204                           extra = cstring_appendChar (extra, rchar);
2205                           rest++; 
2206                           s++;
2207                         }
2208                       
2209                       DPRINTF (("Yo: %s", extra));
2210                       sfree (orest);
2211
2212                       if (cstring_isUndefined (extra))
2213                         {
2214                           showHerald ();
2215                           llerror 
2216                             (FLG_BADFLAG,
2217                              message
2218                              ("Flag %s must be followed by an argument",
2219                               flagcode_unparse (opt)));
2220                         }
2221                       else
2222                         {
2223                           s--;
2224                           
2225                           DPRINTF (("Here we are: %s", extra));
2226
2227                           if (flagcode_hasValue (opt))
2228                             {
2229                               DPRINTF (("Set value flag: %s", extra));
2230                               setValueFlag (opt, extra);
2231                               cstring_free (extra);
2232                             }
2233                           else if (opt == FLG_OPTF)
2234                             {
2235                               FILE *innerf = fopen (cstring_toCharsSafe (extra), "r");
2236                               cstring_markOwned (extra);
2237                               
2238                               if (innerf != NULL)
2239                                 {
2240                                   fileloc fc = g_currentloc;
2241                                   g_currentloc = fileloc_createRc (extra);
2242                                   loadrc (innerf, passThroughArgs);
2243                                   fileloc_reallyFree (g_currentloc);
2244                                   g_currentloc = fc;
2245                                 }
2246                               else 
2247                                 {
2248                                   showHerald ();
2249                                   llerror
2250                                     (FLG_SYNTAX, 
2251                                      message ("Options file not found: %s", 
2252                                               extra));
2253                                 }
2254                             }
2255                           else if (opt == FLG_INIT)
2256                             {
2257 # ifndef NOLCL
2258                               llassert (initFile == NULL);
2259                               
2260                               initFile = tsource_create 
2261                                 (cstring_toCharsSafe (extra), 
2262                                  LCLINIT_SUFFIX, FALSE);
2263                               cstring_markOwned (extra);
2264 # else
2265                               cstring_free (extra);
2266 # endif
2267                             }
2268                           else if (flagcode_hasString (opt))
2269                             {
2270                               if (cstring_firstChar (extra) == '"')
2271                                 {
2272                                   if (cstring_lastChar (extra) == '"')
2273                                     {
2274                                       char *extras = cstring_toCharsSafe (extra);
2275                                       
2276                                       llassert (extras[strlen(extras) - 1] == '"');
2277                                       extras[strlen(extras) - 1] = '\0';
2278                                       extra = cstring_fromChars (extras + 1); 
2279                                       DPRINTF (("Remove quites: %s", extra));
2280                                     }
2281                                   else
2282                                     {
2283                                       llerror
2284                                         (FLG_SYNTAX, 
2285                                          message ("Unmatched \" in option string: %s", 
2286                                                   extra));
2287                                     }
2288                                 }
2289                               
2290                               setStringFlag (opt, extra);
2291                             }
2292                           else
2293                             {
2294                               cstring_free (extra);
2295                               BADEXIT;
2296                             }
2297                         }
2298                     }
2299                   else
2300                     {
2301                       BADEXIT;
2302                     }
2303                 }
2304             }
2305           
2306           *s = c;
2307           DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2308           while ((c == ' ') || (c == '\t'))
2309             {
2310               c = *(++s);
2311               incColumn ();
2312             } 
2313         }
2314       DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2315       s = os;
2316     }
2317
2318   DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2319   sfree (os); 
2320   check (fclose (rcfile) == 0);
2321 }
2322
2323 static fileIdList preprocessFiles (fileIdList fl)
2324   /*@modifies fileSystem@*/
2325 {
2326   bool msg = (context_getFlag (FLG_SHOWSCAN) && fileIdList_size (fl) > 10);
2327   int skip = (fileIdList_size (fl) / 5);
2328   int filesprocessed = 0;
2329   fileIdList dfiles = fileIdList_create ();
2330
2331   fileloc_free (g_currentloc);
2332   g_currentloc = fileloc_createBuiltin ();
2333
2334   fileIdList_elements (fl, fid)
2335     {
2336       char *ppfname = cstring_toCharsSafe (fileName (fid));
2337
2338       if (!(osd_fileIsReadable (ppfname)))
2339         {
2340           lldiagmsg (message ("Cannot open file: %s",
2341                               cstring_fromChars (ppfname)));
2342         }
2343       else
2344         {
2345           fileId  dfile = fileTable_addCTempFile (context_fileTable (), fid);
2346           
2347           llassert (!mstring_isEmpty (ppfname));
2348           
2349           if (msg)
2350             {
2351               if ((filesprocessed % skip) == 0) 
2352                 {
2353                   if (filesprocessed == 0) {
2354                     fprintf (stderr, " ");
2355                   }
2356                   else {
2357                     fprintf (stderr, ".");
2358                   }
2359                   
2360                   (void) fflush (stderr);
2361                 }
2362               filesprocessed++;
2363             }
2364
2365           if (cppProcess (cstring_fromChars (ppfname), 
2366                           fileName (dfile)) != 0) 
2367             {
2368               llfatalerror (message ("Preprocessing error for file: %s", 
2369                                      rootFileName (fid)));
2370             }
2371           
2372           fileIdList_add (dfiles, dfile);
2373         }
2374     } end_fileIdList_elements; 
2375     
2376     return dfiles;
2377 }
This page took 0.285294 seconds and 5 git commands to generate.