2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 ** routines for loading and creating library files
29 ** this is a brute-force implementation, a more efficient
30 ** representation should be designed.
34 # include "lclintMacros.nf"
51 /*@-incondefs@*/ /*@-redecl@*/
52 extern /*@dependent@*/ FILE *yyin;
53 /*@=incondefs@*/ /*@=redecl@*/
55 /*@constant int NUMLIBS; @*/
58 /*@constant int NUMPOSIXLIBS; @*/
59 # define NUMPOSIXLIBS 12
61 static ob_mstring posixlibs[NUMPOSIXLIBS] =
77 static ob_mstring stdlibs[NUMLIBS] =
98 static bool loadStateFile (FILE * p_f, cstring p_name);
101 lcllib_isSkipHeader (cstring sname)
104 bool posixlib = FALSE;
106 char *name = cstring_toCharsSafe (sname);
109 llassert (cstring_isDefined (sname));
110 name = removeExtension (name, ".h");
112 libname = strrchr (name, CONNECTCHAR);
126 if (mstring_equal (libname, "varargs"))
128 fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
132 message ("Include file <%s> is inconsistent with "
133 "ANSI library (should use <stdarg.h>)",
134 cstring_fromChars (libname)),
142 if (context_getFlag (FLG_SKIPANSIHEADERS)
143 && context_usingAnsiLibrary ())
146 for (i = 0; i < NUMLIBS; i++)
148 if (mstring_equal (libname, stdlibs[i]))
156 for (i = 0; i < NUMPOSIXLIBS; i++)
158 if (strchr (posixlibs[i], CONNECTCHAR) != NULL)
162 if ((ptr = strstr (name, posixlibs[i])) != NULL)
164 if (ptr[strlen (posixlibs[i])] == '\0')
178 if (mstring_equal (libname, posixlibs[i]))
190 if (context_usingPosixLibrary ())
192 if (context_getFlag (FLG_SKIPPOSIXHEADERS))
200 fileloc tmp = fileloc_makePreprocPrevious (g_currentloc);
204 message ("Include file <%s> matches the name of a "
205 "POSIX library, but the POSIX library is "
206 "not being used. Consider using +posixlib "
207 "or +posixstrictlib to select the POSIX "
208 "library, or -warnposix "
209 "to suppress this message.",
210 cstring_fromChars (matchname)),
221 static void printDot (void)
223 if (context_getFlag (FLG_SHOWSCAN))
225 (void) fflush (g_msgstream);
226 fprintf (stderr, ".");
227 (void) fflush (stderr);
232 dumpState (cstring cfname)
235 char *fname = cstring_toCharsSafe (cfname);
237 fname = addExtension (fname, DUMP_SUFFIX);
239 f = fopen (fname, "w");
241 if (context_getFlag (FLG_SHOWSCAN))
243 fprintf (stderr, "< Dumping to %s ", fname);
248 llgloberror (message ("Cannot open dump file for writing: %s", cfname));
253 ** sequence is convulted --- must call usymtab_prepareDump before
254 ** dumping ctype table to convert type uid's
259 usymtab_prepareDump ();
262 ** Be careful, these lines must match loadStateFile checking.
265 fprintf (f, ";;LCLint Dump: %s\n", fname);
266 fprintf (f, ";;%s\n", LCL_VERSION);
267 fprintf (f, ";;lib:%d\n", (int) context_getLibrary ());
268 fprintf (f, ";;ctTable\n");
274 fprintf (f, ";;tistable\n");
275 typeIdSet_dumpTable (f);
278 fprintf (f, ";;symTable\n");
282 fprintf (f, ";; Modules access\n");
283 context_dumpModuleAccess (f);
284 fprintf (f, ";;End\n");
285 check (fclose (f) == 0);
288 if (context_getFlag (FLG_SHOWSCAN))
290 fprintf (g_msgstream, " >\n");
302 char *libname = addExtension (context_selectedLibrary (), DUMP_SUFFIX);
305 if (osd_findOnLarchPath (libname, &fpath) != OSD_FILEFOUND)
307 lldiagmsg (message ("Cannot find %sstandard library: %s",
308 cstring_makeLiteralTemp
309 (context_getFlag (FLG_STRICTLIB) ? "strict "
310 : (context_getFlag (FLG_UNIXLIB) ? "unix " : "")),
311 cstring_makeLiteralTemp (libname)));
312 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
317 stdlib = fopen (fpath, "r");
321 lldiagmsg (message ("Cannot read standard library: %s",
322 cstring_fromChars (fpath)));
323 lldiagmsg (cstring_makeLiteral (" Check LARCH_PATH environment variable."));
329 if (context_getFlag (FLG_WHICHLIB))
331 char *t = mstring_create (MAX_NAME_LENGTH);
334 if (fgets (t, MAX_NAME_LENGTH, stdlib) == NULL)
336 llfatalerror (cstring_makeLiteral ("Standard library format invalid"));
339 if (fgets (t, MAX_NAME_LENGTH, stdlib) != NULL)
341 if (*t == ';' && *(t + 1) == ';')
349 lldiagmsg (message ("Standard library: %s <cannot read creation information>",
350 cstring_fromChars (fpath)));
356 tt = strrchr (t, '\n');
360 lldiagmsg (message ("Standard library: %s", cstring_fromChars (fpath)));
361 lldiagmsg (message (" (created using %s)", cstring_fromChars (t)));
366 check (fclose (stdlib) == 0);
367 stdlib = fopen (fpath, "r");
370 llassert (stdlib != NULL);
372 fileloc_reallyFree (g_currentloc);
373 g_currentloc = fileloc_createLib (cstring_makeLiteralTemp (libname));
375 if (context_getDebug (FLG_SHOWSCAN))
377 context_hideShowscan ();
378 result = loadStateFile (stdlib, cstring_fromChars (fpath));
379 context_unhideShowscan ();
383 result = loadStateFile (stdlib, cstring_fromChars (fpath));
386 check (fclose (stdlib) == 0);
394 /*@constant int BUFLEN;@*/
398 loadStateFile (FILE *f, cstring name)
403 ** Check version. Should be >= LCL_MIN_VERSION
406 if ((fgets (buf, BUFLEN, f) == NULL)
407 || !mstring_equalPrefix (buf, ";;LCLint Dump:"))
409 loadllmsg (message ("Load library %s is not in LCLint library format. Attempting "
410 "to continue without library.", name));
414 if (fgets (buf, BUFLEN, f) != NULL)
416 if (!mstring_equalPrefix (buf, ";;"))
418 loadllmsg (message ("Load library %s is not in LCLint library format. Attempting "
419 "to continue without library.", name));
422 else if (mstring_equalPrefix (buf, ";;ctTable"))
424 loadllmsg (message ("Load library %s is in obsolete LCLint library format. Attempting "
425 "to continue anyway, but results may be incorrect. Rebuild "
426 "the library with this version of lclint.",
433 if (sscanf (buf, ";;LCLint %f", &version) != 1)
435 loadllmsg (message ("Load library %s is not in LCLint library format (missing version "
436 "number). Attempting "
437 "to continue without library.", name));
442 if ((LCL_MIN_VERSION - version) >= FLT_EPSILON)
445 char *nl = strchr (buf, '\n');
447 /*drl7x this is evans is code I think
448 I'll need is find out if code is safe or if I
449 broke it somehow... */
450 /*@i223*/ *nl = '\0';
452 vname = cstring_fromChars (buf + 9);
454 loadllmsg (message ("Load library %s is in obsolete LCLint library "
455 "format (version %s). Attempting "
456 "to continue anyway, but results may be incorrect. Rebuild "
457 "the library with this version of lclint.",
462 if ((fgets (buf, BUFLEN, f) == NULL))
464 loadllmsg (message ("Load library %s is not in LCLint library "
465 "format (missing library code). Attempting "
466 "to continue without library.", name));
473 if (sscanf (buf, ";;lib:%d", &lib) != 1)
475 loadllmsg (message ("Load library %s is not in LCLint library "
476 "format (missing library code). Attempting "
477 "to continue without library.", name));
482 flagcode code = (flagcode) lib;
484 if (flagcode_isLibraryFlag (code))
486 if (context_doMerge ())
488 context_setLibrary (code);
493 loadllmsg (message ("Load library %s has invalid library code. "
494 "Attempting to continue without library.",
507 loadllmsg (message ("Load library %s is not in LCLint library format (missing lines). "
508 "Attempting to continue without library.", name));
515 typeIdSet_loadTable (f);
521 context_loadModuleAccess (f);
528 ** load state from file created by dumpState
532 loadState (cstring cfname)
535 char *fname = cstring_toCharsSafe (cfname);
536 cstring ofname = cstring_copy (cfname);
538 fname = addExtension (fname, DUMP_SUFFIX);
540 f = fopen (fname, "r");
544 if (context_getDebug (FLG_SHOWSCAN))
545 fprintf (g_msgstream, " >\n");
547 llfatalerror (message ("Cannot open dump file for loading: %s", cfname));
551 fileloc_reallyFree (g_currentloc);
552 g_currentloc = fileloc_createLib (ofname);
554 if (!loadStateFile (f, ofname))
556 if (!loadStandardState ())
562 check (fclose (f) == 0);
565 cstring_free (ofname);