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
28 * Modified by Herbert 04/19/97:
29 * - added new include file portab.h.
30 * - added new private function fileloc_filenameForCpp() to handle
31 * filenames belonging to "#line" statements for OS/2 and MSDOS. It
32 * gets called by fileloc_lineMarker() and fileloc_previousLineMarker()
33 * instead of fileloc_unparseFilename().
36 # include "lclintMacros.nf"
38 # include "fileIdList.h"
41 static /*@only@*/ fileloc fileloc_createPrim (flkind p_kind, fileId p_fid, int p_line, int p_col);
43 static flkind fileId_kind (fileId s)
45 cstring fname = rootFileName (s);
47 if (fileLib_isLCLFile (fname))
51 else if (cstring_equalPrefix (fname, SYSTEM_LIBDIR))
62 fileloc_decColumn (fileloc f, int x)
64 fileloc ret = fileloc_copy (f);
65 if (x > 0 && fileloc_isDefined (ret))
67 llassertprint (ret->column > x, ("decColumn: %d", x));
75 fileloc_noColumn (fileloc f)
77 if (fileloc_isDefined (f))
79 fileloc ret = fileloc_copy (f);
81 if (fileloc_isDefined (ret))
90 return fileloc_undefined;
95 fileloc_subColumn (fileloc f, int x)
97 if (x > 0 && fileloc_isDefined (f))
99 llassert (f->column > x);
104 fileloc fileloc_copy (fileloc f)
106 if (fileloc_isDefined (f))
108 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
111 ** Legitimate (spurious) errors reported since no copy
115 /*@i3@*/ return f; /* No copy is necessary. */
119 return (fileloc_createPrim (f->kind, f->fid, f->lineno, f->column));
124 return fileloc_undefined;
128 fileloc fileloc_update (/*@only@*/ fileloc old, fileloc fnew)
130 if (fileloc_isUndefined (fnew))
133 return fileloc_undefined;
135 else if (fileloc_isUndefined (old) || fileloc_isBuiltin (old) || fileloc_isExternal (old))
137 return (fileloc_copy (fnew));
141 old->kind = fnew->kind;
142 old->fid = fnew->fid;
143 old->lineno = fnew->lineno;
144 old->column = fnew->column;
150 fileloc fileloc_updateFileId (/*@only@*/ fileloc old, fileId s)
152 if (fileloc_isUndefined (old) || fileloc_isBuiltin (old) || fileloc_isExternal (old))
154 return (fileloc_create (s, 1, 1));
158 old->kind = fileId_kind (s);
168 fileloc_free (/*@only@*/ fileloc f)
170 if (fileloc_isDefined (f))
172 if (f != g_currentloc)
174 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
186 ; /* Don't free g_currentloc ever! */
193 fileloc_reallyFree (/*@only@*/ fileloc f)
195 if (fileloc_isDefined (f))
197 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
204 /*@-branchstate@*/ } /*@=branchstate@*/
208 cstring fileloc_getBase (fileloc f)
210 llassert (fileloc_isDefined (f));
212 return (fileNameBase (f->fid));
216 fileloc_equal (fileloc f1, fileloc f2)
219 || (fileloc_isDefined (f1) && fileloc_isDefined (f2)
220 && ((f1->column == f2->column) &&
221 (f1->lineno == f2->lineno) && fileloc_sameFile (f1, f2))));
225 fileloc_compare (fileloc f1, fileloc f2)
227 if (fileloc_isUndefined (f1))
229 if (fileloc_isUndefined (f2)) return 0;
233 if (fileloc_isUndefined (f2))
237 INTCOMPARERETURN (f1->fid, f2->fid);
238 /*@noaccess fileId@*/
241 /* drl 8-11-01 fix what I think is a bug
242 lineno should more important than column number*/
244 INTCOMPARERETURN (f1->lineno, f2->lineno);
245 INTCOMPARERETURN (f1->column, f2->column);
251 fileloc_withinLines (fileloc f1, fileloc f2, int n)
254 return (fileloc_isDefined (f1) &&
255 fileloc_isDefined (f2) &&
256 ((f2->lineno <= f1->lineno + n)
257 && (f2->lineno >= f1->lineno)
258 && fileloc_sameFile (f1, f2)));
262 fileloc_lessthan (fileloc f1, fileloc f2)
265 return ((fileloc_isDefined (f1) && fileloc_isDefined (f2))
266 && ((f1->fid < f2->fid)
267 || ((f1->fid == f2->fid)
268 && ((f1->lineno < f2->lineno)
269 || ((f1->lineno == f2->lineno)
270 && (f1->column < f2->column))))));
275 ** returns true if f1 and f2 are different files,
276 ** or f1 is before f2 in same file
280 fileloc_notAfter (fileloc f1, fileloc f2)
283 return ((fileloc_isDefined (f1) && fileloc_isDefined (f2))
284 && ((f1->fid != f2->fid)
285 || ((f1->lineno < f2->lineno)
286 || ((f1->lineno == f2->lineno)
287 && (f1->column <= f2->column)))));
288 /*@noaccess fileId@*/
293 fileloc_isStandardLibrary (fileloc f)
295 cstring s = fileloc_getBase (f);
297 return (cstring_equalLit (s, LLSTDLIBS_NAME)
298 || cstring_equalLit (s, LLSTRICTLIBS_NAME)
299 || cstring_equalLit (s, LLUNIXLIBS_NAME)
300 || cstring_equalLit (s, LLUNIXSTRICTLIBS_NAME)
301 || cstring_equalLit (s, LLPOSIXSTRICTLIBS_NAME)
302 || cstring_equalLit (s, LLPOSIXLIBS_NAME));
307 fileloc_sameFileAndLine (fileloc f1, fileloc f2)
309 return (fileloc_sameFile (f1, f2)
310 && (fileloc_isDefined (f1) && fileloc_isDefined (f2)
311 && f1->lineno == f2->lineno));
315 fileloc_sameFile (fileloc f1, fileloc f2)
317 if ((fileloc_isUndefined (f1) || (fileloc_isUndefined (f2))
318 || (fileloc_isLib (f1)) || (fileloc_isLib (f2))))
324 return (fileId_equal (f1->fid, f2->fid));
329 fileloc_sameModule (fileloc f1, fileloc f2)
331 if (fileloc_isUndefined (f1))
333 return (fileloc_isUndefined (f2));
335 else if (fileloc_isUndefined (f2))
341 if (fileloc_isBuiltin (f1) || fileloc_isBuiltin (f2)
342 || fileloc_isExternal (f1) || fileloc_isExternal (f2))
344 return fileloc_sameFile (f1, f2);
348 cstring s1 = fileloc_getBase (f1);
349 cstring s2 = fileloc_getBase (f2);
351 return (cstring_equal (s1, s2));
357 fileloc_sameBaseFile (fileloc f1, fileloc f2)
359 if (fileloc_isUndefined (f1))
361 return (fileloc_isUndefined (f2));
363 else if (fileloc_isUndefined (f2))
369 return (fileId_baseEqual (f1->fid, f2->fid));
373 bool fileloc_isSystemFile (fileloc f1)
375 if (fileloc_isDefined (f1)
376 && !fileloc_isBuiltin (f1)
377 && !fileloc_isExternal (f1))
379 return (fileTable_isSystemFile (context_fileTable (), f1->fid));
385 bool fileloc_isXHFile (fileloc f1)
387 if (fileloc_isDefined (f1)
388 && !fileloc_isBuiltin (f1)
389 && !fileloc_isExternal (f1))
391 DPRINTF (("Fileloc is XH: [%p] %s", f1, fileloc_unparse (f1)));
392 return (fileTable_isXHFile (context_fileTable (), f1->fid));
399 fileloc_almostSameFile (fileloc f1, fileloc f2)
401 if ((fileloc_isUndefined (f1) || (fileloc_isUndefined (f2))
402 || (fileloc_isLib (f1)) || (fileloc_isLib (f2))))
408 if (fileId_baseEqual (f1->fid, f2->fid))
412 else if (fileTable_isSystemFile (context_fileTable (), f1->fid)
413 || fileTable_isSystemFile (context_fileTable (), f2->fid))
417 else if (fileTable_isSpecialFile (context_fileTable (), f1->fid)
418 || fileTable_isSpecialFile (context_fileTable (), f2->fid))
420 return (cstring_equal (fileloc_getBase (f1),
421 fileloc_getBase (f2)));
432 fileloc_fromTok (ltoken t)
434 cstring fname = ltoken_fileName (t);
435 fileId fid = fileTable_lookup (context_fileTable (), fname);
438 if (!fileId_isValid (fid))
440 fid = fileTable_addLCLFile (context_fileTable (), fname);
443 fl = fileloc_create (fid, (int) ltoken_getLine (t), (int) ltoken_getCol (t));
450 fileloc_createLib (cstring ln)
453 fileId fid = fileTable_lookup (context_fileTable (), ln);
455 if (!fileId_isValid (fid))
457 fid = fileTable_addLibraryFile (context_fileTable (), ln);
460 if (cstring_equalPrefix (ln, SYSTEM_LIBDIR))
465 return (fileloc_createPrim (fk, fid, 0, 0));
468 fileloc fileloc_createRc (cstring name)
470 fileId fid = fileTable_addFile (context_fileTable (), name);
472 return (fileloc_createPrim (FL_RC, fid, 0, 0));
475 fileloc fileloc_createExternal (void)
477 /*@i@*/ return (fileloc_getExternal ());
480 fileloc fileloc_getExternal (void)
482 static /*@owned@*/ fileloc res = fileloc_undefined;
484 if (res == fileloc_undefined)
486 res = fileloc_createPrim (FL_EXTERNAL, fileId_invalid, 0, 0);
492 fileloc fileloc_observeBuiltin ()
494 /*@-onlytrans@*/ return (fileloc_getBuiltin ()); /*@=onlytrans@*/
497 fileloc fileloc_getBuiltin ()
499 static /*@owned@*/ fileloc res = fileloc_undefined;
501 if (res == fileloc_undefined)
503 res = fileloc_createPrim (FL_BUILTIN, fileId_invalid, 0, 0);
510 fileloc_makePreproc (fileloc loc)
512 if (fileloc_isDefined (loc))
514 return (fileloc_createPrim (FL_PREPROC, loc->fid,
515 loc->lineno, loc->column));
518 return (fileloc_createPrim (FL_PREPROC, fileId_invalid, 0, 0));
522 fileloc_makePreprocPrevious (fileloc loc)
524 if (fileloc_isDefined (loc))
528 return (fileloc_createPrim (FL_PREPROC, loc->fid,
529 loc->lineno - 1, 0));
533 return (fileloc_createPrim (FL_PREPROC, loc->fid,
538 return (fileloc_createPrim (FL_PREPROC, fileId_invalid, 0, 0));
542 fileloc_createBuiltin ()
544 return (fileloc_createPrim (FL_BUILTIN, fileId_invalid, 0, 0));
549 fileloc_createImport (cstring fname, int lineno)
551 fileId fid = fileTable_lookup (context_fileTable (), fname);
553 if (!fileId_isValid (fid))
555 fid = fileTable_addImportFile (context_fileTable (), fname);
558 return (fileloc_createPrim (FL_IMPORT, fid, lineno, 0));
562 static /*@only@*/ fileloc
563 fileloc_createPrim (flkind kind, fileId fid, int line, int col)
565 fileloc f = (fileloc) dmalloc (sizeof (*f));
572 DPRINTF (("Fileloc create: [%p] %s", f, fileloc_unparse (f)));
578 fileloc_createSpec (fileId fid, int line, int col)
580 return (fileloc_createPrim (FL_SPEC, fid, line, col));
584 fileloc fileloc_create (fileId fid, int line, int col)
586 return (fileloc_createPrim (fileId_kind (fid), fid, line, col));
589 /*@observer@*/ cstring
590 fileloc_filename (fileloc f)
592 return (fileloc_isDefined (f)
593 ? rootFileName (f->fid) : cstring_makeLiteralTemp ("<unknown>"));
597 fileloc_unparseFilename (fileloc f)
599 if (fileloc_isDefined (f))
604 return (message ("load file %s", fileloc_filename (f)));
606 return (cstring_makeLiteral ("# builtin #"));
608 return (message ("import file %s", fileloc_filename (f)));
610 return (cstring_makeLiteral ("<external>"));
612 return (cstring_copy (fileloc_filename (f)));
615 return cstring_undefined;
619 fileloc_lineno (fileloc f)
621 return (fileloc_isDefined (f) ? f->lineno : -1);
625 fileloc_column (fileloc f)
627 return (fileloc_isDefined (f) ? f->column : -1);
631 fileloc_unparse (fileloc f)
633 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
635 if (fileloc_isDefined (f))
640 return (cstring_makeLiteral ("Command Line"));
644 return (message ("import file %s(%d)", rootFileName (f->fid), f->lineno));
648 return (message ("import file %s:%d", rootFileName (f->fid), f->lineno));
653 return (message ("%s(%d)", rootFileName (f->fid), f->lineno));
657 return (message ("%s:%d", rootFileName (f->fid), f->lineno));
660 return (cstring_makeLiteral ("<external>"));
665 if (f->kind == FL_LIB)
667 fname = message ("load file %s", rootFileName (f->fid));
668 cstring_markOwned (fname); /*@i32 memory leak...@*/
672 fname = rootFileName (f->fid);
675 if (context_getFlag (FLG_SHOWCOL))
677 if (fileloc_linenoDefined (f))
679 if (fileloc_columnDefined (f))
683 return (message ("%s(%d,%d)", fname, f->lineno, f->column));
687 return (message ("%s:%d:%d", fname, f->lineno, f->column));
694 return (message ("%s(%d)", fname, f->lineno));
698 return (message ("%s:%d", fname, f->lineno));
702 return (cstring_copy (fname));
704 else if (fileloc_linenoDefined (f))
708 return (message ("%s(%d)", fname, f->lineno));
712 return (message ("%s:%d", fname, f->lineno));
717 return (cstring_copy (fname));
723 return (cstring_makeLiteral ("< Location unknown >"));
727 fileloc_unparseRaw (cstring fname, int lineno)
729 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
733 return (message ("%s(%d)", fname, lineno));
737 return (message ("%s:%d", fname, lineno));
742 fileloc_unparseRawCol (cstring fname, int lineno, int col)
744 if (context_getFlag (FLG_SHOWCOL))
746 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
750 return (message ("%s(%d,%d)", fname, lineno, col));
754 return (message ("%s:%d:%d", fname, lineno, col));
759 return fileloc_unparseRaw (fname, lineno);
763 bool fileloc_isSpecialFile (fileloc f)
765 if (fileloc_isDefined (f)
766 && fileId_isValid (f->fid))
768 return (fileTable_isSpecialFile (context_fileTable (), f->fid));
776 bool fileloc_isHeader (fileloc f)
778 /* returns true if is not a .c file */
780 return (fileloc_isDefined (f) && fileId_isValid (f->fid)
781 && fileId_isHeader (f->fid));
784 bool fileloc_isSpec (fileloc f)
786 return (fileloc_isDefined (f) &&
787 (f->kind == FL_LIB || f->kind == FL_STDLIB || f->kind == FL_SPEC));
790 bool fileloc_isRealSpec (fileloc f)
792 return (fileloc_isDefined (f) && (f->kind == FL_SPEC));
795 bool fileloc_isLib (fileloc f)
797 return (fileloc_isDefined (f)
798 && (f->kind == FL_LIB || f->kind == FL_STDHDR || f->kind == FL_STDLIB));
801 bool fileloc_isStandardLib (fileloc f)
803 return (fileloc_isDefined (f) && f->kind == FL_STDLIB);
806 /*@only@*/ cstring fileloc_unparseDirect (fileloc fl)
808 if (fileloc_isDefined (fl))
810 return (message ("%d:%d:%d",
811 /*@access fileId@*/ (int) fl->fid, /*@noaccess fileId@*/
812 fl->lineno, fl->column));
816 return (cstring_makeLiteral ("<undef>"));
820 bool fileloc_isUser (fileloc f)
822 return (fileloc_isDefined (f)
823 && f->kind == FL_NORMAL);