2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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
27 ** Main module for Splint annotation-assisted program checker
33 ** Ensure that WIN32 and _WIN32 are both defined or both undefined.
38 # error "Inconsistent definitions."
42 # error "Inconsistent definitions."
51 # include "splintMacros.nf"
58 # include "scanline.h"
59 # include "lclscanline.h"
60 # include "lclsyntable.h"
61 # include "lcltokentable.h"
62 # include "lslparse.h"
64 # include "syntable.h"
65 # include "tokentable.h"
71 # include "Headers/version.h" /* Visual C++ finds the wrong version.h */
73 # include "cgrammar.h"
78 extern /*@external@*/ int yydebug;
79 static void cleanupFiles (void);
81 ** evans 2002-07-03: renamed from interrupt to avoid conflict with WATCOM compiler keyword
82 ** (Suggested by Adam Clarke)
85 static void llinterrupt (int p_i);
87 static void describeVars (void);
88 static bool specialFlagsHelp (char *p_next);
89 static bool hasShownHerald = FALSE;
90 static char *specFullName (char *p_specfile, /*@out@*/ char **p_inpath)
91 /*@modifies *p_inpath@*/ ;
93 static bool anylcl = FALSE;
94 static clock_t inittime;
96 static fileIdList preprocessFiles (fileIdList, bool)
97 /*@modifies fileSystem@*/ ;
99 static void warnSysFiles(fileIdList p_files) /*@modifies fileSystem@*/;
102 void lslCleanup (void)
103 /*@globals killed g_symtab@*/
104 /*@modifies internalState, g_symtab@*/
107 ** Cleanup all the LCL/LSL.
110 static bool didCleanup = FALSE;
112 llassert (!didCleanup);
117 lsymbol_destroyMod ();
118 LCLSynTableCleanup ();
119 LCLTokenTableCleanup ();
120 LCLScanLineCleanup ();
123 /* clean up LSL parsing */
126 ltokenTableCleanup ();
130 symtable_free (g_symtab);
135 lslProcess (fileIdList lclfiles)
136 /*@globals undef g_currentSpec, undef g_currentSpecName, g_currentloc,
137 undef killed g_symtab; @*/
138 /*@modifies g_currentSpec, g_currentSpecName, g_currentloc, internalState, fileSystem; @*/
141 bool parser_status = FALSE;
142 bool overallStatus = FALSE;
147 context_resetSpecLines ();
149 fileIdList_elements (lclfiles, fid)
151 cstring actualName = cstring_undefined;
152 cstring fname = fileTable_fileName (fid);
154 if (osd_getPath (cstring_fromChars (g_localSpecPath),
155 fname, &actualName) == OSD_FILENOTFOUND)
157 if (mstring_equal (g_localSpecPath, "."))
159 lldiagmsg (message ("Spec file not found: %q", osd_outputPath (fname)));
163 lldiagmsg (message ("Spec file not found: %q (on %s)",
164 osd_outputPath (fname),
165 cstring_fromChars (g_localSpecPath)));
170 inputStream specFile;
172 char *namePtr = actualName;
174 while (*namePtr == '.' && *(namePtr + 1) == CONNECTCHAR)
178 /*@noaccess cstring@*/
180 g_currentSpec = cstring_fromCharsNew (namePtr);
182 specFile = inputStream_create (cstring_copy (g_currentSpec),
183 LCL_EXTENSION, TRUE);
185 llassert (inputStream_isDefined (specFile));
187 g_currentSpecName = specFullName
188 (cstring_toCharsSafe (g_currentSpec),
193 displayScan (message ("reading spec %s", g_currentSpec));
195 /* Open the source file */
197 if (!inputStream_open (specFile))
199 lldiagmsg (message ("Cannot open file: %q",
200 osd_outputPath (inputStream_fileName (specFile))));
201 inputStream_free (specFile);
205 scopeInfo dummy_scope = (scopeInfo) dmalloc (sizeof (*dummy_scope));
206 dummy_scope->kind = SPE_INVALID;
209 LCLScanReset (specFile);
212 ** Minor hacks to allow more than one LCL file to
213 ** be scanned, while keeping initializations
216 symtable_enterScope (g_symtab, dummy_scope);
217 resetImports (cstring_fromChars (g_currentSpecName));
218 context_enterLCLfile ();
219 (void) lclHadNewError ();
221 parser_status = (ylparse () != 0);
222 context_exitLCLfile ();
224 overallStatus = parser_status || lclHadNewError ();
226 if (context_getFlag (FLG_DOLCS))
230 outputLCSFile (path, "%FAILED Output from ",
235 outputLCSFile (path, "%PASSED Output from ",
240 (void) inputStream_close (specFile);
241 inputStream_free (specFile);
243 symtable_exitScope (g_symtab);
246 cstring_free (actualName);
247 } end_fileIdList_elements;
249 /* Can cleanup lsl stuff right away */
253 g_currentSpec = cstring_undefined;
254 g_currentSpecName = NULL;
257 static void handlePassThroughFlag (char *arg)
260 char *quotechar = strchr (curarg, '\"');
263 char *freearg = NULL;
265 while (quotechar != NULL)
267 if (*(quotechar - 1) == '\\')
269 char *tp = quotechar - 2;
280 curarg = quotechar + 1;
281 quotechar = strchr (curarg, '\"');
286 llassert (quotechar != NULL);
288 offset = (quotechar - arg) + 2;
292 arg = cstring_toCharsSafe
293 (message ("%s\"\'%s",
294 cstring_fromChars (arg),
295 cstring_fromChars (quotechar + 1)));
301 arg = cstring_toCharsSafe
302 (message ("%s\'\"%s",
303 cstring_fromChars (arg),
304 cstring_fromChars (quotechar + 1)));
309 curarg = arg + offset;
310 quotechar = strchr (curarg, '\"');
316 voptgenerror (FLG_BADFLAG,
317 message ("Unclosed quote in flag: %s",
318 cstring_fromChars (arg)),
327 ** If the value is surrounded by single quotes ('), remove
328 ** them. This is an artifact of UNIX command line?
331 def = osd_fixDefine (cstring_fromChars (arg + 1));
332 DPRINTF (("Do define: %s", def));
334 DPRINTF (("After define"));
336 } else if (arg[0] == 'U') {
337 cppDoUndefine (cstring_fromChars (arg + 1));
346 void showHerald (void)
348 if (hasShownHerald || context_getFlag (FLG_QUIET))
354 fprintf (g_messagestream, "%s\n\n", SPLINT_VERSION);
355 hasShownHerald = TRUE;
361 ** Disable MSVC++ warning about return value. Methinks humbly splint control
362 ** comments are a mite more legible.
366 # pragma warning (disable:4035)
369 int main (int argc, char *argv[])
370 /*@globals killed undef g_currentloc,
371 killed g_localSpecPath,
372 killed undef g_currentSpec,
373 killed undef g_currentSpecName,
375 undef g_warningstream, g_messagestream, g_errorstream;
377 /*@modifies g_currentloc, g_localSpecPath, g_currentSpec, g_currentSpecName,
381 bool first_time = TRUE;
383 inputStream sourceFile = inputStream_undefined;
385 fileIdList dercfiles;
386 cstringList passThroughArgs = cstringList_undefined;
387 fileIdList cfiles, xfiles, lclfiles, mtfiles;
388 clock_t before, lcltime, libtime, pptime, cptime, rstime;
392 _wildcard (&argc, &argv);
395 g_warningstream = stdout;
396 g_messagestream = stderr;
397 g_errorstream = stderr;
399 (void) signal (SIGINT, llinterrupt);
400 (void) signal (SIGSEGV, llinterrupt);
404 clabstract_initMod ();
405 typeIdSet_initMod ();
407 cppReader_initMod ();
411 g_currentloc = fileloc_createBuiltin ();
416 context_setInCommandLine ();
420 help_showAvailableHelp ();
424 /* -help must be the first flag to get help */
425 if (flagcode_isHelpFlag (flags_identifyFlag (cstring_fromChars (argv[1]))))
428 ** Skip first flag and help flag
431 help_processFlags (argc - 2, argv + 2);
439 ** Add include directories from environment.
443 cstring incval = cstring_copy (osd_getEnvironmentVariable (INCLUDEPATH_VAR));
444 cstring oincval = incval;
446 if (cstring_isDefined (incval))
449 ** Each directory on the include path is a system include directory.
452 DPRINTF (("include: %s", incval));
453 context_setString (FLG_SYSTEMDIRS, cstring_copy (incval));
455 while (cstring_isDefined (incval))
458 char *nextsep = strchr (incval, PATH_SEPARATOR);
464 dir = cstring_copy (incval);
466 if (cstring_length (dir) == 0
467 || !isalpha ((int) cstring_firstChar (dir)))
470 ** win32 environment values can have special values,
476 cppAddIncludeDir (dir);
479 *nextsep = PATH_SEPARATOR;
480 incval = cstring_fromChars (nextsep + 1);
488 /*@noaccess cstring@*/
491 else /* 2001-09-09: herbert */
493 /* Put C_INCLUDE_PATH directories in sysdirs */
494 cstring cincval = osd_getEnvironmentVariable (cstring_makeLiteralTemp ("C_INCLUDE_PATH"));
496 if (cstring_isDefined (cincval))
498 context_setString (FLG_SYSTEMDIRS, cstring_copy (cincval));
503 cstring_free (oincval);
507 ** check RCFILE for default flags
511 ** Process command line message formatting flags before reading rc file
515 cstring home = osd_getHomeDir ();
516 cstring fname = cstring_undefined;
517 bool defaultf = TRUE;
520 for (i = 1; i < argc; i++)
525 if (*thisarg == '-' || *thisarg == '+')
527 bool set = (*thisarg == '+');
533 ** Don't report warnings this time
536 opt = flags_identifyFlagQuiet (cstring_fromChars (thisarg));
542 else if (flagcode_isMessageControlFlag (opt))
545 ** Need to set it immediately, so rc file scan is displayed
548 context_userSetFlag (opt, set);
550 if (flagcode_hasArgument (opt))
552 llassert (flagcode_hasString (opt));
556 fname = cstring_fromChars (argv[i]);
557 setStringFlag (opt, fname);
564 ("Flag %s must be followed by a string",
565 flagcode_unparse (opt)),
570 else if (opt == FLG_OPTF)
575 fname = cstring_fromChars (argv[i]);
576 (void) rcfiles_read (fname, &passThroughArgs, TRUE);
580 (cstring_makeLiteral ("Flag f to select options file "
581 "requires an argument"));
585 ; /* wait to process later */
592 if (!nof && defaultf)
595 ** No explicit rc file, first try reading ~/.splintrc
598 if (cstring_isUndefined (fname))
600 if (!cstring_isEmpty (home))
602 bool readhomerc, readaltrc;
603 cstring homename, altname;
605 homename = message ("%s%h%s", home, CONNECTCHAR,
606 cstring_fromChars (RCFILE));
607 readhomerc = rcfiles_read (homename, &passThroughArgs, FALSE);
610 ** Try ~/.splintrc also for historical accuracy
613 altname = message ("%s%h%s", home, CONNECTCHAR,
614 cstring_fromChars (ALTRCFILE));
615 readaltrc = rcfiles_read (altname, &passThroughArgs, FALSE);
617 if (readhomerc && readaltrc)
622 message ("Found both %s and %s files. Using both files, "
623 "but recommend using only %s to avoid confusion.",
624 homename, altname, homename),
628 cstring_free (homename);
629 cstring_free (altname);
634 ** Next, read .splintrc in the current working directory
638 cstring rcname = message ("%s%s",osd_getCurrentDirectory (), cstring_fromChars (RCFILE));
639 cstring altname = message ("%s%s",osd_getCurrentDirectory (), cstring_fromChars (ALTRCFILE));
640 bool readrc, readaltrc;
642 readrc = rcfiles_read (rcname, &passThroughArgs, FALSE);
643 readaltrc = rcfiles_read (altname, &passThroughArgs, FALSE);
645 if (readrc && readaltrc)
647 voptgenerror (FLG_WARNRC,
648 message ("Found both %s and %s files. Using both files, "
649 "but recommend using only %s to avoid confusion.",
650 rcname, altname, rcname),
655 cstring_free (rcname);
656 cstring_free (altname);
662 llassert (fileloc_isBuiltin (g_currentloc));
664 cfiles = fileIdList_create ();
665 xfiles = fileIdList_create ();
666 lclfiles = fileIdList_create ();
667 mtfiles = fileIdList_create ();
669 /* argv[0] is the program name, don't pass it to flags_processFlags */
670 flags_processFlags (TRUE, xfiles, cfiles,
683 context_resetErrors ();
684 context_clearInCommandLine ();
686 anylcl = !fileIdList_isEmpty (lclfiles);
688 if (context_doMerge ())
690 cstring m = context_getMerge ();
692 displayScanOpen (message ("< loading %s ", m));
696 if (!usymtab_existsType (context_getBoolName ()))
703 if (!context_getFlag (FLG_NOLIB) && loadStandardState ())
712 /* setup bool type and constants */
716 fileloc_free (g_currentloc);
717 g_currentloc = fileloc_createBuiltin ();
720 ** Read metastate files (must happen before loading libraries)
723 fileIdList_elements (mtfiles, mtfile)
725 context_setFileId (mtfile);
726 displayScan (message ("processing %s", fileTable_rootFileName (mtfile)));
727 mtreader_readFile (cstring_copy (fileTable_fileName (mtfile)));
728 } end_fileIdList_elements;
734 lslProcess (lclfiles);
737 usymtab_initGlobalMarker ();
742 ** call the pre-preprocessor and /lib/cpp to generate appropriate
747 context_setInCommandLine ();
749 DPRINTF (("Pass through: %s", cstringSList_unparse (passThroughArgs)));
751 cstringList_elements (passThroughArgs, thisarg)
753 handlePassThroughFlag (cstring_toCharsSafe (thisarg));
755 end_cstringList_elements;
757 cstringList_free (passThroughArgs);
761 DPRINTF (("Initializing cpp reader!"));
762 cppReader_initialize ();
763 cppReader_saveDefinitions ();
765 context_clearInCommandLine ();
767 if (!context_getFlag (FLG_NOPP))
773 displayScanOpen (cstring_makeLiteral ("preprocessing"));
777 context_setPreprocessing ();
778 dercfiles = preprocessFiles (xfiles, TRUE);
779 tfiles = preprocessFiles (cfiles, FALSE);
780 warnSysFiles(cfiles);
781 dercfiles = fileIdList_append (dercfiles, tfiles);
782 fileIdList_free (tfiles);
784 context_clearPreprocessing ();
786 fileIdList_free (cfiles);
794 dercfiles = fileIdList_append (cfiles, xfiles);
799 ** now, check all the corresponding C files
801 ** (for now these are just <file>.c, but after pre-processing
802 ** will be <tmpprefix>.<file>.c)
807 int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
811 llbug (message ("Files unclosed: %d", nfiles));
816 DPRINTF (("Initializing..."));
820 DPRINTF (("Okay..."));
822 fileIdList_elements (dercfiles, fid)
824 sourceFile = inputStream_create (cstring_copy (fileTable_fileName (fid)), C_EXTENSION, TRUE);
825 context_setFileId (fid);
827 /* Open source file */
829 if (inputStream_isUndefined (sourceFile) || (!inputStream_open (sourceFile)))
831 /* previously, this was ignored ?! */
832 llbug (message ("Could not open temp file: %s", fileTable_fileName (fid)));
836 yyin = inputStream_getFile (sourceFile); /*< shared <- only */
838 llassert (yyin != NULL);
840 displayScan (message ("checking %q", osd_outputPath (fileTable_rootFileName (fid))));
843 ** Every time, except the first time, through the loop,
844 ** need to call yyrestart to clean up the parse buffer.
849 (void) yyrestart (yyin);
856 DPRINTF (("Entering..."));
857 context_enterFile ();
859 context_exitCFile ();
861 (void) inputStream_close (sourceFile);
864 inputStream_free (sourceFile); /* evans 2002-07-12: why no warning without this?!! */
865 } end_fileIdList_elements;
867 fileIdList_free (dercfiles); /* evans 2002-07-12: why no warning without this?!! */
870 /* process any leftover macros */
872 context_processAllMacros ();
874 /* check everything that was specified was defined */
876 /* don't check if no c files were processed ?
877 ** is this correct behaviour?
880 displayScan (cstring_makeLiteral ("global checks"));
884 if (context_getLinesProcessed () > 0)
886 usymtab_allDefined ();
889 if (context_maybeSet (FLG_TOPUNUSED))
891 uentry ue = usymtab_lookupSafe (cstring_makeLiteralTemp ("main"));
893 if (uentry_isValid (ue))
895 uentry_setUsed (ue, fileloc_observeBuiltin ());
901 if (context_maybeSet (FLG_EXPORTLOCAL))
903 usymtab_exportLocal ();
907 if (context_maybeSet (FLG_EXPORTHEADER))
909 usymtab_exportHeader ();
912 if (context_getFlag (FLG_SHOWUSES))
914 usymtab_displayAllUses ();
917 context_checkSuppressCounts ();
919 if (context_doDump ())
921 cstring dump = context_getDump ();
932 if (context_getFlag (FLG_SHOWSUMMARY))
939 bool isQuiet = context_getFlag (FLG_QUIET);
940 cstring specErrors = cstring_undefined;
941 int nspecErrors = lclNumberErrors ();
945 if (context_neednl ())
946 fprintf (g_warningstream, "\n");
950 if (nspecErrors == context_getLCLExpect ())
953 message ("%d spec warning%&, as expected\n ",
958 if (context_getLCLExpect () > 0)
961 message ("%d spec warning%&, expected %d\n ",
963 (int) context_getLCLExpect ());
967 specErrors = message ("%d spec warning%&\n ",
975 if (context_getLCLExpect () > 0)
977 specErrors = message ("No spec warnings, expected %d\n ",
978 (int) context_getLCLExpect ());
983 if (context_anyErrors ())
985 if (context_numErrors () == context_getExpect ())
988 llmsg (message ("Finished checking --- "
989 "%s%d code warning%&, as expected",
990 specErrors, context_numErrors ()));
995 if (context_getExpect () > 0)
999 ("Finished checking --- "
1000 "%s%d code warning%&, expected %d",
1001 specErrors, context_numErrors (),
1002 (int) context_getExpect ()));
1012 llmsg (message ("Finished checking --- "
1013 "%s%d code warning%&",
1014 specErrors, context_numErrors ()));
1023 if (context_getExpect () > 0)
1027 ("Finished checking --- "
1028 "%sno code warnings, expected %d",
1030 (int) context_getExpect ()));
1037 if (context_getLinesProcessed () > 0)
1039 if (cstring_isEmpty (specErrors))
1043 llmsg (message ("Finished checking --- no warnings"));
1050 llmsg (message ("Finished checking --- %sno code warnings",
1058 llmsg (message ("Finished checking --- %sno code processed",
1065 cstring_free (specErrors);
1068 if (context_getFlag (FLG_STATS))
1070 clock_t ttime = clock () - before;
1071 int specLines = context_getSpecLinesProcessed ();
1072 cstring specmsg = cstring_undefined;
1078 specmsg = message ("%d spec, ", specLines);
1081 /* The clock might wrap around, not platform-independent easy way to deal with this... */
1084 # ifndef CLOCKS_PER_SEC
1085 lldiagmsg (message ("%s%d source lines in %d time steps (steps/sec unknown)\n",
1087 context_getLinesProcessed (),
1090 lldiagmsg (message ("%s%d source lines in %f s.\n",
1092 context_getLinesProcessed (),
1093 (double) ttime / CLOCKS_PER_SEC));
1094 DPRINTF (("Time: %ld [%ld - %ld]", ttime, rstime, before));
1099 lldiagmsg (message ("%s%d source lines\n",
1101 context_getLinesProcessed ()));
1110 if (context_getFlag (FLG_TIMEDIST))
1112 clock_t ttime = clock () - before;
1116 char *msg = (char *) dmalloc (256 * sizeof (*msg));
1120 (void) snprintf (msg, 256,
1121 "Time distribution (percent): initialize %.2f / lcl %.2f / "
1122 "pre-process %.2f / c check %.2f / finalize %.2f \n",
1123 (100.0 * (double) (libtime - before) / ttime),
1124 (100.0 * (double) (lcltime - libtime) / ttime),
1125 (100.0 * (double) (pptime - lcltime) / ttime),
1126 (100.0 * (double) (cptime - pptime) / ttime),
1127 (100.0 * (double) (rstime - cptime) / ttime));
1131 (void) snprintf (msg, 256,
1132 "Time distribution (percent): initialize %.2f / "
1133 "pre-process %.2f / c check %.2f / finalize %.2f \n",
1134 (100.0 * (double) (libtime - before) / ttime),
1135 (100.0 * (double) (pptime - libtime) / ttime),
1136 (100.0 * (double) (cptime - pptime) / ttime),
1137 (100.0 * (double) (rstime - cptime) / ttime));
1140 llgenindentmsgnoloc (cstring_fromCharsO (msg));
1144 llexit (expsuccess ? LLSUCCESS : LLFAILURE);
1145 BADBRANCHRET (LLFAILURE);
1150 ** Reenable return value warnings.
1152 # pragma warning (default:4035)
1161 fprintf (g_errorstream, "*** Interrupt\n");
1162 llexit (LLINTERRUPT);
1167 /* Cheat when there are parse errors */
1170 fprintf (g_errorstream, "*** Segmentation Violation\n");
1172 /* Don't catch it if fileloc_unparse causes a signal */
1173 (void) signal (SIGSEGV, NULL);
1175 loc = fileloc_unparse (g_currentloc);
1177 fprintf (g_errorstream, "*** Location (not trusted): %s\n",
1178 cstring_toCharsSafe (loc));
1181 fprintf (g_errorstream, "*** Please report bug to %s\n", SPLINT_MAINTAINER);
1185 fprintf (g_errorstream, "*** Signal: %d\n", i);
1187 fprintf (g_errorstream, "*** Location (not trusted): %s\n",
1188 cstring_toCharsSafe (fileloc_unparse (g_currentloc)));
1191 fprintf (g_errorstream, "*** Please report bug to %s ***\n", SPLINT_MAINTAINER);
1199 static bool doneCleanup = FALSE;
1201 /* make sure this is only called once! */
1203 if (doneCleanup) return;
1208 ** Close all open files
1209 ** (There should only be open files, if we exited after a fatal error.)
1212 fileTable_closeAll (context_fileTable ());
1214 if (context_getFlag (FLG_KEEP))
1216 check (fputs ("Temporary files kept:\n", g_messagestream) != EOF);
1217 fileTable_printTemps (context_fileTable ());
1222 int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
1226 llbug (message ("Files unclosed: %d", nfiles));
1229 fileTable_cleanup (context_fileTable ());
1236 ** cleans up temp files (if necessary) and exits
1242 DPRINTF (("llexit: %d", status));
1245 if (status == LLFAILURE)
1253 if (status != LLFAILURE)
1255 usymtab_destroyMod ();
1256 context_destroyMod ();
1257 exprNode_destroyMod ();
1258 cppReader_destroyMod ();
1260 uentry_destroyMod ();
1261 typeIdSet_destroyMod ();
1264 fileloc_destroyMod ();
1266 dmalloc_shutdown ();
1270 exit ((status == LLSUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE);
1273 static fileIdList preprocessFiles (fileIdList fl, bool xhfiles)
1274 /*@modifies fileSystem@*/
1276 bool msg = (context_getFlag (FLG_SHOWSCAN) && fileIdList_size (fl) > 10);
1277 int skip = (fileIdList_size (fl) / 5);
1278 int filesprocessed = 0;
1279 fileIdList dfiles = fileIdList_create ();
1281 fileloc_free (g_currentloc);
1282 g_currentloc = fileloc_createBuiltin ();
1284 fileIdList_elements (fl, fid)
1286 cstring ppfname = fileTable_fileName (fid);
1288 if (!(osd_fileIsReadable (ppfname)))
1290 lldiagmsg (message ("Cannot open file: %q", osd_outputPath (ppfname)));
1291 ppfname = cstring_undefined;
1294 if (cstring_isDefined (ppfname))
1296 fileId dfile = fileTable_addCTempFile (context_fileTable (), fid);
1300 llassert (fileTable_isXHFile (context_fileTable (), dfile));
1303 llassert (cstring_isNonEmpty (ppfname));
1307 if ((filesprocessed % skip) == 0)
1309 if (filesprocessed == 0) {
1310 displayScanContinue (cstring_makeLiteral (" "));
1313 displayScanContinue (cstring_makeLiteral ("."));
1319 DPRINTF (("outfile: %s", fileTable_fileName (dfile)));
1321 if (cppProcess (ppfname, fileTable_fileName (dfile)) != 0)
1323 llfatalerror (message ("Preprocessing error for file: %s",
1324 fileTable_rootFileName (fid)));
1327 fileIdList_add (dfiles, dfile);
1329 } end_fileIdList_elements;
1334 /* This should be in an lclUtils.c file... */
1335 char *specFullName (char *specfile, /*@out@*/ char **inpath)
1337 /* extract the path and the specname associated with the given file */
1338 char *specname = (char *) dmalloc (sizeof (*specname)
1339 * (strlen (specfile) + 9));
1340 char *ospecname = specname;
1341 char *path = (char *) dmalloc (sizeof (*path) * (strlen (specfile)));
1345 /* initialized path to empty string or may have accidental garbage */
1348 /*@-mayaliasunique@*/
1349 strcpy (specname, specfile);
1350 /*@=mayaliasunique@*/
1352 /* trim off pathnames in specfile */
1353 size = strlen (specname);
1355 for (i = size_toInt (size) - 1; i >= 0; i--)
1357 if (specname[i] == CONNECTCHAR)
1359 /* strcpy (specname, (char *)specname+i+1); */
1360 for (j = 0; j <= i; j++) /* include '/' */
1362 path[j] = specname[j];
1372 ** also remove .lcl file extension, assume it's the last extension
1376 size = strlen (specname);
1378 for (i = size_toInt (size) - 1; i >= 0; i--)
1380 if (specname[i] == '.')
1390 ** If specname no longer points to the original char,
1391 ** we need to allocate a new pointer and copy the string.
1394 if (specname != ospecname) {
1395 char *rspecname = (char *) dmalloc (sizeof (*rspecname) * (strlen (specname) + 1));
1396 strcpy (rspecname, specname); /* evs 2000-05-16: Bug: was ospecname! */
1404 void warnSysFiles(fileIdList files)
1406 fileIdList_elements (files, file)
1409 if (fileTable_isSystemFile (context_fileTable (), file) )
1411 if (!context_getFlag( FLG_SYSTEMDIRERRORS ) )
1413 voptgenerror (FLG_WARNSYSFILES, message ("Warning %s is a considered a system file. No errors in this file will be reported.", fileTable_rootFileName (file) ), g_currentloc);
1417 end_fileIdList_elements;