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
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 "splintMacros.nf"
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 = fileTable_rootFileName (s);
47 if (fileLib_isLCLFile (fname))
51 else if (cstring_equalPrefix (fname, cstring_makeLiteralTemp (SYSTEM_LIBDIR)))
62 fileloc_decColumn (fileloc f, int x)
64 fileloc ret = fileloc_copy (f);
68 if (x > 0 && fileloc_isDefined (ret))
70 llassertprint (ret->column > x, ("decColumn: %d", x));
78 fileloc_noColumn (fileloc f)
80 if (fileloc_isDefined (f))
82 fileloc ret = fileloc_copy (f);
84 if (fileloc_isDefined (ret))
93 return fileloc_undefined;
98 fileloc_subColumn (fileloc f, int x)
100 if (x > 0 && fileloc_isDefined (f))
102 llassert (f->column > x);
107 fileloc fileloc_copy (fileloc f)
109 if (fileloc_isDefined (f))
111 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
114 ** Legitimate (spurious) errors reported since no copy
118 /*@i3@*/ return f; /* No copy is necessary. */
122 return (fileloc_createPrim (f->kind, f->fid, f->lineno, f->column));
127 return fileloc_undefined;
131 fileloc fileloc_update (/*@only@*/ fileloc old, fileloc fnew)
133 if (fileloc_isUndefined (fnew))
136 return fileloc_undefined;
138 else if (fileloc_isUndefined (old) || fileloc_isBuiltin (old) || fileloc_isExternal (old))
140 return (fileloc_copy (fnew));
144 old->kind = fnew->kind;
145 old->fid = fnew->fid;
146 old->lineno = fnew->lineno;
147 old->column = fnew->column;
153 fileloc fileloc_updateFileId (/*@only@*/ fileloc old, fileId s)
155 if (fileloc_isUndefined (old) || fileloc_isBuiltin (old) || fileloc_isExternal (old))
157 return (fileloc_create (s, 1, 1));
161 old->kind = fileId_kind (s);
171 fileloc_free (/*@only@*/ fileloc f)
173 if (fileloc_isDefined (f))
175 if (f != g_currentloc)
177 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
189 ; /* Don't free g_currentloc ever! */
196 fileloc_reallyFree (/*@only@*/ fileloc f)
198 if (fileloc_isDefined (f))
200 if (fileloc_isBuiltin (f) || fileloc_isExternal (f))
207 /*@-branchstate@*/ } /*@=branchstate@*/
211 cstring fileloc_getBase (fileloc f)
213 llassert (fileloc_isDefined (f));
215 return (fileTable_fileNameBase (f->fid));
219 fileloc_equal (fileloc f1, fileloc f2)
222 || (fileloc_isDefined (f1) && fileloc_isDefined (f2)
223 && ((f1->column == f2->column) &&
224 (f1->lineno == f2->lineno) && fileloc_sameFile (f1, f2))));
228 fileloc_compare (fileloc f1, fileloc f2)
230 if (fileloc_isUndefined (f1))
232 if (fileloc_isUndefined (f2)) return 0;
236 if (fileloc_isUndefined (f2))
240 INTCOMPARERETURN (f1->fid, f2->fid);
241 /*@noaccess fileId@*/
244 /* drl 8-11-01 fix what I think is a bug
245 lineno should more important than column number*/
247 INTCOMPARERETURN (f1->lineno, f2->lineno);
248 INTCOMPARERETURN (f1->column, f2->column);
254 fileloc_withinLines (fileloc f1, fileloc f2, int n)
257 return (fileloc_isDefined (f1) &&
258 fileloc_isDefined (f2) &&
259 ((f2->lineno <= f1->lineno + n)
260 && (f2->lineno >= f1->lineno)
261 && fileloc_sameFile (f1, f2)));
265 fileloc_lessthan (fileloc f1, fileloc f2)
268 return ((fileloc_isDefined (f1) && fileloc_isDefined (f2))
269 && ((f1->fid < f2->fid)
270 || ((f1->fid == f2->fid)
271 && ((f1->lineno < f2->lineno)
272 || ((f1->lineno == f2->lineno)
273 && (f1->column < f2->column))))));
278 ** returns true if f1 and f2 are different files,
279 ** or f1 is before f2 in same file
283 fileloc_notAfter (fileloc f1, fileloc f2)
286 return ((fileloc_isDefined (f1) && fileloc_isDefined (f2))
287 && ((f1->fid != f2->fid)
288 || ((f1->lineno < f2->lineno)
289 || ((f1->lineno == f2->lineno)
290 && (f1->column <= f2->column)))));
291 /*@noaccess fileId@*/
296 fileloc_isStandardLibrary (fileloc f)
298 cstring s = fileloc_getBase (f);
300 return (cstring_equalLit (s, LLSTDLIBS_NAME)
301 || cstring_equalLit (s, LLSTRICTLIBS_NAME)
302 || cstring_equalLit (s, LLUNIXLIBS_NAME)
303 || cstring_equalLit (s, LLUNIXSTRICTLIBS_NAME)
304 || cstring_equalLit (s, LLPOSIXSTRICTLIBS_NAME)
305 || cstring_equalLit (s, LLPOSIXLIBS_NAME));
310 fileloc_sameFileAndLine (fileloc f1, fileloc f2)
312 return (fileloc_sameFile (f1, f2)
313 && (fileloc_isDefined (f1) && fileloc_isDefined (f2)
314 && f1->lineno == f2->lineno));
318 fileloc_sameFile (fileloc f1, fileloc f2)
320 if ((fileloc_isUndefined (f1) || (fileloc_isUndefined (f2))
321 || (fileloc_isLib (f1)) || (fileloc_isLib (f2))))
327 return (fileId_equal (f1->fid, f2->fid));
332 fileloc_sameModule (fileloc f1, fileloc f2)
334 if (fileloc_isUndefined (f1))
336 return (fileloc_isUndefined (f2));
338 else if (fileloc_isUndefined (f2))
344 if (fileloc_isBuiltin (f1) || fileloc_isBuiltin (f2)
345 || fileloc_isExternal (f1) || fileloc_isExternal (f2))
347 return fileloc_sameFile (f1, f2);
351 cstring s1 = fileloc_getBase (f1);
352 cstring s2 = fileloc_getBase (f2);
354 return (cstring_equal (s1, s2));
360 fileloc_sameBaseFile (fileloc f1, fileloc f2)
362 if (fileloc_isUndefined (f1))
364 return (fileloc_isUndefined (f2));
366 else if (fileloc_isUndefined (f2))
372 return (fileId_baseEqual (f1->fid, f2->fid));
376 bool fileloc_isSystemFile (fileloc f1)
378 if (fileloc_isDefined (f1)
379 && !fileloc_isBuiltin (f1)
380 && !fileloc_isExternal (f1))
382 return (fileTable_isSystemFile (context_fileTable (), f1->fid));
388 bool fileloc_isXHFile (fileloc f1)
390 if (fileloc_isDefined (f1)
391 && !fileloc_isBuiltin (f1)
392 && !fileloc_isExternal (f1))
394 DPRINTF (("Fileloc is XH: [%p] %s", f1, fileloc_unparse (f1)));
395 return (fileTable_isXHFile (context_fileTable (), f1->fid));
402 fileloc_almostSameFile (fileloc f1, fileloc f2)
404 if ((fileloc_isUndefined (f1) || (fileloc_isUndefined (f2))
405 || (fileloc_isLib (f1)) || (fileloc_isLib (f2))))
411 if (fileId_baseEqual (f1->fid, f2->fid))
415 else if (fileTable_isSystemFile (context_fileTable (), f1->fid)
416 || fileTable_isSystemFile (context_fileTable (), f2->fid))
420 else if (fileTable_isSpecialFile (context_fileTable (), f1->fid)
421 || fileTable_isSpecialFile (context_fileTable (), f2->fid))
423 return (cstring_equal (fileloc_getBase (f1),
424 fileloc_getBase (f2)));
435 fileloc_fromTok (ltoken t)
437 cstring fname = ltoken_fileName (t);
438 fileId fid = fileTable_lookup (context_fileTable (), fname);
441 if (!fileId_isValid (fid))
443 fid = fileTable_addLCLFile (context_fileTable (), fname);
446 fl = fileloc_create (fid, (int) ltoken_getLine (t), (int) ltoken_getCol (t));
453 fileloc_createLib (cstring ln)
456 fileId fid = fileTable_lookup (context_fileTable (), ln);
458 if (!fileId_isValid (fid))
460 fid = fileTable_addLibraryFile (context_fileTable (), ln);
463 if (cstring_equalPrefix (ln, cstring_makeLiteralTemp (SYSTEM_LIBDIR)))
468 return (fileloc_createPrim (fk, fid, 0, 0));
471 fileloc fileloc_createRc (cstring name)
473 fileId fid = fileTable_addFile (context_fileTable (), name);
475 return (fileloc_createPrim (FL_RC, fid, 0, 0));
478 fileloc fileloc_createExternal (void)
480 /*@i@*/ return (fileloc_getExternal ());
483 fileloc fileloc_getExternal (void)
485 static /*@owned@*/ fileloc res = fileloc_undefined;
487 if (res == fileloc_undefined)
489 res = fileloc_createPrim (FL_EXTERNAL, fileId_invalid, 0, 0);
495 fileloc fileloc_observeBuiltin ()
497 /*@-onlytrans@*/ return (fileloc_getBuiltin ()); /*@=onlytrans@*/
500 fileloc fileloc_getBuiltin ()
502 static /*@owned@*/ fileloc res = fileloc_undefined;
504 if (res == fileloc_undefined)
506 res = fileloc_createPrim (FL_BUILTIN, fileId_invalid, 0, 0);
513 fileloc_makePreproc (fileloc loc)
515 if (fileloc_isDefined (loc))
517 return (fileloc_createPrim (FL_PREPROC, loc->fid,
518 loc->lineno, loc->column));
521 return (fileloc_createPrim (FL_PREPROC, fileId_invalid, 0, 0));
525 fileloc_makePreprocPrevious (fileloc loc)
527 if (fileloc_isDefined (loc))
531 return (fileloc_createPrim (FL_PREPROC, loc->fid,
532 loc->lineno - 1, 0));
536 return (fileloc_createPrim (FL_PREPROC, loc->fid,
541 return (fileloc_createPrim (FL_PREPROC, fileId_invalid, 0, 0));
545 fileloc_createBuiltin ()
547 return (fileloc_createPrim (FL_BUILTIN, fileId_invalid, 0, 0));
552 fileloc_createImport (cstring fname, int lineno)
554 fileId fid = fileTable_lookup (context_fileTable (), fname);
556 if (!fileId_isValid (fid))
558 fid = fileTable_addImportFile (context_fileTable (), fname);
561 return (fileloc_createPrim (FL_IMPORT, fid, lineno, 0));
565 static /*@only@*/ fileloc
566 fileloc_createPrim (flkind kind, fileId fid, int line, int col)
568 fileloc f = (fileloc) dmalloc (sizeof (*f));
575 DPRINTF (("Fileloc create: [%p] %s", f, fileloc_unparse (f)));
581 fileloc_createSpec (fileId fid, int line, int col)
583 return (fileloc_createPrim (FL_SPEC, fid, line, col));
587 fileloc fileloc_create (fileId fid, int line, int col)
589 return (fileloc_createPrim (fileId_kind (fid), fid, line, col));
592 /*@observer@*/ cstring
593 fileloc_filename (fileloc f)
595 return (fileloc_isDefined (f) ? fileTable_rootFileName (f->fid) : cstring_makeLiteralTemp ("<unknown>"));
598 /*@only@*/ cstring fileloc_outputFilename (fileloc f)
600 if (fileloc_isDefined (f))
602 if (fileId_isValid (f->fid))
604 return osd_outputPath (fileTable_rootFileName (f->fid));
608 return cstring_makeLiteral ("<invalid>");
613 return cstring_makeLiteral ("<unknown>");
618 fileloc_unparseFilename (fileloc f)
620 if (fileloc_isDefined (f))
625 return (message ("load file %q", fileloc_outputFilename (f)));
627 return (cstring_makeLiteral ("# builtin #"));
629 return (message ("import file %q", fileloc_outputFilename (f)));
631 return (cstring_makeLiteral ("<external>"));
633 return (fileloc_outputFilename (f));
636 return cstring_undefined;
640 fileloc_lineno (fileloc f)
642 return (fileloc_isDefined (f) ? f->lineno : -1);
646 fileloc_column (fileloc f)
648 return (fileloc_isDefined (f) ? f->column : -1);
652 fileloc_unparse (fileloc f)
654 static in_funparse = FALSE;
655 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
656 bool htmlFormat = context_getFlag (FLG_HTMLFILEFORMAT);
657 cstring res = cstring_undefined;
659 /* watch out for recursive calls when debugging... */
660 llassert (!in_funparse);
663 if (fileloc_isDefined (f))
669 res = cstring_makeLiteral ("Command Line");
675 res = message ("import file %q(%d)", fileloc_outputFilename (f), f->lineno);
679 res = message ("import file %q:%d", fileloc_outputFilename (f), f->lineno);
686 res = message ("%q(%d)", fileloc_outputFilename (f), f->lineno);
690 res = message ("%q:%d", fileloc_outputFilename (f), f->lineno);
696 res = cstring_makeLiteral ("<external>");
702 if (f->kind == FL_LIB)
704 fname = message ("load file %q", fileloc_outputFilename (f));
708 fname = fileloc_outputFilename (f);
711 if (context_getFlag (FLG_SHOWCOL))
713 if (fileloc_linenoDefined (f))
715 if (fileloc_columnDefined (f))
719 res = message ("%q(%d,%d)", fname, f->lineno, f->column);
723 res = message ("%q:%d:%d", fname, f->lineno, f->column);
730 res = message ("%q(%d)", fname, f->lineno);
734 res = message ("%q:%d", fname, f->lineno);
743 else if (fileloc_linenoDefined (f))
747 res = message ("%q(%d)", fname, f->lineno);
751 res = message ("%q:%d", fname, f->lineno);
761 if (htmlFormat && fileloc_linenoDefined (f))
763 res = message ("<a href=\"#line%d\">%s</a>", f->lineno, res);
768 res = cstring_makeLiteral ("< Location unknown >");
776 fileloc_unparseRaw (cstring fname, int lineno)
778 if (!cstring_isEmpty (fname))
780 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
784 return (message ("%q(%d)", osd_outputPath (fname), lineno));
788 return (message ("%q:%d", osd_outputPath (fname), lineno));
793 return cstring_makeLiteral ("Command Line");
798 fileloc_unparseRawCol (cstring fname, int lineno, int col)
800 if (!cstring_isEmpty (fname))
802 if (context_getFlag (FLG_SHOWCOL))
804 bool parenFormat = context_getFlag (FLG_PARENFILEFORMAT);
808 return (message ("%q(%d,%d)", osd_outputPath (fname), lineno, col));
812 return (message ("%q:%d:%d", osd_outputPath (fname), lineno, col));
817 return fileloc_unparseRaw (fname, lineno);
822 return cstring_makeLiteral ("Command Line");
826 bool fileloc_isSpecialFile (fileloc f)
828 if (fileloc_isDefined (f)
829 && fileId_isValid (f->fid))
831 return (fileTable_isSpecialFile (context_fileTable (), f->fid));
839 bool fileloc_isHeader (fileloc f)
841 /* returns true if is not a .c file */
843 return (fileloc_isDefined (f) && fileId_isValid (f->fid)
844 && fileId_isHeader (f->fid));
847 bool fileloc_isSpec (fileloc f)
849 return (fileloc_isDefined (f) &&
850 (f->kind == FL_LIB || f->kind == FL_STDLIB || f->kind == FL_SPEC));
853 bool fileloc_isRealSpec (fileloc f)
855 return (fileloc_isDefined (f) && (f->kind == FL_SPEC));
858 bool fileloc_isLib (fileloc f)
860 return (fileloc_isDefined (f)
861 && (f->kind == FL_LIB || f->kind == FL_STDHDR || f->kind == FL_STDLIB));
864 bool fileloc_isStandardLib (fileloc f)
866 return (fileloc_isDefined (f) && f->kind == FL_STDLIB);
869 /*@only@*/ cstring fileloc_unparseDirect (fileloc fl)
871 if (fileloc_isDefined (fl))
873 return (message ("%d:%d:%d",
874 /*@access fileId@*/ (int) fl->fid, /*@noaccess fileId@*/
875 fl->lineno, fl->column));
879 return (cstring_makeLiteral ("<undef>"));
883 bool fileloc_isUser (fileloc f)
885 return (fileloc_isDefined (f)
886 && f->kind == FL_NORMAL);