2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 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
27 ** Main module for LCLint checker
33 ** Ensure that WIN32 and _WIN32 are both defined or both undefined.
38 # error "Inconsistent definitions."
42 # error "Inconsistent definitions."
51 # include "lclintMacros.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"
74 # include "fileIdList.h"
76 # include "cgrammar.h"
80 # include "mtreader.h"
83 extern /*@external@*/ int yydebug;
85 static void printMail (void);
86 static void printMaintainer (void);
87 static void printReferences (void);
88 static void printFlags (void);
89 static void printAnnotations (void);
90 static void printParseErrors (void);
91 static void printComments (void);
92 static void describePrefixCodes (void);
93 static void cleanupFiles (void);
94 static void showHelp (void);
95 static void interrupt (int p_i);
97 static void loadrc (/*@open@*/ FILE *p_rcfile, cstringSList *p_passThroughArgs)
98 /*@ensures closed p_rcfile@*/ ;
100 static void describeVars (void);
101 static bool specialFlagsHelp (char *p_next);
102 static bool hasShownHerald = FALSE;
103 static char *specFullName (char *p_specfile, /*@out@*/ char **p_inpath)
104 /*@modifies *p_inpath@*/ ;
106 static bool anylcl = FALSE;
107 static clock_t inittime;
109 static /*@only@*/ /*@null@*/ inputStream initFile = inputStream_undefined;
111 static fileIdList preprocessFiles (fileIdList, bool)
112 /*@modifies fileSystem@*/ ;
117 void lslCleanup (void)
118 /*@globals killed g_symtab@*/
119 /*@modifies internalState, g_symtab@*/
122 ** Cleanup all the LCL/LSL.
125 static bool didCleanup = FALSE;
127 llassert (!didCleanup);
132 lsymbol_destroyMod ();
133 LCLSynTableCleanup ();
134 LCLTokenTableCleanup ();
135 LCLScanLineCleanup ();
138 /* clean up LSL parsing */
141 ltokenTableCleanup ();
145 symtable_free (g_symtab);
151 /*@globals undef g_symtab; @*/
152 /*@modifies g_symtab, internalState, fileSystem; @*/
155 ** Open init file provided by user, or use the default LCL init file
158 cstring larchpath = context_getLarchPath ();
159 inputStream LSLinitFile = inputStream_undefined;
163 if (inputStream_isUndefined (initFile))
165 initFile = inputStream_create (cstring_makeLiteral (INITFILENAME),
166 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
169 if (!inputStream_getPath (larchpath, initFile))
171 lldiagmsg (message ("Continuing without LCL init file: %s",
172 inputStream_fileName (initFile)));
176 if (!inputStream_open (initFile))
178 lldiagmsg (message ("Continuing without LCL init file: %s",
179 inputStream_fileName (initFile)));
185 if (!inputStream_open (initFile))
187 lldiagmsg (message ("Continuing without LCL init file: %s",
188 inputStream_fileName (initFile)));
192 /* Initialize checker */
200 LCLTokenTableInit ();
212 /* need this to initialize LCL checker */
214 llassert (inputStream_isDefined (initFile));
215 if (inputStream_isOpen (initFile))
219 LCLScanReset (initFile);
220 LCLProcessInitFileInit ();
221 LCLProcessInitFileReset ();
224 LCLProcessInitFile ();
225 LCLProcessInitFileCleanup ();
228 check (inputStream_close (initFile));
231 /* Initialize LSL init files, for parsing LSL signatures from LSL */
233 LSLinitFile = inputStream_create (cstring_makeLiteral ("lslinit.lsi"),
234 cstring_makeLiteralTemp (".lsi"),
237 if (!inputStream_getPath (larchpath, LSLinitFile))
239 lldiagmsg (message ("Continuing without LSL init file: %s",
240 inputStream_fileName (LSLinitFile)));
244 if (!inputStream_open (LSLinitFile))
246 lldiagmsg (message ("Continuing without LSL init file: %s",
247 inputStream_fileName (LSLinitFile)));
263 if (inputStream_isOpen (LSLinitFile))
266 LSLScanReset (LSLinitFile);
267 LSLProcessInitFileInit ();
269 LSLProcessInitFile ();
271 check (inputStream_close (LSLinitFile));
274 inputStream_free (LSLinitFile);
279 (cstring_makeLiteral ("LSL init file error. Attempting to continue."));
283 g_symtab = symtable_new ();
286 ** sort_init must come after symtab has been initialized
295 ** Equivalent to importing old spec_csupport.lcl
296 ** define immutable LCL type "bool" and bool constants TRUE and FALSE
297 ** and initialized them to be equal to LSL's "true" and "false".
299 ** Reads in CTrait.syms (derived from CTrait.lsl) on LARCH_PATH.
303 LCLReportEolTokens (FALSE);
307 lslProcess (fileIdList lclfiles)
308 /*@globals undef g_currentSpec, undef g_currentSpecName, g_currentloc,
309 undef killed g_symtab; @*/
310 /*@modifies g_currentSpec, g_currentSpecName, g_currentloc, internalState, fileSystem; @*/
313 bool parser_status = FALSE;
314 bool overallStatus = FALSE;
318 context_resetSpecLines ();
320 fileIdList_elements (lclfiles, fid)
322 cstring actualName = cstring_undefined;
323 cstring fname = fileName (fid);
325 if (osd_getPath (cstring_fromChars (g_localSpecPath),
326 fname, &actualName) == OSD_FILENOTFOUND)
328 if (mstring_equal (g_localSpecPath, "."))
330 lldiagmsg (message ("Spec file not found: %s", fname));
334 lldiagmsg (message ("Spec file not found: %s (on %s)",
336 cstring_fromChars (g_localSpecPath)));
341 inputStream specFile;
343 char *namePtr = actualName;
345 while (*namePtr == '.' && *(namePtr + 1) == CONNECTCHAR)
349 /*@noaccess cstring@*/
351 g_currentSpec = cstring_fromCharsNew (namePtr);
353 specFile = inputStream_create (cstring_copy (g_currentSpec),
354 LCL_EXTENSION, TRUE);
356 llassert (inputStream_isDefined (specFile));
358 g_currentSpecName = specFullName
359 (cstring_toCharsSafe (g_currentSpec),
364 if (context_getFlag (FLG_SHOWSCAN))
366 lldiagmsg (message ("< reading spec %s >", g_currentSpec));
369 /* Open source file */
371 if (!inputStream_open (specFile))
373 lldiagmsg (message ("Cannot open file: %s",
374 inputStream_fileName (specFile)));
375 inputStream_free (specFile);
379 scopeInfo dummy_scope = (scopeInfo) dmalloc (sizeof (*dummy_scope));
380 dummy_scope->kind = SPE_INVALID;
383 LCLScanReset (specFile);
386 ** Minor hacks to allow more than one LCL file to
387 ** be scanned, while keeping initializations
390 symtable_enterScope (g_symtab, dummy_scope);
391 resetImports (cstring_fromChars (g_currentSpecName));
392 context_enterLCLfile ();
393 (void) lclHadNewError ();
395 parser_status = (ylparse () != 0);
396 context_exitLCLfile ();
398 overallStatus = parser_status || lclHadNewError ();
400 if (context_getFlag (FLG_DOLCS))
404 outputLCSFile (path, "%FAILED Output from ",
409 outputLCSFile (path, "%PASSED Output from ",
414 (void) inputStream_close (specFile);
415 inputStream_free (specFile);
417 symtable_exitScope (g_symtab);
420 cstring_free (actualName);
421 } end_fileIdList_elements;
423 /* Can cleanup lsl stuff right away */
427 g_currentSpec = cstring_undefined;
428 g_currentSpecName = NULL;
432 static void handlePassThroughFlag (char *arg)
435 char *quotechar = strchr (curarg, '\"');
438 char *freearg = NULL;
440 while (quotechar != NULL)
442 if (*(quotechar - 1) == '\\')
444 char *tp = quotechar - 2;
455 curarg = quotechar + 1;
456 quotechar = strchr (curarg, '\"');
461 llassert (quotechar != NULL);
463 offset = (quotechar - arg) + 2;
467 arg = cstring_toCharsSafe
468 (message ("%s\"\'%s",
469 cstring_fromChars (arg),
470 cstring_fromChars (quotechar + 1)));
476 arg = cstring_toCharsSafe
477 (message ("%s\'\"%s",
478 cstring_fromChars (arg),
479 cstring_fromChars (quotechar + 1)));
484 curarg = arg + offset;
485 quotechar = strchr (curarg, '\"');
491 llerror (FLG_BADFLAG,
492 message ("Unclosed quote in flag: %s",
493 cstring_fromChars (arg)));
501 ** If the value is surrounded by single quotes ('), remove
502 ** them. This is an artifact of UNIX command line?
505 def = osd_fixDefine (cstring_fromChars (arg + 1));
506 DPRINTF (("Do define: %s", def));
508 DPRINTF (("After define"));
510 } else if (arg[0] == 'U') {
511 cppDoUndefine (cstring_fromChars (arg + 1));
520 void showHerald (void)
522 if (hasShownHerald || context_getFlag (FLG_QUIET)) return;
526 fprintf (g_msgstream, "%s\n\n", LCL_VERSION);
527 hasShownHerald = TRUE;
532 static void addFile (fileIdList files, /*@only@*/ cstring s)
534 if (fileTable_exists (context_fileTable (), s))
537 lldiagmsg (message ("File listed multiple times: %s", s));
542 fileIdList_add (files, fileTable_addFileOnly (context_fileTable (), s));
546 static void addXHFile (fileIdList files, /*@only@*/ cstring s)
548 if (fileTable_exists (context_fileTable (), s))
551 lldiagmsg (message ("File listed multiple times: %s", s));
556 fileIdList_add (files, fileTable_addXHFile (context_fileTable (), s));
562 ** Disable MSVC++ warning about return value. Methinks humbly lclint control
563 ** comments are a mite more legible.
567 # pragma warning (disable:4035)
570 int main (int argc, char *argv[])
572 /*@globals killed undef g_currentloc,
576 /*@modifies g_currentloc, fileSystem,
580 /*@globals killed undef g_currentloc,
581 killed undef initFile,
582 killed g_localSpecPath,
583 killed undef g_currentSpec,
584 killed undef g_currentSpecName,
588 /*@modifies g_currentloc, initFile,
589 g_localSpecPath, g_currentSpec, g_currentSpecName, fileSystem,
594 bool first_time = TRUE;
595 bool showhelp = FALSE;
598 inputStream sourceFile = inputStream_undefined;
600 fileIdList dercfiles;
601 cstringSList fl = cstringSList_undefined;
602 cstringSList passThroughArgs = cstringSList_undefined;
603 fileIdList cfiles, xfiles, lclfiles, mtfiles;
604 clock_t before, lcltime, libtime, pptime, cptime, rstime;
607 g_msgstream = stdout;
609 (void) signal (SIGINT, interrupt);
610 (void) signal (SIGSEGV, interrupt);
612 cfiles = fileIdList_create ();
613 xfiles = fileIdList_create ();
614 lclfiles = fileIdList_create ();
615 mtfiles = fileIdList_create ();
618 clabstract_initMod ();
619 typeIdSet_initMod ();
620 cppReader_initMod ();
623 g_currentloc = fileloc_createBuiltin ();
628 context_setInCommandLine ();
640 ** Add include directories from environment.
644 cstring incval = cstring_copy (osd_getEnvironmentVariable (INCLUDEPATH_VAR));
645 cstring oincval = incval;
647 if (cstring_isDefined (incval))
650 ** Each directory on the include path is a system include directory.
653 DPRINTF (("include: %s", incval));
654 context_setString (FLG_SYSTEMDIRS, cstring_copy (incval));
656 while (cstring_isDefined (incval))
659 char *nextsep = strchr (incval, PATH_SEPARATOR);
665 dir = cstring_copy (incval);
667 if (cstring_length (dir) == 0
668 || !isalpha ((int) cstring_firstChar (dir)))
671 ** win32 environment values can have special values,
677 cppAddIncludeDir (dir);
680 *nextsep = PATH_SEPARATOR;
681 incval = cstring_fromChars (nextsep + 1);
689 /*@noaccess cstring@*/
693 cstring_free (oincval);
697 ** check RCFILE for default flags
701 cstring home = osd_getHomeDir ();
704 bool defaultf = TRUE;
707 for (i = 1; i < argc; i++)
712 if (*thisarg == '-' || *thisarg == '+')
716 if (mstring_equal (thisarg, "nof"))
720 else if (mstring_equal (thisarg, "f"))
726 rcfile = fopen (fname, "r");
730 fileloc oloc = g_currentloc;
732 g_currentloc = fileloc_createRc (cstring_fromChars (fname));
733 loadrc (rcfile, &passThroughArgs);
734 fileloc_reallyFree (g_currentloc);
740 lldiagmsg (message ("Options file not found: %s",
741 cstring_fromChars (fname)));
746 (cstring_makeLiteral ("Flag f to select options file "
747 "requires an argument"));
751 ; /* wait to process later */
758 if (!cstring_isEmpty (home)) {
759 fname = cstring_toCharsSafe (message ("%s%h%s", home, CONNECTCHAR,
760 cstring_fromChars (RCFILE)));
761 mstring_markFree (fname);
767 if (!nof && defaultf)
769 if (!mstring_isEmpty (fname)) {
770 rcfile = fopen (fname, "r");
774 fileloc oloc = g_currentloc;
776 g_currentloc = fileloc_createRc (cstring_fromChars (fname));
777 loadrc (rcfile, &passThroughArgs);
778 fileloc_reallyFree (g_currentloc);
783 # if defined(MSDOS) || defined(OS2)
784 fname = cstring_toCharsSafe (message ("%s",
785 cstring_fromChars (RCFILE)));
787 fname = cstring_toCharsSafe (message ("./%s",
788 cstring_fromChars (RCFILE)));
791 rcfile = fopen (fname, "r");
795 fileloc oloc = g_currentloc;
797 g_currentloc = fileloc_createRc (cstring_fromChars (fname));
798 loadrc (rcfile, &passThroughArgs);
799 fileloc_reallyFree (g_currentloc);
809 for (i = 1; i < argc; i++)
825 if (*thisarg == '-' || *thisarg == '+')
827 thisarg++; /* skip '-' */
829 if (mstring_equal (thisarg, "modes"))
831 llmsg (describeModes ());
833 else if (mstring_equal (thisarg, "vars")
834 || mstring_equal (thisarg, "env"))
838 else if (mstring_equal (thisarg, "annotations"))
842 else if (mstring_equal (thisarg, "parseerrors"))
846 else if (mstring_equal (thisarg, "comments"))
850 else if (mstring_equal (thisarg, "prefixcodes"))
852 describePrefixCodes ();
854 else if (mstring_equal (thisarg, "references")
855 || mstring_equal (thisarg, "refs"))
859 else if (mstring_equal (thisarg, "mail"))
863 else if (mstring_equal (thisarg, "maintainer")
864 || mstring_equal (thisarg, "version"))
868 else if (mstring_equal (thisarg, "flags"))
872 char *next = argv[i + 1];
874 if (specialFlagsHelp (next))
880 flagkind k = identifyCategory (cstring_fromChars (next));
896 cstring s = describeFlag (cstring_fromChars (thisarg));
898 if (cstring_isDefined (s))
906 if (*thisarg == '-' || *thisarg == '+')
908 bool set = (*thisarg == '+');
911 thisarg++; /* skip '-' */
912 flagname = cstring_fromChars (thisarg);
914 DPRINTF (("Flag: %s", flagname));
915 opt = identifyFlag (flagname);
916 DPRINTF (("Flag: %s", flagcode_unparse (opt)));
918 if (flagcode_isSkip (opt))
920 DPRINTF (("Skipping!"));
922 else if (flagcode_isInvalid (opt))
924 DPRINTF (("Invalid: %s", flagname));
926 if (isMode (flagname))
928 context_setMode (flagname);
932 DPRINTF (("Error!"));
933 llgloberror (message ("Unrecognized option: %s",
934 cstring_fromChars (thisarg)));
939 context_userSetFlag (opt, set);
941 if (flagcode_hasArgument (opt))
947 else if (flagcode_isPassThrough (opt)) /* -D or -U */
949 passThroughArgs = cstringSList_add
950 (passThroughArgs, cstring_fromChars (thisarg));
952 else if (flagcode_hasValue (opt))
956 setValueFlag (opt, cstring_fromChars (argv[i]));
962 ("Flag %s must be followed by a number",
963 flagcode_unparse (opt)));
966 else if (opt == FLG_INCLUDEPATH || opt == FLG_SPECPATH)
968 cstring dir = cstring_suffix (cstring_fromChars (thisarg), 1); /* skip over I */
972 case FLG_INCLUDEPATH:
973 cppAddIncludeDir (dir);
974 /*@switchbreak@*/ break;
977 g_localSpecPath = cstring_toCharsSafe
979 cstring_fromChars (g_localSpecPath),
983 /*@switchbreak@*/ break;
987 else if (flagcode_hasString (opt)
988 || opt == FLG_INIT || opt == FLG_OPTF)
992 cstring arg = cstring_fromChars (argv[i]);
996 ; /* -f already processed */
998 else if (opt == FLG_INIT)
1001 initFile = inputStream_create
1003 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
1010 DPRINTF (("String flag: %s / %s",
1011 flagcode_unparse (opt), arg));
1012 if (opt == FLG_MTSFILE)
1015 ** arg identifies mts files
1018 addFile (mtfiles, message ("%s%s", arg, MTS_EXTENSION));
1019 addXHFile (xfiles, message ("%s%s", arg, XH_EXTENSION));
1023 setStringFlag (opt, arg);
1031 ("Flag %s must be followed by a string",
1032 flagcode_unparse (opt)));
1042 else /* its a filename */
1044 DPRINTF (("Adding filename: %s", thisarg));
1045 fl = cstringSList_add (fl, cstring_fromChars (thisarg));
1053 ** create lists of C and LCL files
1056 cstringSList_elements (fl, current)
1058 cstring ext = fileLib_getExtension (current);
1060 if (cstring_isUndefined (ext))
1062 /* no extension --- both C and LCL with default extensions */
1064 addFile (cfiles, message ("%s%s", current, C_EXTENSION));
1065 addFile (lclfiles, message ("%s%s", current, LCL_EXTENSION));
1067 else if (cstring_equal (ext, XH_EXTENSION))
1069 addXHFile (xfiles, cstring_copy (current));
1071 else if (cstring_equal (ext, LCL_EXTENSION))
1073 addFile (lclfiles, cstring_copy (current));
1075 else if (fileLib_isCExtension (ext))
1077 addFile (cfiles, cstring_copy (current));
1079 else if (cstring_equal (ext, MTS_EXTENSION))
1081 addFile (mtfiles, cstring_copy (current));
1086 (FLG_FILEEXTENSIONS,
1087 message ("Unrecognized file extension: %s (assuming %s is C source code)",
1091 addFile (cfiles, cstring_copy (current));
1093 } end_cstringSList_elements;
1095 showHerald (); /*@i723 move earlier? */
1103 fprintf (g_msgstream, "\n");
1105 fileIdList_free (cfiles);
1106 fileIdList_free (xfiles);
1107 fileIdList_free (lclfiles);
1116 inittime = clock ();
1118 context_resetErrors ();
1119 context_clearInCommandLine ();
1121 anylcl = !fileIdList_isEmpty (lclfiles);
1123 if (context_doMerge ())
1125 cstring m = context_getMerge ();
1127 if (context_getFlag (FLG_SHOWSCAN))
1129 fprintf (g_msgstream, "< loading %s ", cstring_toCharsSafe (m));
1134 if (context_getFlag (FLG_SHOWSCAN))
1136 fprintf (g_msgstream, " >\n");
1139 if (!usymtab_existsType (context_getBoolName ()))
1141 usymtab_initBool ();
1146 if (!context_getFlag (FLG_NOLIB) && loadStandardState ())
1155 /* setup bool type and constants */
1156 usymtab_initBool ();
1159 fileloc_free (g_currentloc);
1160 g_currentloc = fileloc_createBuiltin ();
1163 ** Read metastate files (must happen before loading libraries)
1166 fileIdList_elements (mtfiles, mtfile)
1168 context_setFileId (mtfile);
1170 if (context_getFlag (FLG_SHOWSCAN))
1172 lldiagmsg (message ("< processing %s >", rootFileName (mtfile)));
1175 mtreader_readFile (cstring_copy (fileName (mtfile)));
1176 } end_fileIdList_elements;
1183 llfatalerror (cstring_makeLiteral ("This version of LCLint does not handle LCL files."));
1185 lslProcess (lclfiles);
1189 usymtab_initGlobalMarker ();
1194 ** call the pre-preprocessor and /lib/cpp to generate appropriate
1199 context_setInCommandLine ();
1201 DPRINTF (("Pass through: %s", cstringSList_unparse (passThroughArgs)));
1203 cstringSList_elements (passThroughArgs, thisarg) {
1204 handlePassThroughFlag (cstring_toCharsSafe (thisarg));
1205 } end_cstringSList_elements;
1207 cstringSList_free (passThroughArgs);
1211 DPRINTF (("Initializing cpp reader!"));
1212 cppReader_initialize ();
1213 cppReader_saveDefinitions ();
1215 context_clearInCommandLine ();
1217 if (!context_getFlag (FLG_NOPP))
1223 if (context_getFlag (FLG_SHOWSCAN))
1225 fprintf (stderr, "< preprocessing");
1230 context_setPreprocessing ();
1231 dercfiles = preprocessFiles (xfiles, TRUE);
1232 tfiles = preprocessFiles (cfiles, FALSE);
1233 dercfiles = fileIdList_append (dercfiles, tfiles);
1234 fileIdList_free (tfiles);
1236 context_clearPreprocessing ();
1238 fileIdList_free (cfiles);
1240 if (context_getFlag (FLG_SHOWSCAN))
1242 fprintf (stderr, " >\n");
1250 dercfiles = fileIdList_append (cfiles, xfiles);
1255 ** now, check all the corresponding C files
1257 ** (for now these are just <file>.c, but after pre-processing
1258 ** will be <tmpprefix>.<file>.c)
1263 int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
1267 llbug (message ("Files unclosed: %d", nfiles));
1272 DPRINTF (("Initializing..."));
1274 exprNode_initMod ();
1276 DPRINTF (("Okay..."));
1278 fileIdList_elements (dercfiles, fid)
1280 sourceFile = inputStream_create (cstring_copy (fileName (fid)), C_EXTENSION, TRUE);
1281 context_setFileId (fid);
1283 /* Open source file */
1285 if (inputStream_isUndefined (sourceFile) || (!inputStream_open (sourceFile)))
1287 /* previously, this was ignored ?! */
1288 llbug (message ("Could not open temp file: %s", fileName (fid)));
1292 yyin = inputStream_getFile (sourceFile); /*< shared <- only */
1294 llassert (yyin != NULL);
1296 if (context_getFlag (FLG_SHOWSCAN))
1298 lldiagmsg (message ("< checking %s >", rootFileName (fid)));
1302 ** Every time, except the first time, through the loop,
1303 ** need to call yyrestart to clean up the parse buffer.
1308 (void) yyrestart (yyin);
1315 DPRINTF (("Entering..."));
1316 context_enterFile ();
1318 context_exitCFile ();
1320 (void) inputStream_close (sourceFile);
1322 } end_fileIdList_elements;
1326 /* process any leftover macros */
1328 context_processAllMacros ();
1330 /* check everything that was specified was defined */
1332 /* don't check if no c files were processed ?
1333 ** is this correct behaviour?
1336 if (context_getFlag (FLG_SHOWSCAN))
1338 lldiagmsg (cstring_makeLiteral ("< global checks >"));
1343 if (context_getLinesProcessed () > 0)
1345 usymtab_allDefined ();
1348 if (context_maybeSet (FLG_TOPUNUSED))
1350 uentry ue = usymtab_lookupSafe (cstring_makeLiteralTemp ("main"));
1352 if (uentry_isValid (ue))
1354 uentry_setUsed (ue, fileloc_observeBuiltin ());
1360 if (context_maybeSet (FLG_EXPORTLOCAL))
1362 usymtab_exportLocal ();
1366 if (context_maybeSet (FLG_EXPORTHEADER))
1368 usymtab_exportHeader ();
1371 if (context_getFlag (FLG_SHOWUSES))
1373 usymtab_displayAllUses ();
1376 context_checkSuppressCounts ();
1378 if (context_doDump ())
1380 cstring dump = context_getDump ();
1391 if (context_getFlag (FLG_SHOWSUMMARY))
1398 bool isQuiet = context_getFlag (FLG_QUIET);
1399 cstring specErrors = cstring_undefined;
1401 int nspecErrors = lclNumberErrors ();
1406 if (context_neednl ())
1407 fprintf (g_msgstream, "\n");
1410 if (nspecErrors > 0)
1412 if (nspecErrors == context_getLCLExpect ())
1415 message ("%d spec error%& found, as expected\n ",
1420 if (context_getLCLExpect () > 0)
1423 message ("%d spec error%& found, expected %d\n ",
1425 (int) context_getLCLExpect ());
1429 specErrors = message ("%d spec error%& found\n ",
1437 if (context_getLCLExpect () > 0)
1439 specErrors = message ("No spec errors found, expected %d\n ",
1440 (int) context_getLCLExpect ());
1446 if (context_anyErrors ())
1448 if (context_numErrors () == context_getExpect ())
1451 llmsg (message ("Finished LCLint checking --- "
1452 "%s%d code error%& found, as expected",
1453 specErrors, context_numErrors ()));
1458 if (context_getExpect () > 0)
1462 ("Finished LCLint checking --- "
1463 "%s%d code error%& found, expected %d",
1464 specErrors, context_numErrors (),
1465 (int) context_getExpect ()));
1475 llmsg (message ("Finished LCLint checking --- "
1476 "%s%d code error%& found",
1477 specErrors, context_numErrors ()));
1486 if (context_getExpect () > 0)
1490 ("Finished LCLint checking --- "
1491 "%sno code errors found, expected %d",
1493 (int) context_getExpect ()));
1500 if (context_getLinesProcessed () > 0)
1503 llmsg (message ("Finished LCLint checking --- %sno code errors found",
1510 llmsg (message ("Finished LCLint checking --- %sno code processed",
1517 cstring_free (specErrors);
1520 if (context_getFlag (FLG_STATS))
1522 clock_t ttime = clock () - before;
1523 int specLines = context_getSpecLinesProcessed ();
1529 fprintf (g_msgstream, "%d spec, ", specLines);
1532 # ifndef CLOCKS_PER_SEC
1533 fprintf (g_msgstream, "%d source lines in %ld time steps (steps/sec unknown)\n",
1534 context_getLinesProcessed (),
1537 fprintf (g_msgstream, "%d source lines in %.2f s.\n",
1538 context_getLinesProcessed (),
1539 (double) ttime / CLOCKS_PER_SEC);
1547 if (context_getFlag (FLG_TIMEDIST))
1549 clock_t ttime = clock () - before;
1553 char *msg = (char *) dmalloc (256 * sizeof (*msg));
1558 "Time distribution (percent): initialize %.2f / lcl %.2f / "
1559 "pre-process %.2f / c check %.2f / finalize %.2f \n",
1560 (100.0 * (double) (libtime - before) / ttime),
1561 (100.0 * (double) (lcltime - libtime) / ttime),
1562 (100.0 * (double) (pptime - lcltime) / ttime),
1563 (100.0 * (double) (cptime - pptime) / ttime),
1564 (100.0 * (double) (rstime - cptime) / ttime));
1569 "Time distribution (percent): initialize %.2f / "
1570 "pre-process %.2f / c check %.2f / finalize %.2f \n",
1571 (100.0 * (double) (libtime - before) / ttime),
1572 (100.0 * (double) (pptime - libtime) / ttime),
1573 (100.0 * (double) (cptime - pptime) / ttime),
1574 (100.0 * (double) (rstime - cptime) / ttime));
1577 llgenindentmsgnoloc (cstring_fromCharsO (msg));
1581 llexit (expsuccess ? LLSUCCESS : LLFAILURE);
1586 ** Reenable return value warnings.
1588 # pragma warning (default:4035)
1596 llmsg (message ("Source files are .c, .h and %s files. If there is no suffix,",
1598 llmsg (message (" LCLint will look for <file>.c and <file>%s.", LCL_EXTENSION));
1600 llmsglit ("Use lclint -help <topic or flag name> for more information");
1602 llmsglit ("Topics:");
1604 llmsglit (" annotations (describes source-code annotations)");
1605 llmsglit (" comments (describes control comments)");
1606 llmsglit (" flags (describes flag categories)");
1607 llmsglit (" flags <category> (describes flags in category)");
1608 llmsglit (" flags all (short description of all flags)");
1609 llmsglit (" flags alpha (list all flags alphabetically)");
1610 llmsglit (" flags full (full description of all flags)");
1611 llmsglit (" mail (information on mailing lists)");
1612 llmsglit (" modes (show mode settings)");
1613 llmsglit (" parseerrors (help on handling parser errors)");
1614 llmsglit (" prefixcodes (character codes in namespace prefixes)");
1615 llmsglit (" references (sources for more information)");
1616 llmsglit (" vars (environment variables)");
1617 llmsglit (" version (information on compilation, maintainer)");
1622 specialFlagsHelp (char *next)
1624 if ((next != NULL) && (*next != '-') && (*next != '+'))
1626 if (mstring_equal (next, "alpha"))
1631 else if (mstring_equal (next, "all"))
1633 printAllFlags (TRUE, FALSE);
1636 else if (mstring_equal (next, "categories")
1637 || mstring_equal (next, "cats"))
1639 listAllCategories ();
1642 else if (mstring_equal (next, "full"))
1644 printAllFlags (FALSE, TRUE);
1659 printParseErrors (void)
1661 llmsglit ("Parse Errors");
1662 llmsglit ("------------");
1664 llmsglit ("LCLint will sometimes encounter a parse error for code that "
1665 "can be parsed with a local compiler. There are a few likely "
1666 "causes for this and a number of techniques that can be used "
1667 "to work around the problem.");
1669 llmsglit ("Compiler extensions --- compilers sometimes extend the C "
1670 "language with compiler-specific keywords and syntax. While "
1671 "it is not advisible to use these, oftentimes one has no choice "
1672 "when the system header files use compiler extensions. ");
1674 llmsglit ("LCLint supports some of the GNU (gcc) compiler extensions, "
1675 "if the +gnuextensions flag is set. You may be able to workaround "
1676 "other compiler extensions by using a pre-processor define. "
1677 "Alternately, you can surround the unparseable code with");
1679 llmsglit (" # ifndef __LCLINT__");
1681 llmsglit (" # endif");
1683 /* evans 2000-12-21 fixed typo reported by Jeroen Ruigrok/Asmodai */
1684 llmsglit ("Missing type definitions --- an undefined type name will usually "
1685 "lead to a parse error. This often occurs when a standard header "
1686 "file defines some type that is not part of the standard library. ");
1687 llmsglit ("By default, LCLint does not process the local files corresponding "
1688 "to standard library headers, but uses a library specification "
1689 "instead so dependencies on local system headers can be detected. "
1690 "If another system header file that does not correspond to a "
1691 "standard library header uses one of these superfluous types, "
1692 "a parse error will result.");
1694 llmsglit ("If the parse error is inside a posix standard header file, the "
1695 "first thing to try is +posixlib. This make LCLint use "
1696 "the posix library specification instead of reading the posix "
1699 llmsglit ("Otherwise, you may need to either manually define the problematic "
1700 "type (e.g., add -Dmlink_t=int to your .lclintrc file) or force "
1701 "lclint to process the header file that defines it. This is done "
1702 "by setting -skipansiheaders or -skipposixheaders before "
1703 "the file that defines the type is #include'd.");
1704 llmsglit ("(See lclint -help "
1705 "skipansiheaders and lclint -help skipposixheaders for a list of "
1706 "standard headers.) For example, if <sys/local.h> uses a type "
1707 "defined by posix header <sys/types.h> but not defined by the "
1708 "posix library, we might do: ");
1710 llmsglit (" /*@-skipposixheaders@*/");
1711 llmsglit (" # include <sys/types.h>");
1712 llmsglit (" /*@=skipposixheaders@*/");
1713 llmsglit (" # include <sys/local.h>");
1715 llmsglit ("to force LCLint to process <sys/types.h>.");
1717 llmsglit ("At last resort, +trytorecover can be used to make LCLint attempt "
1718 "to continue after a parse error. This is usually not successful "
1719 "and the author does not consider assertion failures when +trytorecover "
1720 "is used to be bugs.");
1724 printAnnotations (void)
1726 llmsglit ("Annotations");
1727 llmsglit ("-----------");
1729 llmsglit ("Annotations are semantic comments that document certain "
1730 "assumptions about functions, variables, parameters, and types. ");
1732 llmsglit ("They may be used to indicate where the representation of a "
1733 "user-defined type is hidden, to limit where a global variable may "
1734 "be used or modified, to constrain what a function implementation "
1735 "may do to its parameters, and to express checked assumptions about "
1736 "variables, types, structure fields, function parameters, and "
1737 "function results.");
1739 llmsglit ("Annotations are introduced by \"/*@\". The role of the @ may be "
1740 "played by any printable character, selected using -commentchar <char>.");
1742 llmsglit ("Consult the User's Guide for descriptions of checking associated with each annotation.");
1744 llmsglit ("Globals: (in function declarations)");
1745 llmsglit (" /*@globals <globitem>,+ @*/");
1746 llmsglit (" globitem is an identifier, internalState or fileSystem");
1748 llmsglit ("Modifies: (in function declarations)");
1749 llmsglit (" /*@modifies <moditem>,+ @*/");
1750 llmsglit (" moditem is an lvalue");
1751 llmsglit (" /*@modifies nothing @*/");
1752 llmsglit (" /*@*/ (Abbreviation for no globals and modifies nothing.)");
1754 llmsglit ("Iterators:");
1755 llmsglit (" /*@iter <identifier> (<parameter-type-list>) @*/ - declare an iterator");
1757 llmsglit ("Constants:");
1758 llmsglit (" /*@constant <declaration> @*/ - declares a constant");
1760 llmsglit ("Alternate Types:");
1761 llmsglit (" /*@alt <basic-type>,+ @*/");
1762 llmsglit (" (e.g., int /*@alt char@*/ is a type matching either int or char)");
1764 llmsglit ("Declarator Annotations");
1766 llmsglit ("Type Definitions:");
1767 llmsglit (" /*@abstract@*/ - representation is hidden from clients");
1768 llmsglit (" /*@concrete@*/ - representation is visible to clients");
1769 llmsglit (" /*@immutable@*/ - instances of the type cannot change value");
1770 llmsglit (" /*@mutable@*/ - instances of the type can change value");
1771 llmsglit (" /*@refcounted@*/ - reference counted type");
1773 llmsglit ("Global Variables:");
1774 llmsglit (" /*@unchecked@*/ - weakest checking for global use");
1775 llmsglit (" /*@checkmod@*/ - check modification by not use of global");
1776 llmsglit (" /*@checked@*/ - check use and modification of global");
1777 llmsglit (" /*@checkedstrict@*/ - check use of global strictly");
1779 llmsglit ("Memory Management:");
1780 llmsglit (" /*@dependent@*/ - a reference to externally-owned storage");
1781 llmsglit (" /*@keep@*/ - a parameter that is kept by the called function");
1782 llmsglit (" /*@killref@*/ - a refcounted parameter, killed by the call");
1783 llmsglit (" /*@only@*/ - an unshared reference");
1784 llmsglit (" /*@owned@*/ - owner of storage that may be shared by /*@dependent@*/ references");
1785 llmsglit (" /*@shared@*/ - shared reference that is never deallocated");
1786 llmsglit (" /*@temp@*/ - temporary parameter");
1788 llmsglit ("Aliasing:");
1789 llmsglit (" /*@unique@*/ - may not be aliased by any other visible reference");
1790 llmsglit (" /*@returned@*/ - may be aliased by the return value");
1792 llmsglit ("Exposure:");
1793 llmsglit (" /*@observer@*/ - reference that cannot be modified");
1794 llmsglit (" /*@exposed@*/ - exposed reference to storage in another object");
1796 llmsglit ("Definition State:");
1797 llmsglit (" /*@out@*/ - storage reachable from reference need not be defined");
1798 llmsglit (" /*@in@*/ - all storage reachable from reference must be defined");
1799 llmsglit (" /*@partial@*/ - partially defined, may have undefined fields");
1800 llmsglit (" /*@reldef@*/ - relax definition checking");
1802 llmsglit ("Global State: (for globals lists, no /*@, since list is already in /*@\'s)");
1803 llmsglit (" undef - variable is undefined before the call");
1804 llmsglit (" killed - variable is undefined after the call");
1806 llmsglit ("Null State:");
1807 llmsglit (" /*@null@*/ - possibly null pointer");
1808 llmsglit (" /*@notnull@*/ - non-null pointer");
1809 llmsglit (" /*@relnull@*/ - relax null checking");
1811 llmsglit ("Null Predicates:");
1812 llmsglit (" /*@truenull@*/ - if result is TRUE, first parameter is NULL");
1813 llmsglit (" /*@falsenull@*/ - if result is TRUE, first parameter is not NULL");
1815 llmsglit ("Execution:");
1816 llmsglit (" /*@exits@*/ - function never returns");
1817 llmsglit (" /*@mayexit@*/ - function may or may not return");
1818 llmsglit (" /*@trueexit@*/ - function does not return if first parameter is TRUE");
1819 llmsglit (" /*@falseexit@*/ - function does not return if first parameter if FALSE");
1820 llmsglit (" /*@neverexit@*/ - function always returns");
1822 llmsglit ("Side-Effects:");
1823 llmsglit (" /*@sef@*/ - corresponding actual parameter has no side effects");
1825 llmsglit ("Declaration:");
1826 llmsglit (" /*@unused@*/ - need not be used (no unused errors reported)");
1827 llmsglit (" /*@external@*/ - defined externally (no undefined error reported)");
1830 llmsglit (" /*@fallthrough@*/ - fall-through case");
1832 llmsglit ("Break:");
1833 llmsglit (" /*@innerbreak@*/ - break is breaking an inner loop or switch");
1834 llmsglit (" /*@loopbreak@*/ - break is breaking a loop");
1835 llmsglit (" /*@switchbreak@*/ - break is breaking a switch");
1836 llmsglit (" /*@innercontinue@*/ - continue is continuing an inner loop");
1838 llmsglit ("Unreachable Code:");
1839 llmsglit (" /*@notreached@*/ - statement may be unreachable.");
1841 llmsglit ("Special Functions:");
1842 llmsglit (" /*@printflike@*/ - check variable arguments like printf");
1843 llmsglit (" /*@scanflike@*/ - check variable arguments like scanf");
1847 printComments (void)
1849 llmsglit ("Control Comments");
1850 llmsglit ("----------------");
1852 llmsglit ("Setting Flags");
1854 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.");
1856 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,");
1857 llmsglit (" /*@+boolint -modifies =showfunc@*/");
1858 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).");
1860 llmsglit ("Error Suppression");
1862 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.");
1864 llmsglit ("/*@ignore@*/ ... /*@end@*/");
1866 (cstring_makeLiteral
1867 ("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."));
1868 llmsglit ("/*@i@*/");
1870 (cstring_makeLiteral
1871 ("No errors will be reported from an /*@i@*/ comment to the end of the line."));
1872 llmsglit ("/*@i<n>@*/");
1874 (cstring_makeLiteral
1875 ("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."));
1876 llmsglit ("/*@t@*/, /*@t<n>@*/");
1878 (cstring_makeLiteral
1879 ("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."));
1881 llmsglit ("Type Access");
1883 llmsglit ("/*@access <type>@*/");
1884 llmsglit (" Allows the following code to access the representation of <type>");
1885 llmsglit ("/*@noaccess <type>@*/");
1886 llmsglit (" Hides the representation of <type>");
1888 llmsglit ("Macro Expansion");
1890 llmsglit ("/*@notfunction@*/");
1892 (cstring_makeLiteral
1893 ("Indicates that the next macro definition is not intended to be a "
1894 "function, and should be expanded in line instead of checked as a "
1895 "macro function definition."));
1902 llmsglit ("Flag Categories");
1903 llmsglit ("---------------");
1904 listAllCategories ();
1905 llmsglit ("\nTo see the flags in a flag category, do\n lclint -help flags <category>");
1906 llmsglit ("To see a list of all flags in alphabetical order, do\n lclint -help flags alpha");
1907 llmsglit ("To see a full description of all flags, do\n lclint -help flags full");
1911 printMaintainer (void)
1913 llmsg (message ("Maintainer: %s", cstring_makeLiteralTemp (LCLINT_MAINTAINER)));
1914 llmsglit (LCL_COMPILE);
1920 llmsglit ("Mailing Lists");
1921 llmsglit ("-------------");
1923 llmsglit ("There are two mailing lists associated with LCLint: ");
1925 llmsglit (" lclint-announce@virginia.edu");
1927 llmsglit (" Reserved for announcements of new releases and bug fixes.");
1928 llmsglit (" To subscribe, send a message to majordomo@virginia.edu with body: ");
1929 llmsglit (" subscribe lclint-announce");
1931 llmsglit (" lclint-interest@virginia.edu");
1933 llmsglit (" Informal discussions on the use and development of lclint.");
1934 llmsglit (" To subscribe, send a message to majordomo@virginia.edu with body: ");
1935 llmsglit (" subscribe lclint-interest");
1939 printReferences (void)
1941 llmsglit ("References");
1942 llmsglit ("----------");
1944 llmsglit ("The LCLint web site is http://lclint.cs.virginia.edu");
1946 llmsglit ("Technical papers relating to LCLint include:");
1948 llmsglit (" David Evans. \"Static Detection of Dynamic Memory Errors\".");
1949 llmsglit (" SIGPLAN Conference on Programming Language Design and ");
1950 llmsglit (" Implementation (PLDI '96), Philadelphia, PA, May 1996.");
1952 llmsglit (" David Evans, John Guttag, Jim Horning and Yang Meng Tan. ");
1953 llmsglit (" \"LCLint: A Tool for Using Specifications to Check Code\".");
1954 llmsglit (" SIGSOFT Symposium on the Foundations of Software Engineering,");
1955 llmsglit (" December 1994.");
1957 llmsglit ("A general book on Larch is:");
1959 llmsglit (" Guttag, John V., Horning, James J., (with Garland, S. J., Jones, ");
1960 llmsglit (" K. D., Modet, A., and Wing, J. M.), \"Larch: Languages and Tools ");
1961 llmsglit (" for Formal Specification\", Springer-Verlag, 1993.");
1965 describePrefixCodes (void)
1967 llmsglit ("Prefix Codes");
1968 llmsglit ("------------");
1970 llmsglit ("These characters have special meaning in name prefixes:");
1972 llmsg (message (" %h Any uppercase letter [A-Z]", PFX_UPPERCASE));
1973 llmsg (message (" %h Any lowercase letter [a-z]", PFX_LOWERCASE));
1974 llmsg (message (" %h Any character (valid in a C identifier)", PFX_ANY));
1975 llmsg (message (" %h Any digit [0-9]", PFX_DIGIT));
1976 llmsg (message (" %h Any non-uppercase letter [a-z0-9_]", PFX_NOTUPPER));
1977 llmsg (message (" %h Any non-lowercase letter [A-Z0-9_]", PFX_NOTLOWER));
1978 llmsg (message (" %h Any letter [A-Za-z]", PFX_ANYLETTER));
1979 llmsg (message (" %h Any letter or digit [A-Za-z0-9]", PFX_ANYLETTERDIGIT));
1980 llmsglit (" * Zero or more repetitions of the previous character class until the end of the name");
1989 eval = context_getLarchPath ();
1990 def = osd_getEnvironmentVariable (LARCH_PATH);
1992 if (cstring_isDefined (def) ||
1993 !cstring_equal (eval, cstring_fromChars (DEFAULT_LARCHPATH)))
1995 llmsg (message ("LARCH_PATH = %s", eval));
1999 llmsg (message ("LARCH_PATH = <not set> (default = %s)",
2000 cstring_fromChars (DEFAULT_LARCHPATH)));
2003 llmsglit (" --- path used to find larch initialization files and LSL traits");
2005 eval = context_getLCLImportDir ();
2006 def = osd_getEnvironmentVariable (cstring_makeLiteralTemp (LCLIMPORTDIR));
2008 if (cstring_isDefined (def) ||
2009 !cstring_equal (eval, cstring_fromChars (DEFAULT_LCLIMPORTDIR)))
2011 llmsg (message ("%q = %s", cstring_makeLiteral (LCLIMPORTDIR), eval));
2015 llmsg (message ("%s = <not set, default: %s>", cstring_makeLiteralTemp (LCLIMPORTDIR),
2016 cstring_makeLiteralTemp (DEFAULT_LCLIMPORTDIR)));
2019 llmsglit (" --- directory containing lcl standard library files "
2020 "(import with < ... >)");;
2023 ("include path = %q (set by environment variable %s and -I flags)",
2024 cppReader_getIncludePath (), INCLUDEPATH_VAR));
2026 llmsglit (" --- path used to find #include'd files");
2029 ("systemdirs = %s (set by -systemdirs or envirnoment variable %s)", /*@i413223@*/
2030 context_getString (FLG_SYSTEMDIRS),
2033 llmsglit (" --- if file is found on this path, it is treated as a system file for error reporting");
2042 fprintf (stderr, "*** Interrupt\n");
2043 llexit (LLINTERRUPT);
2048 /* Cheat when there are parse errors */
2051 fprintf (stderr, "*** Segmentation Violation\n");
2053 /* Don't catch it if fileloc_unparse causes a signal */
2054 (void) signal (SIGSEGV, NULL);
2056 loc = fileloc_unparse (g_currentloc);
2058 fprintf (stderr, "*** Location (not trusted): %s\n",
2059 cstring_toCharsSafe (loc));
2062 fprintf (stderr, "*** Please report bug to %s\n", LCLINT_MAINTAINER);
2066 fprintf (stderr, "*** Signal: %d\n", i);
2068 fprintf (stderr, "*** Location (not trusted): %s\n",
2069 cstring_toCharsSafe (fileloc_unparse (g_currentloc)));
2072 fprintf (stderr, "*** Please report bug to %s ***\n", LCLINT_MAINTAINER);
2080 static bool doneCleanup = FALSE;
2082 /* make sure this is only called once! */
2084 if (doneCleanup) return;
2088 if (context_getFlag (FLG_KEEP))
2090 check (fputs ("Temporary files kept:\n", stderr) != EOF);
2091 fileTable_printTemps (context_fileTable ());
2096 int nfiles = /*@-unrecog@*/ _fcloseall (); /*@=unrecog@*/
2100 llbug (message ("Files unclosed: %d", nfiles));
2103 fileTable_cleanup (context_fileTable ());
2110 ** cleans up temp files (if necessary)
2117 DPRINTF (("llexit: %d", status));
2120 if (status == LLFAILURE)
2128 if (status != LLFAILURE)
2130 context_destroyMod ();
2131 exprNode_destroyMod ();
2134 uentry_destroyMod ();
2135 typeIdSet_destroyMod ();
2138 dmalloc_shutdown ();
2142 exit ((status == LLSUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE);
2146 loadrc (/*@open@*/ FILE *rcfile, cstringSList *passThroughArgs)
2147 /*@ensures closed rcfile@*/
2149 char *s = mstring_create (MAX_LINE_LENGTH);
2152 DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2156 while (reader_readLine (rcfile, s, MAX_LINE_LENGTH) != NULL)
2163 DPRINTF (("Line: %s", s));
2164 DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2166 while (*s == ' ' || *s == '\t')
2174 bool escaped = FALSE;
2175 bool quoted = FALSE;
2178 DPRINTF (("Process: %s", s));
2179 DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2180 /* comment characters */
2181 if (c == '#' || c == ';' || c == '\n')
2187 if (c == '-' || c == '+')
2194 llerror (FLG_SYNTAX,
2195 message ("Bad flag syntax (+ or - expected, "
2196 "+ is assumed): %s",
2197 cstring_fromChars (s)));
2207 while ((c = *s) != '\0')
2208 { /* remember to handle spaces and quotes in -D and -U ... */
2234 if (c == ' ' || c == '\t' || c == '\n')
2236 /*@innerbreak@*/ break;
2244 DPRINTF (("Nulling: %c", *s));
2247 if (mstring_isEmpty (thisflag))
2249 llfatalerror (message ("Missing flag: %s",
2250 cstring_fromChars (os)));
2253 DPRINTF (("Flag: %s", thisflag));
2255 opt = identifyFlag (cstring_fromChars (thisflag));
2257 if (flagcode_isSkip (opt))
2261 else if (flagcode_isInvalid (opt))
2263 DPRINTF (("Invalid: %s", thisflag));
2265 if (isMode (cstring_fromChars (thisflag)))
2267 context_setMode (cstring_fromChars (thisflag));
2271 llerror (FLG_BADFLAG,
2272 message ("Unrecognized option: %s",
2273 cstring_fromChars (thisflag)));
2278 context_userSetFlag (opt, set);
2280 if (flagcode_hasArgument (opt))
2282 if (opt == FLG_HELP)
2285 llerror (FLG_BADFLAG,
2286 message ("Cannot use help in rc files"));
2288 else if (flagcode_isPassThrough (opt)) /* -D or -U */
2290 cstring arg = cstring_fromCharsNew (thisflag);
2291 cstring_markOwned (arg);
2292 *passThroughArgs = cstringSList_add (*passThroughArgs, arg);
2293 DPRINTF (("Pass through: %s",
2294 cstringSList_unparse (*passThroughArgs)));
2296 else if (opt == FLG_INCLUDEPATH
2297 || opt == FLG_SPECPATH)
2299 cstring dir = cstring_suffix (cstring_fromChars (thisflag), 1); /* skip over I/S */
2303 case FLG_INCLUDEPATH:
2304 cppAddIncludeDir (dir);
2305 /*@switchbreak@*/ break;
2308 g_localSpecPath = cstring_toCharsSafe
2309 (message ("%s:%s", cstring_fromChars (g_localSpecPath), dir));
2311 /*@switchbreak@*/ break;
2315 else if (flagcode_hasString (opt)
2316 || flagcode_hasValue (opt)
2317 || opt == FLG_INIT || opt == FLG_OPTF)
2319 cstring extra = cstring_undefined;
2324 rest = mstring_copy (s);
2325 DPRINTF (("Here: rest = %s", rest));
2329 while ((rchar = *rest) != '\0'
2330 && (isspace ((int) rchar)))
2336 DPRINTF (("Yo: %s", rest));
2338 while ((rchar = *rest) != '\0'
2339 && !isspace ((int) rchar))
2341 extra = cstring_appendChar (extra, rchar);
2346 DPRINTF (("Yo: %s", extra));
2349 if (cstring_isUndefined (extra))
2355 ("Flag %s must be followed by an argument",
2356 flagcode_unparse (opt)));
2362 DPRINTF (("Here we are: %s", extra));
2364 if (flagcode_hasValue (opt))
2366 DPRINTF (("Set value flag: %s", extra));
2367 setValueFlag (opt, extra);
2368 cstring_free (extra);
2370 else if (opt == FLG_OPTF)
2372 FILE *innerf = fopen (cstring_toCharsSafe (extra), "r");
2373 cstring_markOwned (extra);
2377 fileloc fc = g_currentloc;
2378 g_currentloc = fileloc_createRc (extra);
2379 loadrc (innerf, passThroughArgs);
2380 fileloc_reallyFree (g_currentloc);
2388 message ("Options file not found: %s",
2392 else if (opt == FLG_INIT)
2395 llassert (inputStream_isUndefined (initFile));
2397 initFile = inputStream_create
2399 cstring_makeLiteralTemp (LCLINIT_SUFFIX),
2402 cstring_free (extra);
2405 else if (flagcode_hasString (opt))
2407 if (cstring_firstChar (extra) == '"')
2409 if (cstring_lastChar (extra) == '"')
2411 char *extras = cstring_toCharsSafe (extra);
2413 llassert (extras[strlen(extras) - 1] == '"');
2414 extras[strlen(extras) - 1] = '\0';
2415 extra = cstring_fromChars (extras + 1);
2416 DPRINTF (("Remove quites: %s", extra));
2422 message ("Unmatched \" in option string: %s",
2427 setStringFlag (opt, extra);
2431 cstring_free (extra);
2444 DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2445 while ((c == ' ') || (c == '\t'))
2451 DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2455 DPRINTF (("Pass through: %s", cstringSList_unparse (*passThroughArgs)));
2457 check (fclose (rcfile) == 0);
2460 static fileIdList preprocessFiles (fileIdList fl, bool xhfiles)
2461 /*@modifies fileSystem@*/
2463 bool msg = (context_getFlag (FLG_SHOWSCAN) && fileIdList_size (fl) > 10);
2464 int skip = (fileIdList_size (fl) / 5);
2465 int filesprocessed = 0;
2466 fileIdList dfiles = fileIdList_create ();
2468 fileloc_free (g_currentloc);
2469 g_currentloc = fileloc_createBuiltin ();
2471 fileIdList_elements (fl, fid)
2473 cstring ppfname = fileName (fid);
2479 if (osd_findOnLarchPath (ppfname, &fpath) == OSD_FILEFOUND)
2481 if (cstring_equal (ppfname, fpath))
2487 DPRINTF (("xh file: %s", fpath));
2489 fileTable_setFilePath (context_fileTable (), fid, fpath);
2494 lldiagmsg (message ("Cannot find .xh file on LARCH_PATH: %s", ppfname));
2495 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
2496 ppfname = cstring_undefined;
2501 if (!(osd_fileIsReadable (ppfname)))
2503 lldiagmsg (message ("Cannot open file: %s", ppfname));
2504 ppfname = cstring_undefined;
2508 if (cstring_isDefined (ppfname))
2510 fileId dfile = fileTable_addCTempFile (context_fileTable (), fid);
2512 llassert (cstring_isNonEmpty (ppfname));
2516 if ((filesprocessed % skip) == 0)
2518 if (filesprocessed == 0) {
2519 fprintf (stderr, " ");
2522 fprintf (stderr, ".");
2525 (void) fflush (stderr);
2530 if (cppProcess (ppfname, fileName (dfile)) != 0)
2532 llfatalerror (message ("Preprocessing error for file: %s",
2533 rootFileName (fid)));
2536 fileIdList_add (dfiles, dfile);
2538 } end_fileIdList_elements;
2543 /* This should be in an lclUtils.c file... */
2545 char *specFullName (char *specfile, /*@out@*/ char **inpath)
2547 /* extract the path and the specname associated with the given file */
2548 char *specname = (char *) dmalloc (sizeof (*specname)
2549 * (strlen (specfile) + 9));
2550 char *ospecname = specname;
2551 char *path = (char *) dmalloc (sizeof (*path) * (strlen (specfile)));
2555 /* initialized path to empty string or may have accidental garbage */
2558 /*@-mayaliasunique@*/
2559 strcpy (specname, specfile);
2560 /*@=mayaliasunique@*/
2562 /* trim off pathnames in specfile */
2563 size = strlen (specname);
2565 for (i = size_toInt (size) - 1; i >= 0; i--)
2567 if (specname[i] == CONNECTCHAR)
2569 /* strcpy (specname, (char *)specname+i+1); */
2570 for (j = 0; j <= i; j++) /* include '/' */
2572 path[j] = specname[j];
2582 ** also remove .lcl file extension, assume it's the last extension
2586 size = strlen (specname);
2588 for (i = size_toInt (size) - 1; i >= 0; i--)
2590 if (specname[i] == '.')
2600 ** If specname no longer points to the original char,
2601 ** we need to allocate a new pointer and copy the string.
2604 if (specname != ospecname) {
2605 char *rspecname = (char *) dmalloc (sizeof (*rspecname) * (strlen (specname) + 1));
2606 strcpy (rspecname, specname); /* evs 2000-05-16: Bug: was ospecname! */