2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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
28 * Modified by Herbert 04/19/97:
29 * - added new include file portab.h (now in osd.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 "splintMacros.nf"
40 static /*@only@*/ fileloc fileloc_createPrim (flkind p_kind, fileId p_fid, int p_line, int p_col) /*@*/ ;
43 ** builtin locs are never free'd
46 static /*@owned@*/ fileloc s_builtinLoc = fileloc_undefined;
47 static /*@owned@*/ fileloc s_externalLoc = fileloc_undefined;
49 void fileloc_destroyMod ()
51 if (fileloc_isDefined (s_builtinLoc))
54 s_builtinLoc = fileloc_undefined;
57 if (fileloc_isDefined (s_externalLoc))
59 sfree (s_externalLoc);
60 s_externalLoc = fileloc_undefined;
64 static flkind fileId_kind (fileId s)
66 cstring fname = fileTable_rootFileName (s);
68 if (fileLib_isLCLFile (fname))
72 else if (cstring_equalPrefix (fname, cstring_makeLiteralTemp (SYSTEM_LIBDIR)))
83 fileloc_decColumn (fileloc f, int x)
85 fileloc ret = fileloc_copy (f);
89 if (x > 0 && fileloc_isDefined (ret))
91 llassertprint (ret->column > x, ("decColumn %s: %d", fileloc_unparse (f), x));
99 fileloc_noColumn (fileloc f)
101 if (fileloc_isDefined (f))
103 fileloc ret = fileloc_copy (f);
105 if (fileloc_isDefined (ret))
114 return fileloc_undefined;
119 fileloc_subColumn (fileloc f, int x)
121 if (x > 0 && fileloc_isDefined (f))
123 llassert (f->column > x);
128 fileloc fileloc_copy (fileloc f)
130 if (fileloc_isDefined (f))
132 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
135 ** Legitimate (spurious) errors reported since no copy
139 /*@i3@*/ return f; /* No copy is necessary. */
143 return (fileloc_createPrim (f->kind, f->fid, f->lineno, f->column));
148 return fileloc_undefined;
152 fileloc fileloc_update (/*@only@*/ fileloc old, fileloc fnew)
154 if (fileloc_isUndefined (fnew))
157 return fileloc_undefined;
159 else if (fileloc_isUndefined (old) || fileloc_isBuiltin (old) || fileloc_isExternal (old))
161 return (fileloc_copy (fnew));
165 old->kind = fnew->kind;
166 old->fid = fnew->fid;
167 old->lineno = fnew->lineno;
168 old->column = fnew->column;
174 fileloc fileloc_updateFileId (/*@only@*/ fileloc old, fileId s)
176 if (fileloc_isUndefined (old) || fileloc_isBuiltin (old) || fileloc_isExternal (old))
178 return (fileloc_create (s, 1, 1));
182 old->kind = fileId_kind (s);
192 fileloc_free (/*@only@*/ fileloc f)
194 if (fileloc_isDefined (f))
196 if (f != g_currentloc)
198 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
210 ; /* Don't free g_currentloc ever! */
217 fileloc_reallyFree (/*@only@*/ fileloc f)
219 if (fileloc_isDefined (f))
221 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
228 /*@-branchstate@*/ } /*@=branchstate@*/
232 cstring fileloc_getBase (fileloc f)
234 llassert (fileloc_isDefined (f));
236 return (fileTable_fileNameBase (f->fid));
240 fileloc_equal (fileloc f1, fileloc f2)
243 || (fileloc_isDefined (f1) && fileloc_isDefined (f2)
244 && ((f1->column == f2->column) &&
245 (f1->lineno == f2->lineno) && fileloc_sameFile (f1, f2))));
249 fileloc_compare (fileloc f1, fileloc f2)
251 if (fileloc_isUndefined (f1))
253 if (fileloc_isUndefined (f2)) return 0;
257 if (fileloc_isUndefined (f2))
261 INTCOMPARERETURN (f1->fid, f2->fid);
262 /*@noaccess fileId@*/
265 /* drl 8-11-01 fix what I think is a bug
266 lineno should more important than column number*/
268 INTCOMPARERETURN (f1->lineno, f2->lineno);
269 INTCOMPARERETURN (f1->column, f2->column);
275 fileloc_withinLines (fileloc f1, fileloc f2, int n)
278 return (fileloc_isDefined (f1) &&
279 fileloc_isDefined (f2) &&
280 ((f2->lineno <= f1->lineno + n)
281 && (f2->lineno >= f1->lineno)
282 && fileloc_sameFile (f1, f2)));
286 fileloc_lessthan (fileloc f1, fileloc f2)
289 return ((fileloc_isDefined (f1) && fileloc_isDefined (f2))
290 && ((f1->fid < f2->fid)
291 || ((f1->fid == f2->fid)
292 && ((f1->lineno < f2->lineno)
293 || ((f1->lineno == f2->lineno)
294 && (f1->column < f2->column))))));
299 ** returns true if f1 and f2 are different files,
300 ** or f1 is before f2 in same file
304 fileloc_notAfter (fileloc f1, fileloc f2)
307 return ((fileloc_isDefined (f1) && fileloc_isDefined (f2))
308 && ((f1->fid != f2->fid)
309 || ((f1->lineno < f2->lineno)
310 || ((f1->lineno == f2->lineno)
311 && (f1->column <= f2->column)))));
312 /*@noaccess fileId@*/
316 fileloc_isStandardLibrary (fileloc f)
318 cstring s = fileloc_getBase (f);
320 return (cstring_equalLit (s, LLSTDLIBS_NAME)
321 || cstring_equalLit (s, LLSTRICTLIBS_NAME)
322 || cstring_equalLit (s, LLUNIXLIBS_NAME)
323 || cstring_equalLit (s, LLUNIXSTRICTLIBS_NAME)
324 || cstring_equalLit (s, LLPOSIXSTRICTLIBS_NAME)
325 || cstring_equalLit (s, LLPOSIXLIBS_NAME));
329 fileloc_sameFileAndLine (fileloc f1, fileloc f2)
331 return (fileloc_sameFile (f1, f2)
332 && (fileloc_isDefined (f1) && fileloc_isDefined (f2)
333 && f1->lineno == f2->lineno));
337 fileloc_sameFile (fileloc f1, fileloc f2)
339 if ((fileloc_isUndefined (f1) || (fileloc_isUndefined (f2))
340 || (fileloc_isLib (f1)) || (fileloc_isLib (f2))))
346 return (fileId_equal (f1->fid, f2->fid));
351 fileloc_sameModule (fileloc f1, fileloc f2)
353 if (fileloc_isUndefined (f1))
355 return (fileloc_isUndefined (f2));
357 else if (fileloc_isUndefined (f2))
363 if (fileloc_isBuiltin (f1) || fileloc_isBuiltin (f2)
364 || fileloc_isExternal (f1) || fileloc_isExternal (f2))
366 return fileloc_sameFile (f1, f2);
370 cstring s1 = fileloc_getBase (f1);
371 cstring s2 = fileloc_getBase (f2);
373 return (cstring_equal (s1, s2));
379 fileloc_sameBaseFile (fileloc f1, fileloc f2)
381 if (fileloc_isUndefined (f1))
383 return (fileloc_isUndefined (f2));
385 else if (fileloc_isUndefined (f2))
391 return (fileId_baseEqual (f1->fid, f2->fid));
395 bool fileloc_isSystemFile (fileloc f1)
397 if (fileloc_isDefined (f1)
398 && !fileloc_isBuiltin (f1)
399 && !fileloc_isExternal (f1))
401 return (fileTable_isSystemFile (context_fileTable (), f1->fid));
407 bool fileloc_isXHFile (fileloc f1)
409 if (fileloc_isDefined (f1)
410 && !fileloc_isBuiltin (f1)
411 && !fileloc_isExternal (f1))
413 DPRINTF (("Fileloc is XH: [%p] %s", f1, fileloc_unparse (f1)));
414 return (fileTable_isXHFile (context_fileTable (), f1->fid));
421 fileloc_almostSameFile (fileloc f1, fileloc f2)
423 if ((fileloc_isUndefined (f1) || (fileloc_isUndefined (f2))
424 || (fileloc_isLib (f1)) || (fileloc_isLib (f2))))
430 if (fileId_baseEqual (f1->fid, f2->fid))
434 else if (fileTable_isSystemFile (context_fileTable (), f1->fid)
435 || fileTable_isSystemFile (context_fileTable (), f2->fid))
439 else if (fileTable_isSpecialFile (context_fileTable (), f1->fid)
440 || fileTable_isSpecialFile (context_fileTable (), f2->fid))
442 return (cstring_equal (fileloc_getBase (f1),
443 fileloc_getBase (f2)));
453 fileloc_fromTok (ltoken t)
455 cstring fname = ltoken_fileName (t);
456 fileId fid = fileTable_lookup (context_fileTable (), fname);
459 if (!fileId_isValid (fid))
461 fid = fileTable_addLCLFile (context_fileTable (), fname);
464 fl = fileloc_create (fid, (int) ltoken_getLine (t), (int) ltoken_getCol (t));
470 fileloc_createLib (cstring ln)
473 fileId fid = fileTable_lookup (context_fileTable (), ln);
475 if (!fileId_isValid (fid))
477 fid = fileTable_addLibraryFile (context_fileTable (), ln);
480 if (cstring_equalPrefix (ln, cstring_makeLiteralTemp (SYSTEM_LIBDIR)))
485 return (fileloc_createPrim (fk, fid, 0, 0));
488 fileloc fileloc_createRc (cstring name)
490 fileId fid = fileTable_addFile (context_fileTable (), name);
492 return (fileloc_createPrim (FL_RC, fid, 0, 0));
495 fileloc fileloc_createExternal (void)
497 /*@i@*/ return (fileloc_getExternal ());
500 fileloc fileloc_getExternal (void)
502 if (s_externalLoc == fileloc_undefined)
504 s_externalLoc = fileloc_createPrim (FL_EXTERNAL, fileId_invalid, 0, 0);
507 return s_externalLoc;
510 fileloc fileloc_observeBuiltin ()
512 /*@-onlytrans@*/ return (fileloc_getBuiltin ()); /*@=onlytrans@*/
515 fileloc fileloc_getBuiltin ()
517 static /*@owned@*/ fileloc res = fileloc_undefined;
519 if (res == fileloc_undefined)
521 res = fileloc_createPrim (FL_BUILTIN, fileId_invalid, 0, 0);
528 fileloc_makePreproc (fileloc loc)
530 if (fileloc_isDefined (loc))
532 return (fileloc_createPrim (FL_PREPROC, loc->fid,
533 loc->lineno, loc->column));
536 return (fileloc_createPrim (FL_PREPROC, fileId_invalid, 0, 0));
540 fileloc_makePreprocPrevious (fileloc loc)
542 if (fileloc_isDefined (loc))
546 return (fileloc_createPrim (FL_PREPROC, loc->fid,
547 loc->lineno - 1, 0));
551 return (fileloc_createPrim (FL_PREPROC, loc->fid,
556 return (fileloc_createPrim (FL_PREPROC, fileId_invalid, 0, 0));
559 /* We pretend the result is only, because fileloc_free doesn't free it! */
561 fileloc_createBuiltin ()
563 if (fileloc_isUndefined (s_builtinLoc))
565 s_builtinLoc = fileloc_createPrim (FL_BUILTIN, fileId_invalid, 0, 0);
568 /*@-globstate@*/ /*@-retalias@*/
570 /*@=globstate@*/ /*@=retalias@*/
574 fileloc_createImport (cstring fname, int lineno)
576 fileId fid = fileTable_lookup (context_fileTable (), fname);
578 if (!fileId_isValid (fid))
580 fid = fileTable_addImportFile (context_fileTable (), fname);
583 return (fileloc_createPrim (FL_IMPORT, fid, lineno, 0));
586 static /*@only@*/ fileloc
587 fileloc_createPrim (flkind kind, fileId fid, int line, int col)
589 fileloc f = (fileloc) dmalloc (sizeof (*f));
596 DPRINTF (("Fileloc create: [%p] %s", f, fileloc_unparse (f)));
601 fileloc_createSpec (fileId fid, int line, int col)
603 return (fileloc_createPrim (FL_SPEC, fid, line, col));
606 fileloc fileloc_create (fileId fid, int line, int col)
608 return (fileloc_createPrim (fileId_kind (fid), fid, line, col));
611 /*@observer@*/ cstring
612 fileloc_filename (fileloc f)
614 return (fileloc_isDefined (f) ? fileTable_rootFileName (f->fid) : cstring_makeLiteralTemp ("<unknown>"));
617 /*@only@*/ cstring fileloc_outputFilename (fileloc f)
619 if (fileloc_isDefined (f))
621 if (fileId_isValid (f->fid))
623 return osd_outputPath (fileTable_rootFileName (f->fid));
627 return cstring_makeLiteral ("<invalid>");
632 return cstring_makeLiteral ("<unknown>");
637 fileloc_unparseFilename (fileloc f)
639 if (fileloc_isDefined (f))
644 return (message ("load file %q", fileloc_outputFilename (f)));
646 return (cstring_makeLiteral ("# builtin #"));
648 return (message ("import file %q", fileloc_outputFilename (f)));
650 return (cstring_makeLiteral ("<external>"));
652 return (fileloc_outputFilename (f));
655 return cstring_undefined;
659 fileloc_lineno (fileloc f)
661 return (fileloc_isDefined (f) ? f->lineno : -1);
665 fileloc_column (fileloc f)
667 return (fileloc_isDefined (f) ? f->column : -1);
671 fileloc_unparse (fileloc f)
673 static bool in_funparse = FALSE;
674 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
675 bool htmlFormat = context_getFlag (FLG_HTMLFILEFORMAT);
676 cstring res = cstring_undefined;
678 /* watch out for recursive calls when debugging... */
679 llassert (!in_funparse);
682 if (fileloc_isDefined (f))
688 res = cstring_makeLiteral ("Command Line");
694 res = message ("import file %q(%d)", fileloc_outputFilename (f), f->lineno);
698 res = message ("import file %q:%d", fileloc_outputFilename (f), f->lineno);
705 res = message ("%q(%d)", fileloc_outputFilename (f), f->lineno);
709 res = message ("%q:%d", fileloc_outputFilename (f), f->lineno);
715 res = cstring_makeLiteral ("<external>");
721 if (f->kind == FL_LIB)
723 fname = message ("load file %q", fileloc_outputFilename (f));
725 if (!context_getFlag (FLG_SHOWLOADLOC))
733 fname = fileloc_outputFilename (f);
736 if (context_getFlag (FLG_SHOWCOL))
738 if (fileloc_linenoDefined (f))
740 if (fileloc_columnDefined (f))
744 res = message ("%q(%d,%d)", fname, f->lineno, f->column);
748 res = message ("%q:%d:%d", fname, f->lineno, f->column);
755 res = message ("%q(%d)", fname, f->lineno);
759 res = message ("%q:%d", fname, f->lineno);
766 /*@-branchstate@*/ /* spurious warnings reporteded because of break above */
769 else if (fileloc_linenoDefined (f))
773 res = message ("%q(%d)", fname, f->lineno);
777 res = message ("%q:%d", fname, f->lineno);
787 if (htmlFormat && fileloc_linenoDefined (f))
789 res = message ("<a href=\"#line%d\">%s</a>", f->lineno, res);
794 res = cstring_makeLiteral ("< Location unknown >");
796 /*@=branchstate@*/ /* this is a spurious warning because of the break */
803 fileloc_unparseRaw (cstring fname, int lineno)
805 if (!cstring_isEmpty (fname))
807 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
811 return (message ("%q(%d)", osd_outputPath (fname), lineno));
815 return (message ("%q:%d", osd_outputPath (fname), lineno));
820 return cstring_makeLiteral ("Command Line");
825 fileloc_unparseRawCol (cstring fname, int lineno, int col)
827 if (!cstring_isEmpty (fname))
829 if (context_getFlag (FLG_SHOWCOL))
831 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
835 return (message ("%q(%d,%d)", osd_outputPath (fname), lineno, col));
839 return (message ("%q:%d:%d", osd_outputPath (fname), lineno, col));
844 return fileloc_unparseRaw (fname, lineno);
849 return cstring_makeLiteral ("Command Line");
853 bool fileloc_isSpecialFile (fileloc f)
855 if (fileloc_isDefined (f)
856 && fileId_isValid (f->fid))
858 return (fileTable_isSpecialFile (context_fileTable (), f->fid));
866 bool fileloc_isHeader (fileloc f)
868 /* returns true if is not a .c file */
870 return (fileloc_isDefined (f) && fileId_isValid (f->fid)
871 && fileId_isHeader (f->fid));
874 bool fileloc_isSpec (fileloc f)
876 return (fileloc_isDefined (f) &&
877 (f->kind == FL_LIB || f->kind == FL_STDLIB || f->kind == FL_SPEC));
880 bool fileloc_isRealSpec (fileloc f)
882 return (fileloc_isDefined (f) && (f->kind == FL_SPEC));
885 bool fileloc_isLib (fileloc f)
887 return (fileloc_isDefined (f)
888 && (f->kind == FL_LIB || f->kind == FL_STDHDR || f->kind == FL_STDLIB));
891 bool fileloc_isStandardLib (fileloc f)
893 return (fileloc_isDefined (f) && f->kind == FL_STDLIB);
896 /*@only@*/ cstring fileloc_unparseDirect (fileloc fl)
898 if (fileloc_isDefined (fl))
900 return (message ("%d:%d:%d",
901 /*@access fileId@*/ (int) fl->fid, /*@noaccess fileId@*/
902 fl->lineno, fl->column));
906 return (cstring_makeLiteral ("<undef>"));
910 bool fileloc_isUser (fileloc f)
912 return (fileloc_isDefined (f)
913 && f->kind == FL_NORMAL);