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
27 ** error reporting procedures
30 # include "splintMacros.nf"
35 # include "cpperror.h"
36 # include "Headers/version.h" /* Visual C++ finds a different version.h on some path! */
38 /* Don't allow possibly-recursive assertion failures. */
40 # define llassert llassertprotect
42 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
43 /*@modifies *p_stream@*/ ;
45 static int lclerrors = 0;
46 static size_t lastfileloclen = 10;
47 static /*@only@*/ cstring lastmsg = cstring_undefined;
48 static int mcount = 0;
49 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
50 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
51 static /*@only@*/ fileloc lastbug = fileloc_undefined;
52 static bool llgenerrorreal (char *p_srcFile, int p_srcLine,
53 /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
54 /*@modifies g_warningstream@*/ ;
55 static bool llgenerroraux (char *p_srcFile, int p_srcLine,
56 /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
57 /*@modifies g_warningstream@*/ ;
59 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
60 /*@globals lastfileloclen @*/
61 /*@modifies *p_stream@*/ ;
62 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
63 /*@modifies *p_stream@*/ ;
65 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
67 static void showSourceLoc (char *srcFile, int srcLine)
68 /*@modifies g_warningstream@*/
70 if (context_getFlag (FLG_SHOWSOURCELOC)) {
71 llgenhint (message ("%s:%d: Source code error generation point.",
72 cstring_fromChars (srcFile), srcLine));
77 static /*@null@*/ char *
78 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
87 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
90 /* don't exit (EXIT_FAILURE); */
93 static bool s_needsPrepare = TRUE;
95 void prepareMessage ()
97 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
100 if ((context_isPreprocessing () || context_loadingLibrary ())
102 && context_getFlag (FLG_SHOWSCAN))
106 s_needsPrepare = FALSE;
112 void closeMessage (void)
114 if (context_isPreprocessing ()
115 && context_getFlag (FLG_SHOWSCAN))
118 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
119 llassertprotect (!s_needsPrepare);
120 s_needsPrepare = TRUE;
129 llmsg (/*@only@*/ cstring s)
131 context_setNeednl ();
133 printMessage (g_messagestream, s);
138 lldiagmsg (/*@only@*/ cstring s)
140 static bool inmsg = FALSE;
144 fprintf (g_errorstream,
145 "Recursive message call detected: %s\n",
146 cstring_toCharsSafe (s));
152 context_setNeednl ();
154 printMessage (g_messagestream, s);
161 llmsgplain (/*@only@*/ cstring s)
163 context_setNeednl ();
165 printMessage (g_messagestream, s);
169 void llerror_flagWarning (cstring s)
171 if (context_getFlag (FLG_WARNFLAGS))
173 llgenmsg (s, g_currentloc);
182 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
184 int indent = context_getIndentSpaces () - 1;
186 if (indent < 0) indent = 0;
188 context_setNeednl ();
189 printIndentMessage (g_warningstream, s, indent);
195 if (context_getFlag (FLG_HINTS) &&
196 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
207 llshowhint (flagcode f)
209 if (context_getFlag (FLG_HINTS))
211 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
213 cstring desc = flagcodeHint (f);
215 if (cstring_isDefined (desc))
217 llgenhint (cstring_copy (desc));
224 llsuppresshint2 (char c, flagcode f1, flagcode f2)
227 if (context_getFlag (FLG_HINTS))
229 if ((flagcode_numReported (f1) == 0
230 || flagcode_numReported (f2) == 0)
231 || context_getFlag (FLG_FORCEHINTS))
233 cstring desc = flagcodeHint (f1);
234 context_setNeednl ();
237 if (cstring_isUndefined (desc))
239 desc = flagcodeHint (f2);
242 if (flagcode_isNamePrefixFlag (f1))
247 if (flagcode_isNamePrefixFlag (f2))
254 if (cstring_isDefined (desc))
256 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
258 flagcode_unparse (f1)));
262 llgenhint (message ("(Use %h%s to inhibit warning)",
263 c, flagcode_unparse (f1)));
268 if (cstring_isDefined (desc))
270 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
272 flagcode_unparse (f1),
274 flagcode_unparse (f2)));
278 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
279 flagcode_unparse (f1),
280 c, flagcode_unparse (f2)));
288 llsuppresshint (char c, flagcode f)
290 if (context_getFlag (FLG_HINTS))
292 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
294 cstring desc = flagcodeHint (f);
295 context_setNeednl ();
298 if (flagcode_isNamePrefixFlag (f))
303 if (cstring_isDefined (desc))
305 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
306 flagcode_unparse (f)));
310 llgenhint (message ("(Use %h%s to inhibit warning)", c,
311 flagcode_unparse (f)));
318 llnosuppresshint (flagcode f)
320 if (context_getFlag (FLG_FORCEHINTS))
322 cstring desc = flagcodeHint (f);
323 context_setNeednl ();
326 if (cstring_isDefined (desc))
328 printError (g_warningstream, message (" %s", desc));
333 /*@constant int MAXSEARCH; @*/
334 # define MAXSEARCH 20
336 /*@constant int MINLINE; @*/
339 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
342 mstring_split (/*@returned@*/ char **sp,
343 /*@out@*/ nd_charp *tp,
344 int maxline, /*@in@*/ int *indentchars)
353 DPRINTF (("Split: %s / %d", *sp, maxline));
355 if (maxline < MINLINELEN)
357 maxline = MINLINELEN;
360 if (*indentchars > 0)
362 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
366 nl = strchr (s, '\n');
371 ** if there is a newline in first maxline characters, split there
372 ** if line len is <= maxline, return no split
373 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
374 ** split there unless the ' ' is followed by a '}', then
376 ** of the ';' is inside quotation marks
377 ** if there is a space or tab in last maxsearch characters, split there
378 ** else, split at maxline
380 ** special code: slash [1-9] after a newline means indent the rest <n> chars
384 if ((nl != NULL) && ((nl - s) < maxline))
391 llassertprotect (*tp == NULL || (*tp > osp));
395 if (*t >= '\1' && *t <= '\7')
397 *indentchars += (int) (*t - '\1') + 1;
404 else if (size_toInt (strlen (s)) < maxline)
406 llassertprotect (*tp == NULL || (*tp > osp));
413 char *lcolon, *lsemi, *lcomma;
422 lcolon = strrchr (s, ':');
423 lsemi = strrchr (s, ';');
424 lcomma = strrchr (s, ',');
428 splitat = maxcp (lcolon, lsemi);
430 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
431 && *(splitat) != '\0'
432 && *(splitat + 1) == ' '
433 && (*(splitat + 2) != '}'
434 && *(splitat + 2) != ','
435 && (*(splitat + 2) != '\0')))
437 *(splitat + 1) = '\0';
440 llassertprotect (*tp == NULL || (*tp > osp));
444 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
448 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
449 && *(splitat) != '\0'
450 && *(splitat + 1) == ' '
451 && (*(splitat + 2) != '}'
452 && (*(splitat + 2) != '\0')))
454 *(splitat + 1) = '\0';
457 llassertprotect (*tp == NULL || (*tp > osp));
462 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
468 if (*t != ' ' && *t != '\t')
470 llassertprotect (maxline > 0);
471 t = mstring_copy (s + maxline);
472 *(s + maxline) = '\0';
477 llassertprotect (*tp == NULL || (*tp > osp));
481 mstring_markFree (t);
483 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
492 if (*t == '\0') return;
495 ** returns unqualified as only
501 /* Hack to prevent error case for wierd strings. */
507 llassertprotect (*tp == NULL || (*tp > osp));
518 void limitmessage (/*@only@*/ cstring s, fileloc loc)
520 if (mcount > context_getLimit () + 1)
526 cstring flstring = fileloc_unparse (loc);
528 lastfileloclen = cstring_length (flstring);
529 cstring_free (saveOneMessage);
530 saveOneMessage = message ("%q: %q", flstring, s);
534 static int parseerrorcount = 0;
536 void cleanupMessages ()
540 if (context_unlimitedMessages ())
546 int unprinted = mcount - context_getLimit ();
550 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
553 printError (g_warningstream, saveOneMessage);
555 saveOneMessage = cstring_undefined;
559 if (cstring_isDefined (saveOneMessage))
561 /* cstring_free (saveOneMessage); */
562 saveOneMessage = cstring_undefined;
565 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
566 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
567 mcount - context_getLimit ());
576 llgenmsg (/*@only@*/ cstring s, fileloc fl)
578 cstring flstring = fileloc_unparse (fl);
579 lastfileloclen = cstring_length (flstring);
582 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
587 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
589 cstring flstring = fileloc_unparse (fl);
592 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
597 llgenindentmsgnoloc (/*@only@*/ cstring s)
600 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
605 llgentypeerroraux (char *srcFile, int srcLine,
606 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
607 /*@only@*/ cstring s, fileloc fl)
609 cstring hint = cstring_undefined;
610 flagcode code = ocode;
611 flagcode hcode = INVALID_FLAG;
615 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
616 flagcode_unparse (ocode),
617 exprNode_unparse (e1), exprNode_unparse (e2),
618 ctype_unparse (t1), ctype_unparse (t2)));
620 DPRINTF (("Bool: %s / %s",
621 bool_unparse (ctype_isBool (t1)),
622 bool_unparse (ctype_isBool (t2))));
625 ** Set the flag using the underlying types that didn't match.
628 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
629 ut1 = ctype_baseArrayPtr (ut1);
630 ut2 = ctype_baseArrayPtr (ut2);
633 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
634 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
636 hcode = FLG_FLOATDOUBLE;
638 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
639 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
641 hcode = FLG_CHARINTLITERAL;
643 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
644 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
646 hcode = FLG_NUMLITERAL;
648 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
649 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
650 /* evs 2000-07-24: was ctype_isDirectBool */
654 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
655 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
659 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
660 || (ctype_isChar (ut1) && ctype_isChar (ut2))
661 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
663 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
665 if (ctype_isArbitraryIntegral (ctype_realType (ut1))
666 && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
668 hcode = FLG_MATCHANYINTEGRAL;
670 else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
671 && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
673 hcode = FLG_MATCHANYINTEGRAL;
677 hcode = FLG_IGNORESIGNS;
682 hcode = FLG_IGNOREQUALS;
685 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
687 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
689 hcode = FLG_MATCHANYINTEGRAL;
691 else if (ctype_match (ut2, ctype_ulint))
693 hcode = FLG_LONGUNSIGNEDINTEGRAL;
695 else if (ctype_match (ut2, ctype_lint))
697 hcode = FLG_LONGINTEGRAL;
699 else if (ctype_isInt (ut2))
701 hcode = FLG_MATCHANYINTEGRAL;
708 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
710 ctype tr = ctype_realType (ut1);
712 if (ctype_isArbitraryIntegral (tr))
714 hcode = FLG_MATCHANYINTEGRAL;
716 else if (ctype_match (ut1, ctype_ulint))
718 if (ctype_isUnsignedIntegral (tr))
720 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
722 else if (ctype_isSignedIntegral (tr))
728 hcode = FLG_LONGUNSIGNEDINTEGRAL;
731 else if (ctype_match (ut1, ctype_lint))
733 if (ctype_isSignedIntegral (tr))
735 hcode = FLG_LONGSIGNEDINTEGRAL;
737 else if (ctype_isSignedIntegral (tr))
743 hcode = FLG_LONGINTEGRAL;
746 else if (ctype_isInt (ut1))
748 hcode = FLG_MATCHANYINTEGRAL;
760 if (hcode == INVALID_FLAG)
762 DPRINTF (("[%s] %s - %s / %s",
764 bool_unparse (ctype_isEnum (ut1)),
765 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
766 bool_unparse (ctype_isInt (ut2))));
768 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
770 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
771 ctype ct = uentry_getType (ue1);
773 if (ctype_match (ct, ut2))
776 hint = message ("Underlying types match, but %s is an "
777 "abstract type that is not accessible here.",
781 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
783 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
784 ctype ct = uentry_getType (ue);
786 if (ctype_match (ct, ut1))
789 hint = message ("Underlying types match, but %s is an "
790 "abstract type that is not accessible here.",
796 ; /* Not an abstract mismatch. */
800 if (hcode == INVALID_FLAG)
802 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
803 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
807 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
808 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
812 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
813 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
815 hcode = FLG_CHARUNSIGNEDCHAR;
817 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
819 hcode = FLG_RELAXTYPES;
820 DPRINTF (("Setting relax types!"));
824 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
825 ctype_unparse (ut2)));
830 if (cstring_isDefined (hint))
832 if (!context_suppressFlagMsg (ocode, fl))
834 return llgenhinterror (code, s, hint, fl);
845 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
847 if (hcode != INVALID_FLAG && hcode != ocode)
851 if (context_flagOn (code, fl))
853 /* The flag is alreay set, something buggy in the flag code */
854 llcontbug (message ("No hint available, flag %s is already set.",
855 flagcode_unparse (code)));
864 llsuppresshint ('-', code);
867 flagcode_recordError (code);
876 xllgentypeerror (char *srcFile, int srcLine,
877 ctype t1, exprNode e1, ctype t2, exprNode e2,
878 /*@only@*/ cstring s, fileloc fl)
880 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
884 xllgenformattypeerror (char *srcFile, int srcLine,
885 ctype t1, exprNode e1, ctype t2, exprNode e2,
886 /*@only@*/ cstring s, fileloc fl)
888 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
890 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
900 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
902 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
904 llnosuppresshint (o);
905 flagcode_recordError (o);
911 flagcode_recordSuppressed (o);
917 xllgenhinterror (char *srcFile, int srcLine,
918 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
921 if (!context_suppressFlagMsg (o, fl))
923 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
925 flagcode_recordError (o);
927 if (context_getFlag (FLG_HINTS))
948 flagcode_recordSuppressed (o);
953 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
955 return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
959 llgenerroraux (char *srcFile, int srcLine,
960 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
962 if (context_inSuppressZone (fl))
968 if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
976 xllforceerror (char *srcFile, int srcLine,
977 flagcode code, /*@only@*/ cstring s, fileloc fl)
979 flagcode_recordError (code);
981 if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
990 llgenerrorreal (char *srcFile, int srcLine,
991 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
995 /* duplicate message (rescanning a header file */
997 if (!messageLog_add (context_messageLog (), fl, s))
999 DPRINTF (("Duplicate message suppressed! %s / %s",
1000 fileloc_unparse (fl), s));
1006 ** If herald has not been displayed, display it before the first message.
1011 if (iserror) context_hasError ();
1013 if (context_unlimitedMessages ())
1020 ** suppress excessive messages:
1025 char *sc = cstring_toCharsSafe (s);
1026 char *tmpmsg = strchr (sc, ':');
1034 char *savechar = tmpmsg;
1040 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1043 if (mcount == (context_getLimit () + 1))
1045 limitmessage (s, fl);
1049 if (mcount > (context_getLimit ()))
1059 cstring_free (lastmsg);
1060 lastmsg = cstring_fromCharsNew (tmpmsg);
1064 DPRINTF (("Here..."));
1066 if (context_hasAliasAnnote ())
1068 char *sc = cstring_toCharsSafe (s);
1069 char *fcolon = strchr (sc, ':');
1070 cstring a = context_getAliasAnnote ();
1075 s = message ("%q (%q)", s, a);
1082 afterColon = cstring_fromCharsNew (fcolon + 1);
1084 s = message ("%q (%q):%q", s, a, afterColon);
1088 if (context_hasMessageAnnote ())
1090 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1095 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1096 s = message ("%q (%q)", s, context_getMessageAnnote ());
1097 /*@=dependenttrans@*/
1104 afterColon = cstring_fromCharsNew (fcolon + 1);
1106 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1107 s = message ("%q (%q):%q", s,
1108 context_getMessageAnnote (), afterColon);
1109 /*@=dependenttrans@*/
1113 context_setNeednl ();
1116 if (context_showFunction ())
1118 cstring fname = fileloc_unparseFilename (g_currentloc);
1120 if (context_inIterDef ())
1122 fprintf (g_warningstream, "%s: (in iter %s)\n",
1123 cstring_toCharsSafe (fname),
1124 cstring_toCharsSafe (context_inFunctionName ()));
1126 else if (context_inIterEnd ())
1128 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1129 cstring_toCharsSafe (fname),
1130 cstring_toCharsSafe (context_inFunctionName ()));
1132 else if (context_inMacro ())
1134 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1135 cstring_toCharsSafe (context_inFunctionName ()));
1139 fprintf (g_warningstream, "%s: (in function %s)\n",
1140 cstring_toCharsSafe (fname),
1141 cstring_toCharsSafe (context_inFunctionName ()));
1144 cstring_free (fname);
1145 context_setShownFunction ();
1148 flstring = fileloc_unparse (fl);
1149 lastfileloclen = cstring_length (flstring);
1153 printError (g_warningstream, message (" %q: %q", flstring, s));
1157 printError (g_warningstream, message ("%q: %q", flstring, s));
1160 showSourceLoc (srcFile, srcLine);
1167 ** message contains no '\n'
1168 ** message fits in one line: print it
1169 ** message fits in two lines with 3-space indent after fileloc: print it
1170 ** split line with 5-space indent from left margin: print it
1175 void printMessage (FILE *stream, /*@only@*/ cstring s)
1177 printIndentMessage (stream, s, 0);
1181 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1183 static bool inbody = FALSE;
1184 int maxlen = context_getLineLen ();
1185 char *s = cstring_toCharsSafe (sc);
1188 llassertprotect (!inbody);
1196 llassertprotect (st != olds);
1198 mstring_split (&st, &t, maxlen, &indent);
1199 fprintf (stream, "%s\n", st);
1200 llassertprotect (t != s);
1202 } while (s != NULL) ;
1209 void printError (FILE *stream, /*@only@*/ cstring sc)
1211 int maxlen = context_getLineLen ();
1212 size_t nspaces = lastfileloclen + 5;
1213 int nextlen = maxlen - nspaces;
1214 size_t len = cstring_length (sc);
1216 char *s = cstring_toCharsSafe (sc);
1220 DPRINTF (("Print error: [%s]", sc));
1222 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1224 mstring_split (&s, &t, maxlen, &indent);
1226 fprintf (stream, "%s\n", s);
1230 len = mstring_length (t);
1232 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1233 && size_toInt (len) > (nextlen - 1))
1235 fprintf (stream, " %s\n", t);
1239 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1242 for (i = 0; i < size_toInt (nspaces); i++)
1247 spaces[nspaces] = '\0';
1252 mstring_split (&st, &t, nextlen, &indent);
1253 fprintf (stream, "%s%s\n", spaces, st);
1262 DPRINTF (("Here 1: [%s]", sc));
1264 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1266 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1268 if (nspaces < 1) nspaces = 1;
1270 nextlen = maxlen - nspaces;
1272 mstring_split (&s, &t, maxlen, &indent);
1274 fprintf (stream, "%s\n", s);
1278 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1281 for (i = 0; i < size_toInt (nspaces); i++)
1286 spaces[nspaces] = '\0';
1292 mstring_split (&st, &t, nextlen, &indent);
1293 fprintf (stream, "%s%s\n", spaces, st);
1302 nextlen = maxlen - nspaces;
1304 DPRINTF (("Here 2: [%s]", s));
1305 mstring_split (&s, &t, maxlen, &indent);
1306 DPRINTF (("Here 3: [%s] [%s]", s, t));
1308 fprintf (stream, "%s\n", s);
1312 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1315 for (i = 0; i < nspaces; i++)
1320 spaces[nspaces] = '\0';
1325 DPRINTF (("Loop: [%s]", t));
1326 mstring_split (&st, &t, nextlen, &indent);
1327 DPRINTF (("Split: [%s] [%s]", st, t));
1328 fprintf (stream, "%s%s\n", spaces, st);
1329 DPRINTF (("Next..."));
1342 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1345 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1346 fileloc_unparse (g_currentloc), s));
1347 showSourceLoc (srcFile, srcLine);
1354 lclfatalbug (char *msg)
1357 printError (g_errorstream,
1358 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1365 checkParseError (void)
1367 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1369 llfatalerror (message ("%q: Cannot recover from parse error.",
1370 fileloc_unparse (g_currentloc)));
1374 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1377 static int numbugs = 0;
1378 static bool inbug = FALSE;
1382 cstring temps = fileloc_unparseRaw (file, line);
1384 fprintf (g_errorstream,
1385 "%s: Recursive bug detected: %s\n",
1386 cstring_toCharsSafe (temps),
1387 cstring_toCharsSafe (s));
1388 cstring_free (temps);
1397 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1399 llfatalerror (message ("%q: Cannot recover from parse error.",
1400 fileloc_unparse (g_currentloc)));
1403 (void) fflush (g_warningstream);
1405 printError (g_errorstream,
1406 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1407 fileloc_unparse (g_currentloc),
1408 fileloc_unparseRaw (file, line),
1411 /* printCodePoint (); no longer useful */
1416 ** This is confusing, and hardly ever useful.
1420 perror ("Possible system error diagnostic: ");
1431 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1434 (message ("%q: Cannot recover from last bug. "
1435 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1436 fileloc_unparse (g_currentloc)));
1439 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1440 fileloc_free (lastbug);
1441 lastbug = fileloc_copy (g_currentloc);
1447 lclbug (/*@only@*/ cstring s)
1450 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1453 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1458 xllfatalerror (char *srcFile, int srcLine, cstring s)
1461 printError (g_errorstream, s);
1462 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1463 showSourceLoc (srcFile, srcLine);
1468 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1471 (void) fflush (g_warningstream);
1472 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1473 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1474 showSourceLoc (srcFile, srcLine);
1475 (void) fflush (g_warningstream);
1482 return (lclerrors > 0);
1486 lclHadNewError (void)
1488 static int lastcall = 0;
1490 if (lclerrors > lastcall)
1492 lastcall = lclerrors;
1502 lclNumberErrors (void)
1508 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1512 if (ltoken_getCode (t) != NOTTOKEN)
1514 cstring loc = ltoken_unparseLoc (t);
1515 lastfileloclen = cstring_length (loc);
1517 printError (g_warningstream, message ("%q: %q", loc, msg));
1518 showSourceLoc (srcFile, srcLine);
1522 printError (g_warningstream, msg);
1523 showSourceLoc (srcFile, srcLine);
1528 lclplainerror (/*@only@*/ cstring msg)
1531 printError (g_warningstream, msg);
1535 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1537 if (ltoken_getCode (t) != NOTTOKEN)
1539 cstring loc = ltoken_unparseLoc (t);
1540 lastfileloclen = cstring_length (loc);
1541 printError (g_errorstream, message ("%q: %q", loc, msg));
1545 printError (g_errorstream, msg);
1548 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1553 lclplainfatalerror (/*@only@*/ cstring msg)
1555 (void) fflush (g_warningstream);
1556 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1561 lclRedeclarationError (ltoken id)
1563 cstring s = ltoken_getRawString (id);
1566 if (usymtab_existsEither (s))
1568 uentry le = usymtab_lookupEither (s);
1570 lclerror (id, message ("Respecification of %s", s));
1571 llgenindentmsg (message ("Previous specification of %q",
1572 uentry_getName (le)),
1573 uentry_whereSpecified (le));
1577 lclerror (id, message ("Identifier redeclared: %s", s));
1581 void genppllerror (flagcode code, /*@only@*/ cstring s)
1583 if (context_inSuppressZone (g_currentloc))
1589 if (context_getFlag (code))
1591 if (!context_isInCommandLine ())
1593 displayScanClose ();
1598 if (code != FLG_PREPROC)
1600 llsuppresshint ('-', code);
1603 if (!context_isInCommandLine ())
1605 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1615 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1616 /*@only@*/ cstring hint)
1618 if (context_inSuppressZone (g_currentloc))
1621 cstring_free (hint);
1625 if (context_getFlag (code))
1628 context_clearPreprocessing ();
1631 context_setPreprocessing ();
1637 cstring_free (hint);
1642 void ppllerror (/*@only@*/ cstring s)
1644 genppllerror (FLG_PREPROC, s);
1647 void pplldiagmsg (cstring s)
1649 if (!context_isInCommandLine ())
1651 displayScanClose ();
1653 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1661 void loadllmsg (cstring s)
1663 displayScanClose ();
1665 displayScanOpen (cstring_makeLiteral ("< ."));
1668 static void llreportparseerror (/*@only@*/ cstring s)
1670 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1676 llerror (FLG_SYNTAX, s);
1678 fileloc_free (lastparseerror);
1679 lastparseerror = fileloc_copy (g_currentloc);
1683 bool xcppoptgenerror (char *srcFile, int srcLine,
1685 /*@only@*/ cstring s,
1689 fileloc loc = cppReader_getLoc (pfile);
1691 if (context_flagOn (o, loc))
1693 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1695 cppReader_printContainingFiles (pfile);
1709 bool xlloptgenerror (char *srcFile, int srcLine,
1710 flagcode o, /*@only@*/ cstring s, fileloc loc)
1712 DPRINTF (("xllopt: %s", s));
1714 if (llrealerror (srcFile, srcLine, s, loc))
1716 DPRINTF (("Here we are!"));
1717 llsuppresshint ('-', o);
1719 flagcode_recordError (o);
1724 DPRINTF (("Suppressed!"));
1725 flagcode_recordSuppressed (o);
1730 bool xoptgenerror2 (char *srcFile, int srcLine,
1731 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1733 if (context_suppressFlagMsg (f1, loc))
1735 flagcode_recordSuppressed (f1);
1740 if (context_suppressFlagMsg (f2, loc))
1742 flagcode_recordSuppressed (f2);
1747 if (llrealerror (srcFile, srcLine, s, loc))
1749 llsuppresshint2 ('-', f1, f2);
1750 flagcode_recordError (f2);
1756 flagcode_recordSuppressed (f2);
1764 bool xoptgenerror2n (char *srcFile, int srcLine,
1765 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1768 if (context_suppressFlagMsg (f1, loc))
1770 flagcode_recordSuppressed (f1);
1775 if (context_suppressNotFlagMsg (f2, loc))
1777 flagcode_recordSuppressed (f2);
1782 if (llrealerror (srcFile, srcLine, s, loc))
1784 llsuppresshint ('+', f2);
1785 flagcode_recordError (f2);
1790 flagcode_recordSuppressed (f2);
1796 bool xllnoptgenerror (char *srcFile, int srcLine,
1797 flagcode o, /*@only@*/ cstring s, fileloc loc)
1799 if (llrealerror (srcFile, srcLine, s, loc))
1801 llsuppresshint ('+', o);
1802 flagcode_recordError (o);
1807 flagcode_recordSuppressed (o);
1811 void xllparseerror (char *srcFile, int srcLine, cstring s)
1813 if (context_getFlag (FLG_TRYTORECOVER))
1817 if (parseerrorcount > GIVEUPPARSE)
1819 if (cstring_isDefined (s))
1821 xllfatalerror (srcFile, srcLine,
1822 message ("%q: Parse Error: %q. "
1823 "Too many errors, giving up.",
1824 fileloc_unparse (g_currentloc), s));
1828 xllfatalerror (srcFile, srcLine,
1829 message ("%q: Parse Error. Too many errors, giving up.",
1830 fileloc_unparse (g_currentloc)));
1835 if (cstring_isDefined (s))
1837 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1839 showSourceLoc (srcFile, srcLine);
1843 llreportparseerror (message ("Parse Error. Attempting to continue."));
1844 showSourceLoc (srcFile, srcLine);
1852 if (cstring_isDefined (s))
1854 msg = message ("Parse Error: %q.", s);
1858 msg = message ("Parse Error.");
1863 message ("%q: %s (For help on parse errors, "
1864 "see splint -help parseerrors.)",
1865 fileloc_unparse (g_currentloc), msg));
1869 bool xfsgenerror (char *srcFile, int srcLine,
1870 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1872 if (flagSpec_isOn (fs, fl))
1874 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1876 llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1877 flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1882 flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1888 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1894 bool doCheck (bool x, cstring pred, cstring file, int line)
1897 llbug (message ("%q: Check Failed: %s",
1898 fileloc_unparseRaw (file, line),
1905 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1910 #ifndef HAVE_STRERROR
1913 result = strerror (errnum);
1916 /* VAXCRTL's strerror() takes an optional second argument, which only
1917 matters when the first argument is EVMSERR. However, it's simplest
1918 just to pass it unconditionally. `vaxc$errno' is declared in
1919 <errno.h>, and maintained by the library in parallel with `errno'.
1920 We assume that caller's `errnum' either matches the last setting of
1921 `errno' by the library or else does not have the value `EVMSERR'. */
1923 result = strerror (errnum, vaxc$errno);
1928 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1931 return cstring_fromChars (result);
1934 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1939 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1940 fileloc_unparse (g_currentloc),
1941 fileloc_unparseRaw (file, line),
1953 (void) fflush (g_warningstream);
1954 (void) fflush (g_messagestream);
1957 static bool s_scanOpen = FALSE;
1959 void displayScan (cstring msg)
1963 displayScanClose ();
1966 llassert (!s_scanOpen);
1968 if (context_getFlag (FLG_SHOWSCAN))
1971 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
1972 (void) fflush (g_messagestream);
1978 void displayScanOpen (cstring msg)
1982 displayScanClose ();
1985 llassert (!s_scanOpen);
1988 if (context_getFlag (FLG_SHOWSCAN))
1990 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
1991 (void) fflush (g_messagestream);
1997 void displayScanContinue (/*@temp@*/ cstring msg)
1999 if (context_getFlag (FLG_SHOWSCAN))
2003 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2004 (void) fflush (g_messagestream);
2009 ** Don't call bug recursively
2012 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2017 void displayScanClose (void)
2021 if (context_getFlag (FLG_SHOWSCAN))
2023 fprintf (g_messagestream, " >\n");
2024 (void) fflush (g_messagestream);
2030 ** Don't call bug recursively
2033 fprintf (stderr, "*** Bug: scan close scan not open\n");