Less permissive syntax for notreached comment.
[splint-patched.git] / src / llmain.c
bloba39ceab8ae3e49b7dc542baf614d1dd4cbc0f1b2
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** llmain.c
27 ** Main module for Splint annotation-assisted program checker
30 # include <signal.h>
31 # include <time.h>
33 # include "splintMacros.nf"
34 # include "basic.h"
35 # include "osd.h"
36 # include "help.h"
38 # include "lslgrammar.h"
39 # include "lslscanline.h"
40 # include "lslscan.h"
41 # include "lslsyntable.h"
42 # include "lsltokentable.h"
43 # include "lslinit.h"
45 # include "lclscan.h"
46 # include "lclscanline.h"
47 # include "lclsyntable.h"
48 # include "lcltokentable.h"
49 # include "lcllib.h"
51 # include "llgrammar.h"
53 # include "cscanner.h"
54 # define C_DEBUG 1
55 # include "cgrammar.h"
56 # define MTDEBUG 1
57 # include "mtgrammar.h"
59 # include "lh.h"
60 # include "imports.h"
62 # include "Headers/version.h" /* Visual C++ finds the wrong version.h */
63 # include "rcfiles.h"
64 # include "cpp.h"
66 static void cleanupFiles (void);
67 static void cleanupMemory (void);
70 ** evans 2002-07-03: renamed from interrupt to avoid conflict with WATCOM compiler keyword
71 ** (Suggested by Adam Clarke)
73 static void llinterrupt (int p_i);
75 static char* specFullName (char *p_specfile, /*@out@*/ char **p_inpath)
76 /*@modifies *p_inpath@*/ ;
78 static bool anylcl = FALSE;
80 static fileIdList preprocessFiles (fileIdList)
81 /*@modifies fileSystem@*/ ;
82 static void warnSysFiles(fileIdList);
84 static
85 void lslCleanup (void)
86 /*@globals killed g_symtab@*/
87 /*@modifies internalState, g_symtab@*/
90 ** Cleanup all the LCL/LSL.
93 static bool didCleanup = FALSE;
95 llassert (!didCleanup);
96 llassert (anylcl);
98 didCleanup = TRUE;
100 lsymbol_destroyMod ();
101 LCLSynTableCleanup ();
102 LCLTokenTableCleanup ();
103 LCLScanLineCleanup ();
104 LCLScanCleanup ();
106 /* clean up LSL parsing */
108 lsynTableCleanup ();
109 ltokenTableCleanup ();
110 lscanLineCleanup ();
111 LSLScanCleanup ();
113 symtable_free (g_symtab);
114 sort_destroyMod ();
117 static void
118 lslProcess (fileIdList lclfiles)
119 /*@globals undef g_currentSpec, undef g_currentSpecName, g_currentloc,
120 undef killed g_symtab; @*/
121 /*@modifies g_currentSpec, g_currentSpecName, g_currentloc, internalState, fileSystem; @*/
123 char *path = NULL;
124 bool parser_status = FALSE;
125 bool overallStatus = FALSE;
127 lslinit_process ();
129 context_resetSpecLines ();
131 fileIdList_elements (lclfiles, fid)
133 cstring actualName = cstring_undefined;
134 cstring fname = fileTable_fileName (fid);
136 if (osd_getPath (cstring_fromChars (g_localSpecPath),
137 fname, &actualName) == OSD_FILENOTFOUND)
139 if (mstring_equal (g_localSpecPath, "."))
141 lldiagmsg (message ("Spec file not found: %q", osd_outputPath (fname)));
143 else
145 lldiagmsg (message ("Spec file not found: %q (on %s)",
146 osd_outputPath (fname),
147 cstring_fromChars (g_localSpecPath)));
150 else
152 inputStream specFile;
153 /*@access cstring@*/
154 char *namePtr = actualName;
156 while (*namePtr == '.' && *(namePtr + 1) == CONNECTCHAR)
158 namePtr += 2;
160 /*@noaccess cstring@*/
162 g_currentSpec = cstring_fromCharsNew (namePtr);
164 specFile = inputStream_create (cstring_copy (g_currentSpec),
165 LCL_EXTENSION, TRUE);
167 llassert (inputStream_isDefined (specFile));
169 g_currentSpecName = specFullName
170 (cstring_toCharsSafe (g_currentSpec),
171 &path);
173 setSpecFileId (fid);
175 displayScan (message ("reading spec %s", g_currentSpec));
177 /* Open the source file */
179 if (!inputStream_open (specFile))
181 lldiagmsg (message ("Cannot open file: %q",
182 osd_outputPath (inputStream_fileName (specFile))));
183 inputStream_free (specFile);
185 else
187 scopeInfo dummy_scope = (scopeInfo) dmalloc (sizeof (*dummy_scope));
188 dummy_scope->kind = SPE_INVALID;
190 lhInit (specFile);
191 LCLScanReset (specFile);
194 ** Minor hacks to allow more than one LCL file to
195 ** be scanned, while keeping initializations
198 symtable_enterScope (g_symtab, dummy_scope);
199 resetImports (cstring_fromChars (g_currentSpecName));
200 context_enterLCLfile ();
201 (void) lclHadNewError ();
203 parser_status = (ylparse () != 0);
204 context_exitLCLfile ();
205 lhCleanup ();
206 overallStatus = parser_status || lclHadNewError ();
208 if (context_getFlag (FLG_DOLCS))
210 if (overallStatus)
212 outputLCSFile (path, "%FAILED Output from ",
213 g_currentSpecName);
215 else
217 outputLCSFile (path, "%PASSED Output from ",
218 g_currentSpecName);
222 (void) inputStream_close (specFile);
223 inputStream_free (specFile);
225 symtable_exitScope (g_symtab);
228 cstring_free (actualName);
229 } end_fileIdList_elements;
231 /* Can cleanup lsl stuff right away */
233 lslCleanup ();
235 g_currentSpec = cstring_undefined;
236 g_currentSpecName = NULL;
239 void showHerald (void)
241 static bool hasShownHerald = FALSE;
242 if (hasShownHerald || context_getFlag (FLG_QUIET))
244 return;
246 else
248 fprintf (g_messagestream, "%s\n\n", SPLINT_VERSION);
249 hasShownHerald = TRUE;
250 llflush ();
254 int main (int argc, char *argv[])
255 /*@globals killed undef g_currentloc,
256 killed g_localSpecPath,
257 killed undef g_currentSpec,
258 killed undef g_currentSpecName,
259 killed undef c_in,
260 undef g_warningstream, g_messagestream, g_errorstream;
262 /*@modifies g_currentloc, g_localSpecPath, g_currentSpec, g_currentSpecName,
263 fileSystem, c_in;
266 bool first_time = TRUE;
267 bool expsuccess;
268 inputStream sourceFile = inputStream_undefined;
270 cstringList cppArgs = cstringList_undefined;
271 fileIdList cfiles, lclfiles, mtfiles, dercfiles;
272 clock_t before, lcltime, libtime, pptime, cptime, rstime;
273 int i = 0;
275 /* EMX seems to be UNIX compatibility layer for OS2 */
276 # ifdef __EMX__
277 _wildcard (&argc, &argv);
278 # endif
280 g_warningstream = stdout;
281 g_messagestream = stderr;
282 g_errorstream = stderr;
284 (void) signal (SIGINT, llinterrupt);
285 (void) signal (SIGSEGV, llinterrupt);
287 c_debug = 0;
288 mtdebug = 0;
290 flags_initMod ();
291 qual_initMod ();
292 clabstract_initMod ();
293 typeIdSet_initMod ();
294 osd_initMod ();
296 setCodePoint ();
298 g_currentloc = fileloc_createBuiltin ();
300 before = clock ();
301 context_initMod ();
303 context_setInCommandLine ();
305 if (argc <= 1)
307 help_showAvailableHelp ();
308 cleanupFiles ();
309 cleanupMemory ();
310 return EXIT_SUCCESS;
313 /* -help must be the first flag to get help */
314 if (flagcode_isHelpFlag (flags_identifyFlag (cstring_fromChars (argv[1]))))
317 ** Skip first flag and help flag
320 help_processFlags (argc - 2, argv + 2);
321 cleanupFiles ();
322 cleanupMemory ();
323 return EXIT_SUCCESS;
326 setCodePoint ();
329 ** check RCFILE for default flags
333 ** Process command line message formatting flags before reading rc file
337 cstring home = cstring_makeLiteralTemp (getenv ("HOME"));
338 cstring fname = cstring_undefined;
339 bool defaultf = TRUE;
340 bool nof = FALSE;
342 for (i = 1; i < argc; i++)
344 char *thisarg;
345 thisarg = argv[i];
347 if (*thisarg == '-' || *thisarg == '+')
349 bool set = (*thisarg == '+');
350 flagcode opt;
352 thisarg++;
355 ** Don't report warnings this time
358 opt = flags_identifyFlagQuiet (cstring_fromChars (thisarg));
360 if (opt == FLG_NOF)
362 nof = TRUE;
364 else if (flagcode_isMessageControlFlag (opt))
367 ** Need to set it immediately, so rc file scan is displayed
370 context_userSetFlag (opt, set);
372 if (flagcode_hasArgument (opt))
374 llassert (flagcode_hasString (opt));
376 if (++i < argc)
378 fname = cstring_fromChars (argv[i]);
379 flags_setStringFlag (opt, fname);
381 else
383 voptgenerror
384 (FLG_BADFLAG,
385 message
386 ("Flag %s must be followed by a string",
387 flagcode_unparse (opt)),
388 g_currentloc);
392 else if (opt == FLG_OPTF)
394 if (++i < argc)
396 defaultf = FALSE;
397 fname = cstring_fromChars (argv[i]);
398 (void) rcfiles_read (fname, &cppArgs, TRUE);
400 else
401 llfatalerror
402 (cstring_makeLiteral ("Flag f to select options file "
403 "requires an argument"));
405 else
407 ; /* wait to process later */
412 setCodePoint ();
414 if (!nof && defaultf)
417 ** No explicit rc file, first try reading ~/.splintrc
420 if (cstring_isUndefined (fname))
422 if (!cstring_isEmpty (home))
424 bool readhomerc, readaltrc;
425 cstring homename, altname;
427 homename = message ("%s%h%s", home, CONNECTCHAR,
428 cstring_fromChars (RCFILE));
429 readhomerc = rcfiles_read (homename, &cppArgs, FALSE);
432 ** Try $HOME/.lclintrc also for historical accuracy
435 altname = message ("%s%h%s", home, CONNECTCHAR,
436 cstring_fromChars (ALTRCFILE));
437 readaltrc = rcfiles_read (altname, &cppArgs, FALSE);
439 if (readhomerc && readaltrc)
442 voptgenerror
443 (FLG_WARNRC,
444 message ("Found both %s and %s files. Using both files, "
445 "but recommend using only %s to avoid confusion.",
446 homename, altname, homename),
447 g_currentloc);
450 cstring_free (homename);
451 cstring_free (altname);
456 ** Next, read .splintrc in the current working directory
460 cstring rcname = message ("%s%s",osd_getCurrentDirectory (), cstring_fromChars (RCFILE));
461 cstring altname = message ("%s%s",osd_getCurrentDirectory (), cstring_fromChars (ALTRCFILE));
462 bool readrc, readaltrc;
464 readrc = rcfiles_read (rcname, &cppArgs, FALSE);
465 readaltrc = rcfiles_read (altname, &cppArgs, FALSE);
467 if (readrc && readaltrc)
469 voptgenerror (FLG_WARNRC,
470 message ("Found both %s and %s files. Using both files, "
471 "but recommend using only %s to avoid confusion.",
472 rcname, altname, rcname),
473 g_currentloc);
477 cstring_free (rcname);
478 cstring_free (altname);
483 setCodePoint ();
484 llassert (fileloc_isBuiltin (g_currentloc));
486 cfiles = fileIdList_create ();
487 lclfiles = fileIdList_create ();
488 mtfiles = fileIdList_create ();
490 /* argv[0] is the program name, don't pass it to flags_processFlags */
491 flags_processFlags (TRUE, cfiles, lclfiles, mtfiles,
492 &cppArgs, argc - 1, argv + 1);
494 showHerald ();
496 if (context_getFlag (FLG_CSV)) {
497 cstring fname = context_getString (FLG_CSV);
499 if (cstring_isDefined (fname)) {
500 if (osd_fileExists (fname) && !context_getFlag (FLG_CSVOVERWRITE)) {
501 lldiagmsg (message ("Specified CSV output file already exists (use +csvoverwrite to automatically overwrite): %s",
502 fname));
503 } else {
504 g_csvstream = fopen (cstring_toCharsSafe (fname), "w");
506 DPRINTF (("Creating: %s", fname));
507 if (g_csvstream == NULL) {
508 lldiagmsg (message ("Cannot open file for CSV output: %s", fname));
509 } else {
510 displayScan (message ("Starting CSV output file: %s", context_getString (FLG_CSV)));
511 fprintf (g_csvstream,
512 "Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text\n");
518 # ifdef DOANNOTS
519 initAnnots ();
520 # endif
522 context_resetErrors ();
523 context_clearInCommandLine ();
525 anylcl = !fileIdList_isEmpty (lclfiles);
527 if (context_doMerge ())
529 cstring m = context_getMerge ();
531 displayScanOpen (message ("< loading %s ", m));
532 loadState (m);
533 displayScanClose ();
535 if (!usymtab_existsType (context_getBoolName ()))
537 usymtab_initBool ();
540 else
542 if (!context_getFlag (FLG_NOLIB) && loadStandardState ())
546 else
548 ctype_initTable ();
551 /* setup bool type and constants */
552 usymtab_initBool ();
555 fileloc_free (g_currentloc);
556 g_currentloc = fileloc_createBuiltin ();
559 ** Read metastate files (must happen before loading libraries)
562 fileIdList_elements (mtfiles, mtfile)
564 context_setFileId (mtfile);
565 displayScan (message ("processing %s", fileTable_rootFileName (mtfile)));
566 mtreader_readFile (cstring_copy (fileTable_fileName (mtfile)));
567 } end_fileIdList_elements;
569 libtime = clock ();
571 if (anylcl)
573 lslProcess (lclfiles);
576 usymtab_initGlobalMarker ();
578 lcltime = clock ();
581 ** pre-processing
584 if (!context_getFlag (FLG_NOPP))
586 context_setInCommandLine ();
587 cppReader_initMod (&cppArgs);
588 cleanupMessages ();
589 llflush ();
590 context_clearInCommandLine ();
592 displayScanOpen (cstring_makeLiteral ("preprocessing"));
594 context_setPreprocessing ();
595 warnSysFiles (cfiles);
596 dercfiles = preprocessFiles (cfiles);
597 fileIdList_free (cfiles);
598 context_clearPreprocessing ();
600 displayScanClose ();
602 else
604 dercfiles = cfiles;
606 cstringList_free (cppArgs);
608 pptime = clock ();
611 ** now, check all the (possibly preprocessed) C files
614 DPRINTF (("Initializing..."));
616 exprNode_initMod ();
618 DPRINTF (("Okay..."));
620 fileIdList_elements (dercfiles, fid)
622 sourceFile = inputStream_create (cstring_copy (fileTable_fileName (fid)), C_EXTENSION, TRUE);
623 context_setFileId (fid);
625 /* Open source file */
627 if (inputStream_isUndefined (sourceFile) || (!inputStream_open (sourceFile)))
629 /* previously, this was ignored ?! */
630 llbug (message ("Could not open temp file: %s", fileTable_fileName (fid)));
632 else
634 c_in = inputStream_getFile (sourceFile); /*< shared <- only */
636 llassert (c_in != NULL);
638 displayScan (message ("checking %q", osd_outputPath (fileTable_rootFileName (fid))));
641 ** Every time, except the first time, through the loop,
642 ** need to call c_restart to clean up the parse buffer.
645 if (!first_time)
647 (void) c_restart (c_in);
649 else
651 first_time = FALSE;
654 DPRINTF (("Entering..."));
655 context_enterFile ();
656 (void) c_parse ();
657 context_exitCFile ();
659 (void) inputStream_close (sourceFile);
662 inputStream_free (sourceFile); /* evans 2002-07-12: why no warning without this?!! */
663 } end_fileIdList_elements;
665 fileIdList_free (dercfiles); /* evans 2002-07-12: why no warning without this?!! */
666 cptime = clock ();
668 /* process any leftover macros */
670 context_processAllMacros ();
672 /* check everything that was specified was defined */
674 /* don't check if no c files were processed ?
675 ** is this correct behaviour?
678 displayScan (cstring_makeLiteral ("global checks"));
680 cleanupMessages ();
682 if (context_getLinesProcessed () > 0)
684 usymtab_allDefined ();
687 if (context_maybeSet (FLG_TOPUNUSED))
689 uentry ue = usymtab_lookupSafe (cstring_makeLiteralTemp ("main"));
691 if (uentry_isValid (ue))
693 uentry_setUsed (ue, fileloc_observeBuiltin ());
696 usymtab_allUsed ();
699 if (context_maybeSet (FLG_EXPORTLOCAL))
701 usymtab_exportLocal ();
705 if (context_maybeSet (FLG_EXPORTHEADER))
707 usymtab_exportHeader ();
710 if (context_getFlag (FLG_SHOWUSES))
712 usymtab_displayAllUses ();
715 context_checkSuppressCounts ();
717 if (context_doDump ())
719 cstring dump = context_getDump ();
721 dumpState (dump);
724 # ifdef DOANNOTS
725 printAnnots ();
726 # endif
728 if (g_csvstream != NULL) {
729 displayScan (message ("Closing CSV file: %s", context_getString (FLG_CSV)));
730 check (fclose (g_csvstream) == 0);
733 if (context_getFlag (FLG_SHOWSUMMARY))
735 summarizeErrors ();
739 bool isQuiet = context_getFlag (FLG_QUIET);
740 cstring specErrors = cstring_undefined;
741 int nspecErrors = lclNumberErrors ();
743 expsuccess = TRUE;
745 if (context_neednl ())
746 fprintf (g_warningstream, "\n");
748 if (nspecErrors > 0)
750 if (nspecErrors == context_getLCLExpect ())
752 specErrors =
753 message ("%d spec warning%&, as expected\n ",
754 nspecErrors);
756 else
758 if (context_getLCLExpect () > 0)
760 specErrors =
761 message ("%d spec warning%&, expected %d\n ",
762 nspecErrors,
763 (int) context_getLCLExpect ());
765 else
767 specErrors = message ("%d spec warning%&\n ",
768 nspecErrors);
769 expsuccess = FALSE;
773 else
775 if (context_getLCLExpect () > 0)
777 specErrors = message ("No spec warnings, expected %d\n ",
778 (int) context_getLCLExpect ());
779 expsuccess = FALSE;
783 if (context_anyErrors ())
785 if (context_numErrors () == context_getExpect ())
787 if (!isQuiet) {
788 llmsg (message ("Finished checking --- "
789 "%s%d code warning%&, as expected",
790 specErrors, context_numErrors ()));
793 else
795 if (context_getExpect () > 0)
797 if (!isQuiet) {
798 llmsg (message
799 ("Finished checking --- "
800 "%s%d code warning%&, expected %d",
801 specErrors, context_numErrors (),
802 (int) context_getExpect ()));
805 expsuccess = FALSE;
807 else
809 if (!isQuiet)
811 llmsg (message ("Finished checking --- "
812 "%s%d code warning%&",
813 specErrors, context_numErrors ()));
816 expsuccess = FALSE;
820 else
822 if (context_getExpect () > 0)
824 if (!isQuiet) {
825 llmsg (message
826 ("Finished checking --- "
827 "%sno code warnings, expected %d",
828 specErrors,
829 (int) context_getExpect ()));
832 expsuccess = FALSE;
834 else
836 if (context_getLinesProcessed () > 0)
838 if (cstring_isEmpty (specErrors))
840 if (!isQuiet)
842 llmsg (message ("Finished checking --- no warnings"));
845 else
847 if (!isQuiet)
849 llmsg (message ("Finished checking --- %sno code warnings",
850 specErrors));
854 else
856 if (!isQuiet) {
857 llmsg (message ("Finished checking --- %sno code processed",
858 specErrors));
864 cstring_free (specErrors);
866 if (context_numBugs () > 0) {
867 expsuccess = FALSE;
868 if (!isQuiet) {
869 llmsg (message (" %d internal bugs reported", context_numBugs ()));
874 if (context_getFlag (FLG_STATS))
876 clock_t ttime = clock () - before;
877 int specLines = context_getSpecLinesProcessed ();
878 cstring specmsg = cstring_undefined;
880 rstime = clock ();
882 if (specLines > 0)
884 specmsg = message ("%d spec, ", specLines);
887 /* The clock might wrap around, not platform-independent easy way to deal with this... */
888 if (ttime > 0)
890 # ifndef CLOCKS_PER_SEC
891 lldiagmsg (message ("%s%d source lines in %d time steps (steps/sec unknown)\n",
892 specmsg,
893 context_getLinesProcessed (),
894 (int) ttime));
895 # else
896 lldiagmsg (message ("%s%d source lines in %f s.\n",
897 specmsg,
898 context_getLinesProcessed (),
899 (double) ttime / CLOCKS_PER_SEC));
900 DPRINTF (("Time: %ld [%ld - %ld]", ttime, rstime, before));
901 # endif
903 else
905 lldiagmsg (message ("%s%d source lines\n",
906 specmsg,
907 context_getLinesProcessed ()));
911 else
913 rstime = clock ();
916 if (context_getFlag (FLG_TIMEDIST))
918 clock_t ttime = clock () - before;
920 if (ttime > 0)
922 char *msg = (char *) dmalloc (256 * sizeof (*msg));
924 if (anylcl)
926 (void) snprintf (msg, 256,
927 "Time distribution (percent): initialize %.2f / lcl %.2f / "
928 "pre-process %.2f / c check %.2f / finalize %.2f \n",
929 (100.0 * (double) (libtime - before) / ttime),
930 (100.0 * (double) (lcltime - libtime) / ttime),
931 (100.0 * (double) (pptime - lcltime) / ttime),
932 (100.0 * (double) (cptime - pptime) / ttime),
933 (100.0 * (double) (rstime - cptime) / ttime));
935 else
937 (void) snprintf (msg, 256,
938 "Time distribution (percent): initialize %.2f / "
939 "pre-process %.2f / c check %.2f / finalize %.2f \n",
940 (100.0 * (double) (libtime - before) / ttime),
941 (100.0 * (double) (pptime - libtime) / ttime),
942 (100.0 * (double) (cptime - pptime) / ttime),
943 (100.0 * (double) (rstime - cptime) / ttime));
946 llgenindentmsgnoloc (cstring_fromCharsO (msg));
950 cleanupFiles ();
951 cleanupMemory ();
952 return (expsuccess ? EXIT_SUCCESS: EXIT_FAILURE);
955 static void
956 llinterrupt (int i)
958 if (i == SIGINT)
960 fprintf (g_errorstream, "*** Interrupt\n");
961 failexit ();
963 else
965 if (i == SIGSEGV)
967 /* Cheat when there are parse errors */
968 checkParseError ();
970 fprintf (g_errorstream, "*** Segmentation Violation\n");
972 /* Don't catch it if fileloc_unparse causes a signal */
973 (void) signal (SIGSEGV, NULL);
975 else
977 fprintf (g_errorstream, "*** Signal: %d\n", i);
980 /*@-mustfree@*/ /* no clean-up, so freeing file location string is useless */
981 fprintf (g_errorstream, "*** Location (not trusted): %s\n",
982 cstring_toCharsSafe (fileloc_unparse (g_currentloc)));
983 /*@=mustfree@*/
984 printCodePoint ();
985 fprintf (g_errorstream, "*** Please report bug to %s\n"
986 "*** A useful bug report should include everything we need to reproduce the bug.\n",
987 SPLINT_MAINTAINER);
989 /* Note: no clean-up */
990 exit (EXIT_FAILURE);
994 static void
995 cleanupFiles (void)
997 setCodePoint ();
1000 ** Close all open files
1001 ** (There should only be open files, if we exited after a fatal error.)
1004 fileTable_closeAll (context_fileTable ());
1006 osd_fcloseall ();
1008 if (context_getFlag (FLG_KEEP))
1010 check (fputs ("Temporary files kept:\n", g_messagestream) != EOF);
1011 fileTable_printTemps (context_fileTable ());
1013 else
1015 fileTable_cleanup (context_fileTable ());
1019 static void
1020 cleanupMemory (void)
1022 usymtab_destroyMod ();
1023 context_destroyMod ();
1024 exprNode_destroyMod ();
1025 cppReader_destroyMod ();
1026 sRef_destroyMod ();
1027 uentry_destroyMod ();
1028 typeIdSet_destroyMod ();
1029 qual_destroyMod ();
1030 osd_destroyMod ();
1031 fileloc_destroyMod ();
1035 ** cleans up and exits
1038 /*@noreturn@*/ void
1039 failexit (void)
1041 cleanupFiles ();
1042 cleanupMemory ();
1043 exit (EXIT_FAILURE);
1046 static fileIdList preprocessFiles (fileIdList fl)
1047 /*@modifies fileSystem@*/
1049 bool msg = (context_getFlag (FLG_SHOWSCAN) && fileIdList_size (fl) > 10);
1050 int skip = (fileIdList_size (fl) / 5);
1051 int filesprocessed = 0;
1052 fileIdList dfiles = fileIdList_create ();
1054 fileloc_free (g_currentloc);
1055 g_currentloc = fileloc_createBuiltin ();
1057 fileIdList_elements (fl, fid)
1059 cstring ppfname;
1061 llassert (fileId_isValid(fid));
1063 ppfname = fileTable_fileName (fid);
1064 if (!(osd_fileIsReadable (ppfname)))
1066 lldiagmsg (message ("Cannot open file: %q", osd_outputPath (ppfname)));
1068 else
1070 fileId dfile;
1071 fileTable ft;
1073 llassert (cstring_isNonEmpty (ppfname));
1075 if (msg)
1077 if ((filesprocessed % skip) == 0)
1079 if (filesprocessed == 0) {
1080 displayScanContinue (cstring_makeLiteral (" "));
1082 else {
1083 displayScanContinue (cstring_makeLiteral ("."));
1086 filesprocessed++;
1089 ft = context_fileTable ();
1090 dfile = fileTable_addTempFile (ft, ft->elements[fid]->ftype, fid);
1091 DPRINTF (("infile: %s", ppfname));
1092 DPRINTF (("outfile: %s", fileTable_fileName (dfile)));
1093 if (cppProcess (ppfname, fileTable_fileName (dfile)) != 0)
1095 llfatalerror (message ("Preprocessing error for file: %s",
1096 fileTable_rootFileName (fid)));
1099 fileIdList_add (dfiles, dfile);
1101 } end_fileIdList_elements;
1103 return dfiles;
1106 /* This should be in an lclUtils.c file... */
1107 static char*
1108 specFullName (char *specfile, /*@out@*/ char **inpath)
1110 /* extract the path and the specname associated with the given file */
1111 char *specname = (char *) dmalloc (sizeof (*specname)
1112 * (strlen (specfile) + 9));
1113 char *ospecname = specname;
1114 char *path = (char *) dmalloc (sizeof (*path) * (strlen (specfile)));
1115 size_t size;
1116 long int i, j;
1118 /* initialized path to empty string or may have accidental garbage */
1119 *path = '\0';
1121 /*@-mayaliasunique@*/
1122 strcpy (specname, specfile);
1123 /*@=mayaliasunique@*/
1125 /* trim off pathnames in specfile */
1126 size = strlen (specname);
1128 for (i = size_toInt (size) - 1; i >= 0; i--)
1130 if (specname[i] == CONNECTCHAR)
1132 /* strcpy (specname, (char *)specname+i+1); */
1133 for (j = 0; j <= i; j++) /* include '/' */
1135 path[j] = specname[j];
1138 path[i + 1] = '\0';
1139 specname += i + 1;
1140 break;
1145 ** also remove .lcl file extension, assume it's the last extension
1146 ** of the file name
1149 size = strlen (specname);
1151 for (i = size_toInt (size) - 1; i >= 0; i--)
1153 if (specname[i] == '.')
1155 specname[i] = '\0';
1156 break;
1160 *inpath = path;
1163 ** If specname no longer points to the original char,
1164 ** we need to allocate a new pointer and copy the string.
1167 if (specname != ospecname) {
1168 char *rspecname = (char *) dmalloc (sizeof (*rspecname) * (strlen (specname) + 1));
1169 strcpy (rspecname, specname); /* evs 2000-05-16: Bug: was ospecname! */
1170 sfree (ospecname);
1171 return rspecname;
1174 return specname;
1177 static void
1178 warnSysFiles(fileIdList files)
1180 fileIdList_elements (files, fid)
1182 llassert (fileId_isValid(fid));
1183 if (fileTable_isSystemFile (context_fileTable (), fid) &&
1184 /* don't warn for non-readable files (preprocess ignores them) */
1185 osd_fileIsReadable (fileTable_fileName (fid)))
1187 if (!context_getFlag (FLG_SYSTEMDIRERRORS))
1189 voptgenerror (FLG_WARNSYSFILES,
1190 message ("Warning: %s is considered a system file. No errors in this file will be reported.",
1191 fileTable_rootFileName (fid)),
1192 g_currentloc);
1196 end_fileIdList_elements;