]> andersk Git - splint.git/blob - src/llmain.c
Finshed basic merge. Still trying to get it through the test suit.
[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   bool expsuccess;
564   tsource *sourceFile = (tsource *) 0;
565  
566   fileIdList dercfiles;
567   cstringSList fl = cstringSList_undefined;
568   cstringSList passThroughArgs = cstringSList_undefined;
569   fileIdList cfiles;
570   fileIdList lclfiles;
571   clock_t before, lcltime, libtime, pptime, cptime, rstime;
572   int i = 0;
573
574   g_msgstream = stdout;
575
576   (void) signal (SIGINT, interrupt);
577   (void) signal (SIGSEGV, interrupt); 
578
579   cfiles = fileIdList_create ();
580   lclfiles = fileIdList_create ();
581
582   flags_initMod ();
583   typeIdSet_initMod ();
584   cppReader_initMod ();
585
586   setCodePoint ();
587
588   g_currentloc = fileloc_createBuiltin ();
589
590   before = clock ();
591   context_initMod ();
592   context_setInCommandLine ();
593
594   if (argc <= 1)
595     {
596       showHelp ();
597       llexit (LLGIVEUP);
598     }
599
600   setCodePoint ();
601   yydebug = 0;
602
603   /*
604   ** Add include directories from environment.
605   */
606
607   {
608     char *incval = mstring_copy (osd_getEnvironmentVariable (INCLUDE_VAR));
609
610     if (incval != NULL)
611       {
612         /*
613         ** Each directory on the include path is a system include directory.
614         */
615
616         DPRINTF (("include: %s", incval));
617         context_setString (FLG_SYSTEMDIRS, cstring_fromCharsNew (incval));
618
619         while (incval != NULL)
620           {
621             char *nextsep = strchr (incval, SEPCHAR);
622
623             if (nextsep != NULL)
624               {
625                 cstring dir;
626                 *nextsep = '\0';
627                 dir = cstring_fromCharsNew (incval);
628
629                 if (cstring_length (dir) == 0
630                     || !isalpha ((int) cstring_firstChar (dir)))
631                   {
632                     /* 
633                     ** win32 environment values can have special values,
634                     ** ignore them
635                     */
636                   }
637                 else
638                   {
639                     DPRINTF (("Add include: %s", dir));
640                     cppAddIncludeDir (dir);
641                   }
642
643                 *nextsep = SEPCHAR;
644                 incval = nextsep + 1;
645                 cstring_free (dir);
646               }
647             else
648               {
649                 break;
650               }
651           }
652       }
653   }
654
655   /*
656   ** check RCFILE for default flags
657   */
658
659   {
660     cstring home = cstring_fromChars (osd_getHomeDir ());
661     char *fname  = NULL;
662     FILE *rcfile;
663     bool defaultf = TRUE;
664     bool nof = FALSE;
665
666     for (i = 1; i < argc; i++)
667       {
668         char *thisarg;
669         thisarg = argv[i];
670         
671         if (*thisarg == '-' || *thisarg == '+')
672           {
673             thisarg++;
674
675             if (mstring_equal (thisarg, "nof"))
676               {
677                 nof = TRUE;
678               }
679             else if (mstring_equal (thisarg, "f"))
680               {
681                 if (++i < argc)
682                   {
683                     defaultf = FALSE;
684                     fname = argv[i];
685                     rcfile = fopen (fname, "r");
686
687                     if (rcfile != NULL)
688                       {
689                         fileloc oloc = g_currentloc;
690                         
691                         g_currentloc = fileloc_createRc (cstring_fromChars (fname));
692                         loadrc (rcfile, &passThroughArgs);
693                         fileloc_reallyFree (g_currentloc); 
694                         g_currentloc = oloc;
695                       }
696                     else 
697                       {
698                         showHerald ();
699                         lldiagmsg (message ("Options file not found: %s", 
700                                             cstring_fromChars (fname)));
701                       }
702                   }
703                 else
704                   llfatalerror
705                     (cstring_makeLiteral ("Flag f to select options file "
706                                           "requires an argument"));
707               }
708             else
709               {
710                 ; /* wait to process later */
711               }
712           }
713       }
714     
715     if (fname == NULL)
716       {
717         if (!cstring_isEmpty (home)) {
718           fname = cstring_toCharsSafe (message ("%s%h%s", home, CONNECTCHAR,
719                                                 cstring_fromChars (RCFILE)));
720           mstring_markFree (fname);
721         }
722       }
723
724     setCodePoint ();
725
726     if (!nof && defaultf)
727       {
728         if (!mstring_isEmpty (fname)) {
729           rcfile = fopen (fname, "r");
730           
731           if (rcfile != NULL)
732             {
733               fileloc oloc = g_currentloc;
734               
735               g_currentloc = fileloc_createRc (cstring_fromChars (fname));
736               loadrc (rcfile, &passThroughArgs);
737               fileloc_reallyFree (g_currentloc);
738               g_currentloc = oloc;
739             }
740         }
741
742 # if defined(MSDOS) || defined(OS2)
743         fname = cstring_toCharsSafe (message ("%s",
744                                               cstring_fromChars (RCFILE)));
745 # else
746         fname = cstring_toCharsSafe (message ("./%s", 
747                                               cstring_fromChars (RCFILE)));
748 # endif
749
750         rcfile = fopen (fname, "r");
751
752         if (rcfile != NULL)
753           {
754             fileloc oloc = g_currentloc;
755
756             g_currentloc = fileloc_createRc (cstring_fromChars (fname));
757             loadrc (rcfile, &passThroughArgs);
758             fileloc_reallyFree (g_currentloc);
759             g_currentloc = oloc;
760           }
761
762         sfree (fname); 
763       }
764   }
765   
766   setCodePoint ();
767   
768   for (i = 1; i < argc; i++)
769     {
770       char *thisarg;
771       flagcode opt;
772       
773       thisarg = argv[i];
774       
775       if (showhelp)
776         {
777           if (allhelp)
778             {
779               showHerald ();
780             }
781           
782           allhelp = FALSE;
783           
784           if (*thisarg == '-' || *thisarg == '+')
785             {
786               thisarg++;        /* skip '-' */
787             }
788           if (mstring_equal (thisarg, "modes"))
789             {
790               llmsg (describeModes ());
791             }
792           else if (mstring_equal (thisarg, "vars")
793                    || mstring_equal (thisarg, "env"))
794             {
795               describeVars ();
796             }
797           else if (mstring_equal (thisarg, "annotations"))
798             {
799               printAnnotations ();
800             }
801           else if (mstring_equal (thisarg, "parseerrors"))
802             {
803               printParseErrors ();
804             }
805           else if (mstring_equal (thisarg, "comments"))
806             {
807               printComments ();
808             }
809           else if (mstring_equal (thisarg, "prefixcodes"))
810             {
811               describePrefixCodes ();
812             }
813           else if (mstring_equal (thisarg, "references") 
814                    || mstring_equal (thisarg, "refs"))
815             {
816               printReferences ();
817             }
818           else if (mstring_equal (thisarg, "mail"))
819             {
820               printMail ();
821             }
822           else if (mstring_equal (thisarg, "maintainer")
823                    || mstring_equal (thisarg, "version"))
824             {
825               printMaintainer ();
826             }
827           else if (mstring_equal (thisarg, "flags"))
828             {
829               if (i + 1 < argc)
830                 {
831                   char *next = argv[i + 1];
832                   
833                   if (specialFlagsHelp (next))
834                     {
835                       i++;
836                     }
837                   else
838                     {
839                       flagkind k = identifyCategory (cstring_fromChars (next));
840                       
841                       if (k != FK_NONE)
842                         {
843                           printCategory (k);
844                           i++;
845                         }
846                     }
847                 }
848               else
849                 {
850                   printFlags ();
851                 }
852             }
853           else
854             {
855               cstring s = describeFlag (cstring_fromChars (thisarg));
856               
857               if (cstring_isDefined (s))
858                 {
859                   llmsg (s);
860                 }
861             }
862         }
863       else
864         {
865           if (*thisarg == '-' || *thisarg == '+')
866             {
867               bool set = (*thisarg == '+');
868               cstring flagname;
869               
870               thisarg++;        /* skip '-' */
871               flagname = cstring_fromChars (thisarg);
872               
873               opt = identifyFlag (flagname);
874               
875               if (flagcode_isSkip (opt))
876                 {
877                   ;
878                 }
879               else if (flagcode_isInvalid (opt))
880                 {
881                   if (isMode (flagname))
882                     {
883                       context_setMode (flagname);
884                     }
885                   else
886                     {
887                       llgloberror (message ("Unrecognized option: %s", 
888                                             cstring_fromChars (thisarg)));
889                     }
890                 }
891               else
892                 {
893                   context_userSetFlag (opt, set);
894                   
895                   if (flagcode_hasArgument (opt))
896                     {
897                       if (opt == FLG_HELP)
898                         {
899                           showhelp = TRUE;
900                         }
901                       else if (flagcode_isPassThrough (opt)) /* -D or -U */
902                         { 
903                           passThroughArgs = cstringSList_add 
904                             (passThroughArgs, cstring_fromChars (thisarg));
905                         }
906                       else if (flagcode_hasValue (opt))
907                         {
908                           if (++i < argc)
909                             {
910                               setValueFlag (opt, cstring_fromChars (argv[i]));
911                             }
912                           else
913                             {
914                               llfatalerror 
915                                 (message
916                                  ("Flag %s must be followed by a number",
917                                   flagcode_unparse (opt)));
918                             }
919                         } 
920                       else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
921                         {
922                           cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */
923                           
924                           switch (opt)
925                             {
926                             case FLG_INCLUDEPATH:
927                               cppAddIncludeDir (dir);
928                               /*@switchbreak@*/ break;
929                             case FLG_SPECPATH:
930                               /*@-mustfree@*/
931                               g_localSpecPath = cstring_toCharsSafe
932                                 (message ("%s%h%s", 
933                                           cstring_fromChars (g_localSpecPath), 
934                                           SEPCHAR,
935                                           dir));
936                               /*@=mustfree@*/
937                               /*@switchbreak@*/ break;
938                               BADDEFAULT;
939                             }
940                         }
941                       else if (flagcode_hasString (opt)
942                                || opt == FLG_INIT || opt == FLG_OPTF)
943                         {
944                           if (++i < argc)
945                             {
946                               cstring arg = cstring_fromChars (argv[i]);
947                               
948                               if (opt == FLG_OPTF)
949                                 {
950                                   ; /* -f already processed */
951                                 }
952                               else if (opt == FLG_INIT)
953                                 {
954 # ifndef NOLCL
955                                   initFile = tsource_create 
956                                     (cstring_toCharsSafe (arg), 
957                                      LCLINIT_SUFFIX, FALSE);
958 # endif
959                                   break;
960                                 }
961                               else
962                                 {
963                                   setStringFlag (opt, arg);
964                                 }
965                             }
966                           else
967                             {
968                               llfatalerror 
969                                 (message
970                                  ("Flag %s must be followed by a string",
971                                   flagcode_unparse (opt)));
972                             }
973                         }
974                       else
975                         {
976                           /* no argument */
977                         }
978                     }
979                 }
980             }
981           else /* its a filename */
982             {
983               fl = cstringSList_add (fl, cstring_fromChars (thisarg));
984             }
985         }
986     }
987
988   setCodePoint ();  
989
990   /*
991   ** create lists of C and LCL files
992   */
993
994   cstringSList_elements (fl, current)
995     {
996       char *fname = cstring_toCharsSafe (current);
997       char *ext = strrchr (fname, '.');
998
999       if (ext == NULL)
1000         {
1001           /* no extension --- both C and LCL with default extensions */
1002           
1003           addFile (cfiles, message ("%s.c", cstring_fromChars (fname)));
1004           addFile (lclfiles, message ("%s.lcl", cstring_fromChars (fname)));
1005         }
1006       else if (isCext (ext))
1007         {
1008           addFile (cfiles, cstring_fromCharsNew (fname));
1009         }
1010       else 
1011         {
1012           if (!mstring_equal (ext, ".lcl"))
1013             {
1014               lldiagmsg (message ("Unrecognized file extension: %s (assuming lcl)", 
1015                                   cstring_fromChars (ext)));
1016             }
1017
1018           addFile (lclfiles, cstring_fromCharsNew (fname));
1019         }
1020     } end_cstringSList_elements;
1021   
1022   
1023   showHerald ();
1024
1025   
1026   if (showhelp)
1027     {
1028       if (allhelp)
1029         {
1030           showHelp ();
1031         }
1032       fprintf (g_msgstream, "\n");
1033
1034       fileIdList_free (cfiles);
1035       fileIdList_free (lclfiles);
1036       
1037       llexit (LLSUCCESS);
1038     }
1039
1040 # ifdef DOANNOTS
1041   initAnnots ();
1042 # endif
1043
1044   inittime = clock ();
1045
1046   context_resetErrors ();
1047   context_clearInCommandLine ();
1048
1049   anylcl = !fileIdList_isEmpty (lclfiles);
1050
1051   if (context_doMerge ())
1052     {
1053       cstring m = context_getMerge ();
1054
1055       if (context_getFlag (FLG_SHOWSCAN))
1056         {
1057           fprintf (g_msgstream, "< loading %s ", cstring_toCharsSafe (m));
1058         }
1059
1060       loadState (m);
1061
1062       if (context_getFlag (FLG_SHOWSCAN))
1063         {
1064           fprintf (g_msgstream, " >\n");
1065         }
1066
1067       if (!usymtab_existsType (context_getBoolName ()))
1068         {
1069           usymtab_initBool (); 
1070         }
1071     }
1072   else
1073     {
1074       if (!context_getFlag (FLG_NOLIB) && loadStandardState ())
1075         {
1076           ;
1077         }
1078       else
1079         {
1080           ctype_initTable ();
1081         }
1082
1083       /* setup bool type and constants */
1084       usymtab_initBool (); 
1085     }
1086
1087   fileloc_free (g_currentloc);
1088   g_currentloc = fileloc_createBuiltin ();
1089
1090   libtime = clock ();
1091   
1092   if (anylcl)
1093     {
1094 # ifdef NOLCL
1095       llfatalerror (cstring_makeLiteral ("This version of LCLint does not handle LCL files."));
1096 # else
1097       lslProcess (lclfiles);
1098 # endif
1099     }
1100
1101   /*
1102   ** pre-processing
1103   **
1104   ** call the pre-preprocessor and /lib/cpp to generate appropriate
1105   ** files
1106   **
1107   */
1108
1109   context_setInCommandLine ();
1110
1111   cppReader_initialize ();
1112
1113   DPRINTF (("Pass through: %s", cstringSList_unparse (passThroughArgs)));
1114   
1115   cstringSList_elements (passThroughArgs, thisarg) {
1116     handlePassThroughFlag (cstring_toCharsSafe (thisarg));
1117   } end_cstringSList_elements;
1118
1119   cstringSList_free (passThroughArgs);
1120
1121   cleanupMessages ();
1122
1123   cppReader_saveDefinitions ();
1124   
1125   context_clearInCommandLine ();
1126
1127   if (!context_getFlag (FLG_NOPP))
1128     {
1129       llflush ();
1130
1131       if (context_getFlag (FLG_SHOWSCAN))
1132         {
1133           fprintf (stderr, "< preprocessing"); 
1134         }
1135       
1136       lcltime = clock ();
1137
1138       context_setPreprocessing ();
1139       dercfiles = preprocessFiles (cfiles);
1140       context_clearPreprocessing ();
1141
1142       fileIdList_free (cfiles);
1143
1144       if (context_getFlag (FLG_SHOWSCAN))
1145         {
1146           fprintf (stderr, " >\n");
1147         }
1148       
1149       pptime = clock ();
1150     }
1151   else
1152     {
1153       lcltime = clock ();
1154       dercfiles = cfiles;
1155       pptime = clock ();
1156     }
1157   
1158   /*
1159   ** now, check all the corresponding C files
1160   **
1161   ** (for now these are just <file>.c, but after pre-processing
1162   **  will be <tmpprefix>.<file>.c)
1163   */
1164
1165   {
1166 # ifdef WIN32
1167     int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
1168
1169     if (nfiles != 0) 
1170       {
1171         llbug (message ("Files unclosed: %d", nfiles));
1172       }
1173 # endif
1174   }
1175
1176   exprNode_initMod ();
1177
1178   fileIdList_elements (dercfiles, fid)
1179     {
1180       sourceFile = tsource_create (cstring_toCharsSafe (fileName (fid)),
1181                                    C_SUFFIX, TRUE);
1182       context_setFileId (fid);
1183       
1184       /* Open source file  */
1185       
1186       if (sourceFile == (tsource *) 0 || (!tsource_open (sourceFile)))
1187         {
1188           /* previously, this was ignored  ?! */
1189           llbug (message ("Could not open temp file: %s", fileName (fid)));
1190         }
1191       else
1192         {
1193           yyin = sourceFile->file; /*< shared <- only */
1194         
1195           llassert (yyin != NULL);
1196
1197           if (context_getFlag (FLG_SHOWSCAN))
1198             {
1199                       lldiagmsg (message ("< checking %s >", rootFileName (fid)));
1200             }
1201           
1202           /*
1203           ** Every time, except the first time, through the loop,
1204           ** need to call yyrestart to clean up the parse buffer.
1205           */
1206
1207           if (!first_time)
1208             {
1209               (void) yyrestart (yyin);  
1210             }
1211           else
1212             {
1213               first_time = FALSE;
1214             }
1215           
1216           context_enterFile ();
1217           (void) yyparse ();
1218           context_exitFile ();
1219                     
1220           (void) tsource_close (sourceFile);
1221         }
1222       
1223     } end_fileIdList_elements;
1224
1225   cptime = clock ();
1226   
1227   /* process any leftover macros */
1228
1229   context_processAllMacros ();
1230   
1231   /* check everything that was specified was defined */
1232   
1233   /* don't check if no c files were processed ?
1234   **   is this correct behaviour?
1235   */
1236   
1237   if (context_getFlag (FLG_SHOWSCAN))
1238     {
1239       lldiagmsg (cstring_makeLiteral ("< global checks >"));
1240     }
1241
1242   cleanupMessages ();
1243   
1244   if (context_getLinesProcessed () > 0)
1245     {
1246       usymtab_allDefined ();
1247     }
1248
1249   if (context_maybeSet (FLG_TOPUNUSED))
1250     {
1251       uentry ue = usymtab_lookupSafe (cstring_makeLiteralTemp ("main"));
1252
1253       if (uentry_isValid (ue))
1254         {
1255           uentry_setUsed (ue, fileloc_observeBuiltin ());
1256         }
1257
1258       usymtab_allUsed ();
1259     }
1260
1261   if (context_maybeSet (FLG_EXPORTLOCAL))
1262     {
1263       usymtab_exportLocal ();
1264     }
1265
1266   
1267   if (context_maybeSet (FLG_EXPORTHEADER))
1268     {
1269       usymtab_exportHeader ();
1270     }
1271
1272   if (context_getFlag (FLG_SHOWUSES))
1273     {
1274       usymtab_displayAllUses ();
1275     }
1276
1277   context_checkSuppressCounts ();
1278
1279   if (context_doDump ())
1280     {
1281       cstring dump = context_getDump ();
1282
1283       dumpState (dump);
1284     }
1285
1286 # ifdef DOANNOTS
1287   printAnnots ();
1288 # endif
1289
1290   cleanupFiles ();
1291
1292   if (context_getFlag (FLG_SHOWSUMMARY))
1293     {
1294       summarizeErrors (); 
1295     }
1296
1297   
1298   {
1299     bool isQuiet = context_getFlag (FLG_QUIET);
1300     cstring specErrors = cstring_undefined;
1301 # ifndef NOLCL
1302     int nspecErrors = lclNumberErrors ();
1303 # endif
1304     
1305     expsuccess = TRUE;
1306
1307     if (context_neednl ())
1308       fprintf (g_msgstream, "\n");
1309     
1310 # ifndef NOLCL
1311     if (nspecErrors > 0)
1312       {
1313         if (nspecErrors == context_getLCLExpect ())
1314           {
1315             specErrors = 
1316               message ("%d spec error%p found, as expected\n       ", 
1317                        nspecErrors);
1318           }
1319         else
1320           {
1321             if (context_getLCLExpect () > 0)
1322               {
1323                 specErrors = 
1324                   message ("%d spec error%p found, expected %d\n       ", 
1325                            nspecErrors,
1326                            (int) context_getLCLExpect ());
1327               }
1328             else
1329               {
1330                 specErrors = message ("%d spec error%p found\n       ",
1331                                       nspecErrors);
1332                 expsuccess = FALSE;
1333               }
1334           }
1335       }
1336     else
1337         {
1338           if (context_getLCLExpect () > 0)
1339             {
1340               specErrors = message ("No spec errors found, expected %d\n       ", 
1341                                     (int) context_getLCLExpect ());
1342               expsuccess = FALSE;
1343             }
1344         }
1345 # endif
1346
1347       if (context_anyErrors ())
1348         {
1349           if (context_numErrors () == context_getExpect ())
1350             {
1351               if (!isQuiet) {
1352                 llmsg (message ("Finished LCLint checking --- "
1353                                 "%s%d code error%p found, as expected",
1354                                 specErrors, context_numErrors ()));
1355               }
1356             }
1357           else
1358             {
1359               if (context_getExpect () > 0)
1360                 {
1361                   if (!isQuiet) {
1362                     llmsg (message 
1363                            ("Finished LCLint checking --- "
1364                             "%s%d code error%p found, expected %d",
1365                             specErrors, context_numErrors (), 
1366                             (int) context_getExpect ()));
1367                   }
1368
1369                   expsuccess = FALSE;
1370                 }
1371               else
1372                 {
1373                   
1374                   if (!isQuiet) {
1375                     llmsg (message ("Finished LCLint checking --- "
1376                                     "%s%d code error%p found", 
1377                                     specErrors, context_numErrors ()));
1378                   }
1379
1380                   expsuccess = FALSE;
1381                 }
1382             }
1383         }
1384       else
1385         {
1386           if (context_getExpect () > 0)
1387             {
1388               if (!isQuiet) {
1389                 llmsg (message
1390                        ("Finished LCLint checking --- "
1391                         "%sno code errors found, expected %d", 
1392                         specErrors,
1393                         (int) context_getExpect ()));
1394               }
1395
1396               expsuccess = FALSE;
1397             }
1398           else
1399             {
1400               if (context_getLinesProcessed () > 0)
1401                 {
1402                   if (!isQuiet) {
1403                     llmsg (message ("Finished LCLint checking --- %sno code errors found", 
1404                                     specErrors));
1405                   }
1406                 }
1407               else
1408                 {
1409                   if (!isQuiet) {
1410                     llmsg (message ("Finished LCLint checking --- %sno code processed", 
1411                                     specErrors));
1412                   }
1413                 }
1414             }
1415         }
1416
1417       cstring_free (specErrors);
1418   }
1419   
1420   if (context_getFlag (FLG_STATS))
1421     {
1422       clock_t ttime = clock () - before;
1423       int specLines = context_getSpecLinesProcessed ();
1424       
1425       rstime = clock ();
1426       
1427       if (specLines > 0)
1428         {
1429           fprintf (g_msgstream, "%d spec, ", specLines);
1430         }
1431       
1432 # ifndef CLOCKS_PER_SEC
1433       fprintf (g_msgstream, "%d source lines in %ld time steps (steps/sec unknown)\n", 
1434                context_getLinesProcessed (), 
1435                (long) ttime);
1436 # else
1437       fprintf (g_msgstream, "%d source lines in %.2f s.\n", 
1438                context_getLinesProcessed (), 
1439                (double) ttime / CLOCKS_PER_SEC);
1440 # endif
1441     }
1442   else
1443     {
1444       rstime = clock ();
1445     }
1446   
1447   if (context_getFlag (FLG_TIMEDIST))
1448     {
1449       clock_t ttime = clock () - before;
1450       
1451       if (ttime > 0)
1452         {
1453           char *msg = (char *) dmalloc (256 * sizeof (*msg));
1454           
1455           if (anylcl)
1456             {
1457               sprintf (msg, 
1458                        "Time distribution (percent): initialize %.2f / lcl %.2f / "
1459                        "pre-process %.2f / c check %.2f / finalize %.2f \n", 
1460                        (100.0 * (double) (libtime - before) / ttime),
1461                        (100.0 * (double) (lcltime - libtime) / ttime),
1462                        (100.0 * (double) (pptime - lcltime) / ttime),
1463                        (100.0 * (double) (cptime - pptime) / ttime),
1464                        (100.0 * (double) (rstime - cptime) / ttime));
1465             }
1466           else
1467             {
1468               sprintf (msg, 
1469                        "Time distribution (percent): initialize %.2f / "
1470                        "pre-process %.2f / c check %.2f / finalize %.2f \n", 
1471                        (100.0 * (double) (libtime - before) / ttime),
1472                        (100.0 * (double) (pptime - libtime) / ttime),
1473                        (100.0 * (double) (cptime - pptime) / ttime),
1474                        (100.0 * (double) (rstime - cptime) / ttime));
1475             }
1476           
1477           llgenindentmsgnoloc (cstring_fromCharsO (msg));
1478         }
1479     }
1480
1481   llexit (expsuccess ? LLSUCCESS : LLFAILURE);
1482 }
1483
1484 /*
1485 ** Reenable return value warnings.
1486 */
1487
1488 #pragma warning (default:4035)
1489
1490 void
1491 showHelp (void)
1492 {
1493   showHerald ();
1494   
1495   llmsglit ("Source files are .c, .h and .lcl files.  If there is no suffix,");
1496   llmsglit ("   LCLint will look for <file>.c and <file>.lcl.");
1497   llmsglit ("");
1498   llmsglit ("Use lclint -help <topic or flag name> for more information");
1499   llmsglit ("");
1500   llmsglit ("Topics:");
1501   llmsglit ("");
1502   llmsglit ("   annotations (describes source-code annotations)");
1503   llmsglit ("   comments (describes control comments)");
1504   llmsglit ("   flags (describes flag categories)");
1505   llmsglit ("   flags <category> (describes flags in category)");
1506   llmsglit ("   flags all (short description of all flags)");
1507   llmsglit ("   flags alpha (list all flags alphabetically)");
1508   llmsglit ("   flags full (full description of all flags)");
1509   llmsglit ("   mail (information on mailing lists)");
1510   llmsglit ("   modes (show mode settings)");
1511   llmsglit ("   parseerrors (help on handling parser errors)");
1512   llmsglit ("   prefixcodes (character codes in namespace prefixes)");
1513   llmsglit ("   references (sources for more information)");
1514   llmsglit ("   vars (environment variables)"); 
1515   llmsglit ("   version (information on compilation, maintainer)");
1516   llmsglit ("");
1517 }
1518
1519 static bool
1520 specialFlagsHelp (char *next)
1521 {
1522   if ((next != NULL) && (*next != '-') && (*next != '+'))
1523     {
1524       if (mstring_equal (next, "alpha"))
1525         {
1526           printAlphaFlags ();
1527           return TRUE;
1528         }
1529       else if (mstring_equal (next, "all"))
1530         {
1531           printAllFlags (TRUE, FALSE);
1532           return TRUE;
1533         }
1534       else if (mstring_equal (next, "categories")
1535                || mstring_equal (next, "cats"))
1536         {
1537           listAllCategories ();
1538           return TRUE;
1539         }
1540       else if (mstring_equal (next, "full"))
1541         {
1542           printAllFlags (FALSE, TRUE);
1543           return TRUE;
1544         }
1545       else
1546         {
1547           return FALSE;
1548         }
1549     }
1550   else
1551     {
1552       return FALSE;
1553     }
1554 }
1555
1556 void
1557 printParseErrors (void)
1558 {
1559   llmsglit ("Parse Errors");
1560   llmsglit ("------------");
1561   llmsglit ("");
1562   llmsglit ("LCLint will sometimes encounter a parse error for code that "
1563             "can be parsed with a local compiler. There are a few likely "
1564             "causes for this and a number of techniques that can be used "
1565             "to work around the problem.");
1566   llmsglit ("");
1567   llmsglit ("Compiler extensions --- compilers sometimes extend the C "
1568             "language with compiler-specific keywords and syntax. While "
1569             "it is not advisible to use these, oftentimes one has no choice "
1570             "when the system header files use compiler extensions. ");
1571   llmsglit ("");
1572   llmsglit ("LCLint supports some of the GNU (gcc) compiler extensions, "
1573             "if the +gnuextensions flag is set. You may be able to workaround "
1574             "other compiler extensions by using a pre-processor define. "
1575             "Alternately, you can surround the unparseable code with");
1576   llmsglit ("");
1577   llmsglit ("   # ifndef __LCLINT__");
1578   llmsglit ("   ...");
1579   llmsglit ("   # endif");
1580   llmsglit ("");
1581   llmsglit ("Missing type definitions --- an undefined type name will usually "
1582             "lead to a parse error. This ofter occurs when a standard header "
1583             "file defines some type that is not part of the standard library. ");
1584   llmsglit ("By default, LCLint does not process the local files corresponding "
1585             "to standard library headers, but uses a library specification "
1586             "instead so dependencies on local system headers can be detected. "
1587             "If another system header file that does not correspond to a "
1588             "standard library header uses one of these superfluous types, "
1589             "a parse error will result.");
1590   llmsglit ("");
1591   llmsglit ("If the parse error is inside a posix standard header file, the "
1592             "first thing to try is +posixlib. This make LCLint use "
1593             "the posix library specification instead of reading the posix "
1594             "header files.");
1595   llmsglit ("");
1596   llmsglit ("Otherwise, you may need to either manually define the problematic "
1597             "type (e.g., add -Dmlink_t=int to your .lclintrc file) or force "
1598             "lclint to process the header file that defines it. This is done "
1599             "by setting -skipansiheaders or -skipposixheaders before "
1600             "the file that defines the type is #include'd.");
1601   llmsglit ("(See lclint -help "
1602             "skipansiheaders and lclint -help skipposixheaders for a list of "
1603             "standard headers.)  For example, if <sys/local.h> uses a type "
1604             "defined by posix header <sys/types.h> but not defined by the "
1605             "posix library, we might do: ");
1606   llmsglit ("");
1607   llmsglit ("   /*@-skipposixheaders@*/");
1608   llmsglit ("   # include <sys/types.h>");
1609   llmsglit ("   /*@=skipposixheaders@*/");
1610   llmsglit ("   # include <sys/local.h>");
1611   llmsglit ("");
1612   llmsglit ("to force LCLint to process <sys/types.h>.");
1613   llmsglit ("");
1614   llmsglit ("At last resort, +trytorecover can be used to make LCLint attempt "
1615             "to continue after a parse error.  This is usually not successful "
1616             "and the author does not consider assertion failures when +trytorecover "
1617             "is used to be bugs.");
1618 }
1619
1620 void
1621 printAnnotations (void)
1622 {
1623   llmsglit ("Annotations");
1624   llmsglit ("-----------");
1625   llmsglit ("");
1626   llmsglit ("Annotations are stylized comments that document certain "
1627             "assumptions about functions, variables, parameters, and types. ");
1628   llmsglit ("");
1629   llmsglit ("They may be used to indicate where the representation of a "
1630             "user-defined type is hidden, to limit where a global variable may "
1631             "be used or modified, to constrain what a function implementation "
1632             "may do to its parameters, and to express checked assumptions about "
1633             "variables, types, structure fields, function parameters, and "
1634             "function results.");
1635   llmsglit ("");
1636   llmsglit ("Annotations are introduced by \"/*@\". The role of the @ may be "
1637             "played by any printable character, selected using -commentchar <char>.");
1638   llmsglit ("");
1639   llmsglit ("Consult the User's Guide for descriptions of checking associated with each annotation.");
1640   llmsglit ("");
1641   llmsglit ("Globals: (in function declarations)");
1642   llmsglit ("   /*@globals <globitem>,+ @*/");
1643   llmsglit ("      globitem is an identifier, internalState or fileSystem");
1644   llmsglit ("");
1645   llmsglit ("Modifies: (in function declarations)");
1646   llmsglit ("   /*@modifies <moditem>,+ @*/");
1647   llmsglit ("      moditem is an lvalue");
1648   llmsglit ("   /*@modifies nothing @*/");
1649   llmsglit ("   /*@*/   (Abbreviation for no globals and modifies nothing.)");
1650   llmsglit ("");
1651   llmsglit ("Iterators:");
1652   llmsglit ("   /*@iter <identifier> (<parameter-type-list>) @*/ - declare an iterator");
1653   llmsglit ("");
1654   llmsglit ("Constants:");
1655   llmsglit ("   /*@constant <declaration> @*/ - declares a constant");
1656   llmsglit ("");
1657   llmsglit ("Alternate Types:");
1658   llmsglit ("   /*@alt <basic-type>,+ @*/");
1659   llmsglit ("   (e.g., int /*@alt char@*/ is a type matching either int or char)");
1660   llmsglit ("");
1661   llmsglit ("Declarator Annotations");
1662   llmsglit ("");
1663   llmsglit ("Type Definitions:");
1664   llmsglit ("   /*@abstract@*/ - representation is hidden from clients");
1665   llmsglit ("   /*@concrete@*/ - representation is visible to clients");
1666   llmsglit ("   /*@immutable@*/ - instances of the type cannot change value");
1667   llmsglit ("   /*@mutable@*/ - instances of the type can change value");
1668   llmsglit ("   /*@refcounted@*/ - reference counted type");
1669   llmsglit ("");
1670   llmsglit ("Global Variables:");
1671   llmsglit ("   /*@unchecked@*/ - weakest checking for global use");
1672   llmsglit ("   /*@checkmod@*/ - check modification by not use of global");
1673   llmsglit ("   /*@checked@*/ - check use and modification of global");
1674   llmsglit ("   /*@checkedstrict@*/ - check use of global strictly");
1675   llmsglit ("");
1676   llmsglit ("Memory Management:");
1677   llmsglit ("   /*@dependent@*/ - a reference to externally-owned storage");
1678   llmsglit ("   /*@keep@*/ - a parameter that is kept by the called function");
1679   llmsglit ("   /*@killref@*/ - a refcounted parameter, killed by the call");
1680   llmsglit ("   /*@only@*/ - an unshared reference");
1681   llmsglit ("   /*@owned@*/ - owner of storage that may be shared by /*@dependent@*/ references");
1682   llmsglit ("   /*@shared@*/ - shared reference that is never deallocated");
1683   llmsglit ("   /*@temp@*/ - temporary parameter");
1684   llmsglit ("");
1685   llmsglit ("Aliasing:");
1686   llmsglit ("   /*@unique@*/ - may not be aliased by any other visible reference");
1687   llmsglit ("   /*@returned@*/ - may be aliased by the return value");
1688   llmsglit ("");
1689   llmsglit ("Exposure:");
1690   llmsglit ("   /*@observer@*/ - reference that cannot be modified");
1691   llmsglit ("   /*@exposed@*/ - exposed reference to storage in another object");
1692   llmsglit ("");
1693   llmsglit ("Definition State:");
1694   llmsglit ("   /*@out@*/ - storage reachable from reference need not be defined");
1695   llmsglit ("   /*@in@*/ - all storage reachable from reference must be defined");
1696   llmsglit ("   /*@partial@*/ - partially defined, may have undefined fields");
1697   llmsglit ("   /*@reldef@*/ - relax definition checking");
1698   llmsglit ("");
1699   llmsglit ("Global State: (for globals lists, no /*@, since list is already in /*@\'s)");
1700   llmsglit ("   undef - variable is undefined before the call");
1701   llmsglit ("   killed - variable is undefined after the call");
1702   llmsglit ("");
1703   llmsglit ("Null State:");
1704   llmsglit ("   /*@null@*/ - possibly null pointer");
1705   llmsglit ("   /*@notnull@*/ - non-null pointer");
1706   llmsglit ("   /*@relnull@*/ - relax null checking");
1707   llmsglit ("");
1708   llmsglit ("Null Predicates:");
1709   llmsglit ("   /*@truenull@*/ - if result is TRUE, first parameter is NULL");
1710   llmsglit ("   /*@falsenull@*/ - if result is TRUE, first parameter is not NULL");
1711   llmsglit ("");
1712   llmsglit ("Execution:");
1713   llmsglit ("   /*@exits@*/ - function never returns");
1714   llmsglit ("   /*@mayexit@*/ - function may or may not return");
1715   llmsglit ("   /*@trueexit@*/ - function does not return if first parameter is TRUE");
1716   llmsglit ("   /*@falseexit@*/ - function does not return if first parameter if FALSE");
1717   llmsglit ("   /*@neverexit@*/ - function always returns");
1718   llmsglit ("");
1719   llmsglit ("Side-Effects:");
1720   llmsglit ("   /*@sef@*/ - corresponding actual parameter has no side effects");
1721   llmsglit ("");
1722   llmsglit ("Declaration:");
1723   llmsglit ("   /*@unused@*/ - need not be used (no unused errors reported)");
1724   llmsglit ("   /*@external@*/ - defined externally (no undefined error reported)");
1725   llmsglit ("");
1726   llmsglit ("Case:");
1727   llmsglit ("   /*@fallthrough@*/ - fall-through case");
1728   llmsglit ("");
1729   llmsglit ("Break:");
1730   llmsglit ("   /*@innerbreak@*/ - break is breaking an inner loop or switch");
1731   llmsglit ("   /*@loopbreak@*/ - break is breaking a loop");
1732   llmsglit ("   /*@switchbreak@*/ - break is breaking a switch");
1733   llmsglit ("   /*@innercontinue@*/ - continue is continuing an inner loop");
1734   llmsglit ("");
1735   llmsglit ("Unreachable Code:");
1736   llmsglit ("   /*@notreached@*/ - statement may be unreachable.");
1737   llmsglit ("");
1738   llmsglit ("Special Functions:");
1739   llmsglit ("   /*@printflike@*/ - check variable arguments like printf");
1740   llmsglit ("   /*@scanflike@*/ - check variable arguments like scanf");
1741 }
1742
1743 void
1744 printComments (void)
1745 {
1746   llmsglit ("Control Comments");
1747   llmsglit ("----------------");
1748   llmsglit ("");
1749   llmsglit ("Setting Flags");
1750   llmsglit ("");
1751   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.");
1752   llmsglit ("");
1753   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,");
1754   llmsglit ("   /*@+boolint -modifies =showfunc@*/");
1755   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).");
1756   llmsglit ("");
1757   llmsglit ("Error Suppression");
1758   llmsglit ("");
1759   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.");
1760   llmsglit ("");
1761   llmsglit ("/*@ignore@*/ ... /*@end@*/");
1762   llgenindentmsgnoloc
1763     (cstring_makeLiteral 
1764      ("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."));
1765   llmsglit ("/*@i@*/");
1766     llgenindentmsgnoloc
1767     (cstring_makeLiteral 
1768      ("No errors will be reported from an /*@i@*/ comment to the end of the line."));
1769   llmsglit ("/*@i<n>@*/");
1770   llgenindentmsgnoloc
1771     (cstring_makeLiteral 
1772      ("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."));
1773   llmsglit ("/*@t@*/, /*@t<n>@*/");
1774   llgenindentmsgnoloc
1775     (cstring_makeLiteral 
1776      ("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."));
1777   llmsglit ("");
1778   llmsglit ("Type Access");
1779   llmsglit ("");
1780   llmsglit ("/*@access <type>@*/"); 
1781   llmsglit ("   Allows the following code to access the representation of <type>");
1782   llmsglit ("/*@noaccess <type>@*/");
1783   llmsglit ("   Hides the representation of <type>");
1784   llmsglit ("");
1785   llmsglit ("Macro Expansion");
1786   llmsglit ("");
1787   llmsglit ("/*@notfunction@*/");
1788   llgenindentmsgnoloc 
1789     (cstring_makeLiteral
1790      ("Indicates that the next macro definition is not intended to be a "
1791       "function, and should be expanded in line instead of checked as a "
1792       "macro function definition."));
1793 }
1794
1795   
1796 void
1797 printFlags (void)
1798 {
1799   llmsglit ("Flag Categories");
1800   llmsglit ("---------------");
1801   listAllCategories ();
1802   llmsglit ("\nTo see the flags in a flag category, do\n   lclint -help flags <category>");
1803   llmsglit ("To see a list of all flags in alphabetical order, do\n   lclint -help flags alpha");
1804   llmsglit ("To see a full description of all flags, do\n   lclint -help flags full");
1805 }
1806
1807 void
1808 printMaintainer (void)
1809 {
1810   llmsg (message ("Maintainer: %s", cstring_makeLiteralTemp (LCLINT_MAINTAINER)));
1811   llmsglit (LCL_COMPILE);
1812 }
1813
1814 void
1815 printMail (void)
1816 {
1817   llmsglit ("Mailing Lists");
1818   llmsglit ("-------------");
1819   llmsglit ("");
1820   llmsglit ("There are two mailing lists associated with LCLint: ");
1821   llmsglit ("");
1822   llmsglit ("   lclint-announce@virginia.edu");
1823   llmsglit ("");
1824   llmsglit ("      Reserved for announcements of new releases and bug fixes.");
1825   llmsglit ("      To subscribe, send a message to majordomo@virginia.edu with body: ");
1826   llmsglit ("           subscribe lclint-announce");
1827   llmsglit ("");
1828   llmsglit ("   lclint-interest@virginia.edu");
1829   llmsglit ("");
1830   llmsglit ("      Informal discussions on the use and development of lclint.");
1831   llmsglit ("      To subscribe, send a message to majordomo@virginia.edu with body: ");
1832   llmsglit ("           subscribe lclint-interest");
1833 }
1834
1835 void
1836 printReferences (void)
1837 {
1838   llmsglit ("References");
1839   llmsglit ("----------");
1840   llmsglit ("");
1841   llmsglit ("The LCLint web site is http://lclint.cs.virginia.edu");
1842   llmsglit ("");
1843   llmsglit ("Technical papers relating to LCLint include:");
1844   llmsglit ("");
1845   llmsglit ("   David Evans. \"Static Detection of Dynamic Memory Errors\".");  
1846   llmsglit ("   SIGPLAN Conference on Programming Language Design and ");
1847   llmsglit ("   Implementation (PLDI '96), Philadelphia, PA, May 1996.");
1848   llmsglit ("");
1849   llmsglit ("   David Evans, John Guttag, Jim Horning and Yang Meng Tan. ");
1850   llmsglit ("   \"LCLint: A Tool for Using Specifications to Check Code\".");
1851   llmsglit ("   SIGSOFT Symposium on the Foundations of Software Engineering,");
1852   llmsglit ("   December 1994.");
1853   llmsglit ("");
1854   llmsglit ("A general book on Larch is:");
1855   llmsglit ("");
1856   llmsglit ("   Guttag, John V., Horning, James J., (with Garland, S. J., Jones, ");
1857   llmsglit ("   K. D., Modet, A., and Wing, J. M.), \"Larch: Languages and Tools ");
1858   llmsglit ("   for Formal Specification\", Springer-Verlag, 1993.");
1859 }
1860
1861 void
1862 describePrefixCodes (void)
1863 {
1864   llmsglit ("Prefix Codes");
1865   llmsglit ("------------");
1866   llmsglit ("");
1867   llmsglit ("These characters have special meaning in name prefixes:");
1868   llmsglit ("");
1869   llmsg (message ("   %h  Any uppercase letter [A-Z]", PFX_UPPERCASE));
1870   llmsg (message ("   %h  Any lowercase letter [a-z]", PFX_LOWERCASE));
1871   llmsg (message ("   %h  Any character (valid in a C identifier)", PFX_ANY));
1872   llmsg (message ("   %h  Any digit [0-9]", PFX_DIGIT));
1873   llmsg (message ("   %h  Any non-uppercase letter [a-z0-9_]", PFX_NOTUPPER));
1874   llmsg (message ("   %h  Any non-lowercase letter [A-Z0-9_]", PFX_NOTLOWER));
1875   llmsg (message ("   %h  Any letter [A-Za-z]", PFX_ANYLETTER));
1876   llmsg (message ("   %h  Any letter or digit [A-Za-z0-9]", PFX_ANYLETTERDIGIT));
1877   llmsglit ("   *  Zero or more repetitions of the previous character class until the end of the name");
1878 }
1879
1880 void
1881 describeVars (void)
1882 {
1883   cstring eval;
1884   char *def;
1885
1886   eval = context_getLarchPath ();
1887   def = osd_getEnvironmentVariable (LARCH_PATH);
1888
1889   if (def != NULL || 
1890       !cstring_equal (eval, cstring_fromChars (DEFAULT_LARCHPATH)))
1891     {
1892       llmsg (message ("LARCH_PATH = %s", eval));
1893     }
1894   else
1895     {
1896       llmsg (message ("LARCH_PATH = <not set> (default = %s)",
1897                       cstring_fromChars (DEFAULT_LARCHPATH)));
1898     }
1899   
1900   llmsglit ("   --- path used to find larch initialization files and LSL traits");
1901
1902   eval = context_getLCLImportDir ();
1903   def = osd_getEnvironmentVariable (LCLIMPORTDIR);
1904
1905   if (def != NULL ||
1906       !cstring_equal (eval, cstring_fromChars (DEFAULT_LCLIMPORTDIR)))
1907     {
1908       llmsg (message ("%q = %s", cstring_makeLiteral (LCLIMPORTDIR), eval));
1909     }
1910   else
1911     {
1912       llmsg (message ("%s = <not set, default: %s>", cstring_makeLiteralTemp (LCLIMPORTDIR), 
1913                       cstring_makeLiteralTemp (DEFAULT_LCLIMPORTDIR))); 
1914     }
1915   
1916   llmsglit ("   --- directory containing lcl standard library files "
1917             "(import with < ... >)");;
1918
1919   {
1920     cstring dirs = context_getString (FLG_SYSTEMDIRS);
1921     llmsg (message 
1922            ("systemdirs = %s (set by include envirnoment variable or -systemdirs)",
1923             dirs));
1924
1925   }
1926 }
1927
1928 void
1929 interrupt (int i)
1930 {
1931   switch (i)
1932     {
1933     case SIGINT:
1934       fprintf (stderr, "*** Interrupt\n");
1935       llexit (LLINTERRUPT);
1936     case SIGSEGV:
1937       {
1938         cstring loc;
1939         
1940         /* Cheat when there are parse errors */
1941         checkParseError (); 
1942         
1943         fprintf (stderr, "*** Segmentation Violation\n");
1944         
1945         /* Don't catch it if fileloc_unparse causes a signal */
1946         (void) signal (SIGSEGV, NULL);
1947
1948         loc = fileloc_unparse (g_currentloc);
1949         
1950         fprintf (stderr, "*** Location (not trusted): %s\n", 
1951                  cstring_toCharsSafe (loc));
1952         cstring_free (loc);
1953         printCodePoint ();
1954         fprintf (stderr, "*** Please report bug to %s\n", LCLINT_MAINTAINER);
1955         exit (LLGIVEUP);
1956       }
1957     default:
1958       fprintf (stderr, "*** Signal: %d\n", i);
1959       /*@-mustfree@*/
1960       fprintf (stderr, "*** Location (not trusted): %s\n", 
1961                cstring_toCharsSafe (fileloc_unparse (g_currentloc)));
1962       /*@=mustfree@*/
1963       printCodePoint ();
1964       fprintf (stderr, "*** Please report bug to %s ***\n", LCLINT_MAINTAINER);
1965       exit (LLGIVEUP);
1966     }
1967 }
1968
1969 void
1970 cleanupFiles (void)
1971 {
1972   static bool doneCleanup = FALSE;
1973
1974   /* make sure this is only called once! */
1975
1976   if (doneCleanup) return;
1977
1978   setCodePoint ();
1979
1980   if (context_getFlag (FLG_KEEP))
1981     {
1982       check (fputs ("Temporary files kept:\n", stderr) != EOF);
1983       fileTable_printTemps (context_fileTable ());
1984     }
1985   else
1986     {
1987 # ifdef WIN32
1988       int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
1989       
1990       if (nfiles != 0) 
1991         {
1992           llbug (message ("Files unclosed: %d", nfiles));
1993         }
1994 # endif
1995       fileTable_cleanup (context_fileTable ());
1996     }
1997
1998   doneCleanup = TRUE;
1999 }
2000
2001 /*
2002 ** cleans up temp files (if necessary)
2003 ** exits lclint
2004 */
2005
2006 /*@exits@*/ void
2007 llexit (int status)
2008 {
2009   DPRINTF (("llexit: %d", status));
2010
2011 # ifdef WIN32
2012   if (status == LLFAILURE) 
2013     {
2014       _fcloseall ();
2015     }
2016 # endif
2017
2018   cleanupFiles ();
2019
2020   if (status != LLFAILURE)
2021     {
2022       context_destroyMod ();
2023       exprNode_destroyMod ();
2024       
2025       sRef_destroyMod ();
2026       uentry_destroyMod ();
2027       typeIdSet_destroyMod ();
2028       
2029 # ifdef USEDMALLOC
2030       dmalloc_shutdown ();
2031 # endif
2032     }
2033
2034   exit ((status == LLSUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE);
2035 }
2036
2037 void
2038 loadrc (FILE *rcfile, cstringSList *passThroughArgs)
2039 {
2040   char *s = mstring_create (MAX_LINE_LENGTH);
2041   char *os = s;
2042
2043   DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2044
2045   s = os;
2046
2047   while (fgets (s, MAX_LINE_LENGTH, rcfile) != NULL)
2048     {
2049       char c;
2050       bool set = FALSE;     
2051       char *thisflag;
2052       flagcode opt;
2053
2054       DPRINTF (("Line: %s", s));
2055       DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2056       incLine ();
2057             
2058       while (*s == ' ' || *s == '\t' || *s == '\n') 
2059         {
2060           s++;
2061           incColumn ();
2062         }
2063       
2064       while (*s != '\0')
2065         {
2066           bool escaped = FALSE;
2067           bool quoted = FALSE;
2068           c = *s;
2069
2070           DPRINTF (("Process: %s", s));
2071           DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2072           /* comment characters */
2073           if (c == '#' || c == ';' || c == '\n') 
2074             {
2075               /*@innerbreak@*/
2076               break;
2077             }
2078           
2079           if (c == '-' || c == '+')
2080             {
2081               set = (c == '+');
2082             }
2083           else
2084             {
2085               showHerald ();
2086               llerror (FLG_SYNTAX, 
2087                        message ("Bad flag syntax (+ or - expected, "
2088                                 "+ is assumed): %s", 
2089                                 cstring_fromChars (s)));
2090               s--;
2091               set = TRUE;
2092             }
2093           
2094           s++;
2095           incColumn ();
2096           
2097           thisflag = s;
2098           
2099           while ((c = *s) != '\0')
2100             { /* remember to handle spaces and quotes in -D and -U ... */
2101               if (escaped)
2102                 {
2103                   escaped = FALSE;
2104                 }
2105               else if (quoted)
2106                 {
2107                   if (c == '\\')
2108                     {
2109                       escaped = TRUE;
2110                     }
2111                   else if (c == '\"')
2112                     {
2113                       quoted = FALSE;
2114                     }
2115                   else
2116                     {
2117                       ;
2118                     }
2119                 }
2120               else if (c == '\"')
2121                 {
2122                   quoted = TRUE;
2123                 }
2124               else
2125                 {
2126                  if (c == ' ' || c == '\t' || c == '\n')
2127                    {
2128                      /*@innerbreak@*/ break;
2129                    }
2130                }
2131                   
2132               s++; 
2133               incColumn ();
2134             }
2135
2136           DPRINTF (("Nulling: %c", *s));
2137           *s = '\0';
2138
2139           if (mstring_isEmpty (thisflag))
2140             {
2141               llfatalerror (message ("Missing flag: %s",
2142                                      cstring_fromChars (os)));
2143             }
2144
2145           DPRINTF (("Flag: %s", thisflag));
2146
2147           opt = identifyFlag (cstring_fromChars (thisflag));
2148           
2149           if (flagcode_isSkip (opt))
2150             {
2151               ;
2152             }
2153           else if (flagcode_isInvalid (opt))
2154             {
2155               if (isMode (cstring_fromChars (thisflag)))
2156                 {
2157                   context_setMode (cstring_fromChars (thisflag));
2158                 }
2159               else
2160                 {
2161                   llerror (FLG_BADFLAG,
2162                            message ("Unrecognized option: %s", 
2163                                     cstring_fromChars (thisflag)));
2164                 }
2165             }
2166           else
2167             {
2168               context_userSetFlag (opt, set);
2169
2170               if (flagcode_hasArgument (opt))
2171                 {
2172                   if (opt == FLG_HELP)
2173                     {
2174                       showHerald ();
2175                       llerror (FLG_BADFLAG,
2176                                message ("Cannot use help in rc files"));
2177                     }
2178                   else if (flagcode_isPassThrough (opt)) /* -D or -U */
2179                     {
2180                       cstring arg = cstring_fromCharsNew (thisflag);
2181                       cstring_markOwned (arg);
2182                       *passThroughArgs = cstringSList_add (*passThroughArgs, arg);
2183                       DPRINTF (("Pass through: %s",
2184                                 cstringSList_unparse (*passThroughArgs)));
2185                     }
2186                   else if (opt == FLG_INCLUDEPATH 
2187                            || opt == FLG_SPECPATH)
2188                     {
2189                       cstring dir = cstring_suffix (cstring_fromChars (thisflag), 1); /* skip over I/S */
2190                                       
2191                       switch (opt)
2192                         {
2193                         case FLG_INCLUDEPATH:
2194                           cppAddIncludeDir (dir);
2195                           /*@switchbreak@*/ break;
2196                         case FLG_SPECPATH:
2197                           /*@-mustfree@*/
2198                           g_localSpecPath = cstring_toCharsSafe
2199                             (message ("%s:%s", cstring_fromChars (g_localSpecPath), dir));
2200                           /*@=mustfree@*/
2201                           /*@switchbreak@*/ break;
2202                           BADDEFAULT;
2203                         }
2204                     }
2205                   else if (flagcode_hasString (opt)
2206                            || flagcode_hasValue (opt)
2207                            || opt == FLG_INIT || opt == FLG_OPTF)
2208                     {
2209                       cstring extra = cstring_undefined;
2210                       char *rest, *orest;
2211                       char rchar;
2212                       
2213                       *s = c;
2214                       rest = mstring_copy (s);
2215                       DPRINTF (("Here: rest = %s", rest));
2216                       orest = rest;
2217                       *s = '\0';
2218                       
2219                       while ((rchar = *rest) != '\0'
2220                              && (isspace ((int) rchar)))
2221                         {
2222                           rest++;
2223                           s++;
2224                         }
2225                       
2226                       DPRINTF (("Yo: %s", rest));
2227
2228                       while ((rchar = *rest) != '\0' 
2229                              && !isspace ((int) rchar))
2230                         {
2231                           extra = cstring_appendChar (extra, rchar);
2232                           rest++; 
2233                           s++;
2234                         }
2235                       
2236                       DPRINTF (("Yo: %s", extra));
2237                       sfree (orest);
2238
2239                       if (cstring_isUndefined (extra))
2240                         {
2241                           showHerald ();
2242                           llerror 
2243                             (FLG_BADFLAG,
2244                              message
2245                              ("Flag %s must be followed by an argument",
2246                               flagcode_unparse (opt)));
2247                         }
2248                       else
2249                         {
2250                           s--;
2251                           
2252                           DPRINTF (("Here we are: %s", extra));
2253
2254                           if (flagcode_hasValue (opt))
2255                             {
2256                               DPRINTF (("Set value flag: %s", extra));
2257                               setValueFlag (opt, extra);
2258                               cstring_free (extra);
2259                             }
2260                           else if (opt == FLG_OPTF)
2261                             {
2262                               FILE *innerf = fopen (cstring_toCharsSafe (extra), "r");
2263                               cstring_markOwned (extra);
2264                               
2265                               if (innerf != NULL)
2266                                 {
2267                                   fileloc fc = g_currentloc;
2268                                   g_currentloc = fileloc_createRc (extra);
2269                                   loadrc (innerf, passThroughArgs);
2270                                   fileloc_reallyFree (g_currentloc);
2271                                   g_currentloc = fc;
2272                                 }
2273                               else 
2274                                 {
2275                                   showHerald ();
2276                                   llerror
2277                                     (FLG_SYNTAX, 
2278                                      message ("Options file not found: %s", 
2279                                               extra));
2280                                 }
2281                             }
2282                           else if (opt == FLG_INIT)
2283                             {
2284 # ifndef NOLCL
2285                               llassert (initFile == NULL);
2286                               
2287                               initFile = tsource_create 
2288                                 (cstring_toCharsSafe (extra), 
2289                                  LCLINIT_SUFFIX, FALSE);
2290                               cstring_markOwned (extra);
2291 # else
2292                               cstring_free (extra);
2293 # endif
2294                             }
2295                           else if (flagcode_hasString (opt))
2296                             {
2297                               if (cstring_firstChar (extra) == '"')
2298                                 {
2299                                   if (cstring_lastChar (extra) == '"')
2300                                     {
2301                                       char *extras = cstring_toCharsSafe (extra);
2302                                       
2303                                       llassert (extras[strlen(extras) - 1] == '"');
2304                                       extras[strlen(extras) - 1] = '\0';
2305                                       extra = cstring_fromChars (extras + 1); 
2306                                       DPRINTF (("Remove quites: %s", extra));
2307                                     }
2308                                   else
2309                                     {
2310                                       llerror
2311                                         (FLG_SYNTAX, 
2312                                          message ("Unmatched \" in option string: %s", 
2313                                                   extra));
2314                                     }
2315                                 }
2316                               
2317                               setStringFlag (opt, extra);
2318                             }
2319                           else
2320                             {
2321                               cstring_free (extra);
2322                               BADEXIT;
2323                             }
2324                         }
2325                     }
2326                   else
2327                     {
2328                       BADEXIT;
2329                     }
2330                 }
2331             }
2332           
2333           *s = c;
2334           DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2335           while ((c == ' ') || (c == '\t'))
2336             {
2337               c = *(++s);
2338               incColumn ();
2339             } 
2340         }
2341       DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2342       s = os;
2343     }
2344
2345   DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2346   sfree (os); 
2347   check (fclose (rcfile) == 0);
2348 }
2349
2350 static fileIdList preprocessFiles (fileIdList fl)
2351   /*@modifies fileSystem@*/
2352 {
2353   bool msg = (context_getFlag (FLG_SHOWSCAN) && fileIdList_size (fl) > 10);
2354   int skip = (fileIdList_size (fl) / 5);
2355   int filesprocessed = 0;
2356   fileIdList dfiles = fileIdList_create ();
2357
2358   fileloc_free (g_currentloc);
2359   g_currentloc = fileloc_createBuiltin ();
2360
2361   fileIdList_elements (fl, fid)
2362     {
2363       char *ppfname = cstring_toCharsSafe (fileName (fid));
2364
2365       if (!(osd_fileIsReadable (ppfname)))
2366         {
2367           lldiagmsg (message ("Cannot open file: %s",
2368                               cstring_fromChars (ppfname)));
2369         }
2370       else
2371         {
2372           fileId  dfile = fileTable_addCTempFile (context_fileTable (), fid);
2373           
2374           llassert (!mstring_isEmpty (ppfname));
2375           
2376           if (msg)
2377             {
2378               if ((filesprocessed % skip) == 0) 
2379                 {
2380                   if (filesprocessed == 0) {
2381                     fprintf (stderr, " ");
2382                   }
2383                   else {
2384                     fprintf (stderr, ".");
2385                   }
2386                   
2387                   (void) fflush (stderr);
2388                 }
2389               filesprocessed++;
2390             }
2391
2392           if (cppProcess (cstring_fromChars (ppfname), 
2393                           fileName (dfile)) != 0) 
2394             {
2395               llfatalerror (message ("Preprocessing error for file: %s", 
2396                                      rootFileName (fid)));
2397             }
2398           
2399           fileIdList_add (dfiles, dfile);
2400         }
2401     } end_fileIdList_elements; 
2402     
2403     return dfiles;
2404 }
This page took 0.222063 seconds and 5 git commands to generate.