]> andersk Git - splint.git/blame - src/llmain.c
Readded files.
[splint.git] / src / llmain.c
CommitLineData
616915dd 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
82extern /*@external@*/ int yydebug;
83
84static void printMail (void);
85static void printMaintainer (void);
86static void printReferences (void);
87static void printFlags (void);
88static void printAnnotations (void);
89static void printParseErrors (void);
90static void printComments (void);
91static void describePrefixCodes (void);
92static void cleanupFiles (void);
93static void showHelp (void);
94static void interrupt (int p_i);
95static void loadrc (FILE *p_rcfile, cstringSList *p_passThroughArgs);
96static void describeVars (void);
97static bool specialFlagsHelp (char *p_next);
98static bool hasShownHerald = FALSE;
99
100static bool anylcl = FALSE;
101static clock_t inittime;
102
103static /*@only@*/ /*@null@*/ tsource *initFile = (tsource *) 0;
104
105static fileIdList preprocessFiles (fileIdList)
106 /*@modifies fileSystem@*/ ;
107
108# ifndef NOLCL
109
110static
111void 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
143static
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
296static void
297lslProcess (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
419static 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
501void 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
513static 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
536int 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
1490void
1491showHelp (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
1519static bool
1520specialFlagsHelp (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
1556void
1557printParseErrors (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
1620void
1621printAnnotations (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
1743void
1744printComments (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
1796void
1797printFlags (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
1807void
1808printMaintainer (void)
1809{
1810 llmsg (message ("Maintainer: %s", cstring_makeLiteralTemp (LCLINT_MAINTAINER)));
1811 llmsglit (LCL_COMPILE);
1812}
1813
1814void
1815printMail (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
1835void
1836printReferences (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
1861void
1862describePrefixCodes (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
1880void
1881describeVars (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
1928void
1929interrupt (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
1969void
1970cleanupFiles (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
2007llexit (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
2037void
2038loadrc (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
2350static 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.368466 seconds and 5 git commands to generate.