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
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 bool s_scanOpen = FALSE;
46 static int s_lclerrors = 0;
47 static size_t s_lastfileloclen = 10;
48 static /*@only@*/ cstring s_lastmsg = cstring_undefined;
49 static int s_mcount = 0;
50 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
51 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
52 static /*@only@*/ fileloc lastbug = fileloc_undefined;
53 static bool llgenerrorreal (flagcode p_code,
54 char *p_srcFile, int p_srcLine,
55 /*@only@*/ cstring p_s,
56 /*@temp@*/ cstring p_addtext,
57 fileloc p_fl, bool p_iserror, bool p_indent)
58 /*@modifies g_warningstream@*/ ;
59 static bool llgenerroraux (flagcode p_code, char *p_srcFile, int p_srcLine,
60 /*@only@*/ cstring p_s,
61 /*@temp@*/ cstring p_addtext,
62 fileloc p_fl, bool p_iserror, bool p_indent)
63 /*@modifies g_warningstream@*/ ;
65 static void generateCSV (flagcode p_code, cstring p_s, cstring p_addtext, fileloc p_fl)
66 /*@modifies g_csvstream@*/ ;
68 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
69 /*@globals s_lastfileloclen @*/
70 /*@modifies *p_stream@*/ ;
71 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
72 /*@modifies *p_stream@*/ ;
74 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
76 static void showSourceLoc (char *srcFile, int srcLine)
77 /*@modifies g_warningstream@*/
79 if (context_getFlag (FLG_SHOWSOURCELOC)) {
80 llgenhint (message ("%s:%d: Source code error generation point.",
81 cstring_fromChars (srcFile), srcLine));
86 static /*@null@*/ char *
87 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
96 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
99 /* don't exit (EXIT_FAILURE); */
102 static bool s_needsPrepare = TRUE;
104 void prepareMessage ()
106 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
109 if ((context_isPreprocessing () || context_loadingLibrary ())
111 && context_getFlag (FLG_SHOWSCAN))
115 s_needsPrepare = FALSE;
121 void closeMessage (void)
123 if (context_isPreprocessing ()
124 && context_getFlag (FLG_SHOWSCAN))
127 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
128 llassertprotect (!s_needsPrepare);
129 s_needsPrepare = TRUE;
138 llmsg (/*@only@*/ cstring s)
140 context_setNeednl ();
142 printMessage (g_messagestream, s);
147 lldiagmsg (/*@only@*/ cstring s)
149 static bool inmsg = FALSE;
153 fprintf (g_errorstream,
154 "Recursive message call detected: %s\n",
155 cstring_toCharsSafe (s));
161 context_setNeednl ();
163 printMessage (g_messagestream, s);
170 llmsgplain (/*@only@*/ cstring s)
172 context_setNeednl ();
174 printMessage (g_messagestream, s);
178 void llerror_flagWarning (cstring s)
180 if (context_getFlag (FLG_WARNFLAGS))
182 llgenmsg (s, g_currentloc);
191 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
193 int indent = context_getIndentSpaces () - 1;
195 if (indent < 0) indent = 0;
197 context_setNeednl ();
198 printIndentMessage (g_warningstream, s, indent);
204 if (context_getFlag (FLG_HINTS) &&
205 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
216 llshowhint (flagcode f)
218 if (context_getFlag (FLG_HINTS))
220 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
222 cstring desc = flagcodeHint (f);
224 if (cstring_isDefined (desc))
226 llgenhint (cstring_copy (desc));
233 llsuppresshint2 (char c, flagcode f1, flagcode f2)
236 if (context_getFlag (FLG_HINTS))
238 if ((flagcode_numReported (f1) == 0
239 || flagcode_numReported (f2) == 0)
240 || context_getFlag (FLG_FORCEHINTS))
242 cstring desc = flagcodeHint (f1);
243 context_setNeednl ();
244 s_lastfileloclen = 8;
246 if (cstring_isUndefined (desc))
248 desc = flagcodeHint (f2);
251 if (flagcode_isNamePrefixFlag (f1))
256 if (flagcode_isNamePrefixFlag (f2))
263 if (cstring_isDefined (desc))
265 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
267 flagcode_unparse (f1)));
271 llgenhint (message ("(Use %h%s to inhibit warning)",
272 c, flagcode_unparse (f1)));
277 if (cstring_isDefined (desc))
279 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
281 flagcode_unparse (f1),
283 flagcode_unparse (f2)));
287 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
288 flagcode_unparse (f1),
289 c, flagcode_unparse (f2)));
297 llsuppresshint (char c, flagcode f)
299 if (context_getFlag (FLG_HINTS))
301 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
303 cstring desc = flagcodeHint (f);
304 context_setNeednl ();
305 s_lastfileloclen = 8;
307 if (flagcode_isNamePrefixFlag (f))
312 if (cstring_isDefined (desc))
314 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
315 flagcode_unparse (f)));
319 llgenhint (message ("(Use %h%s to inhibit warning)", c,
320 flagcode_unparse (f)));
327 llnosuppresshint (flagcode f)
329 if (context_getFlag (FLG_FORCEHINTS))
331 cstring desc = flagcodeHint (f);
332 context_setNeednl ();
333 s_lastfileloclen = 8;
335 if (cstring_isDefined (desc))
337 printError (g_warningstream, message (" %s", desc));
342 /*@constant int MAXSEARCH; @*/
343 # define MAXSEARCH 20
345 /*@constant int MINLINE; @*/
348 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
353 ** Divides a string into lines of up to maxline characters.
355 ** Initial string: *sp
357 ** Output split: *sp / *tp
362 mstring_split (/*@returned@*/ char **sp,
363 /*@out@*/ nd_charp *tp,
364 int maxline, /*@in@*/ int *indentchars)
373 DPRINTF (("Split: %s / %d", *sp, maxline));
375 if (maxline < MINLINELEN)
377 maxline = MINLINELEN;
380 if (*indentchars > 0)
382 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
389 ** if there is a newline in first maxline characters, split there
390 ** if line len is <= maxline, return no split
391 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
392 ** split there unless the ' ' is followed by a '}', then
394 ** of the ';' is inside quotation marks
395 ** if there is a space or tab in last maxsearch characters, split there
396 ** else, split at maxline
398 ** special code: slash [1-9] after a newline means indent the rest <n> chars
402 nl = strchr (s, '\n');
404 if ((nl != NULL) && ((nl - s) < maxline))
411 llassertprotect (*tp == NULL || (*tp > osp));
415 if (*t >= '\1' && *t <= '\7')
417 *indentchars += (int) (*t - '\1') + 1;
424 else if (size_toInt (strlen (s)) < maxline)
426 llassertprotect (*tp == NULL);
433 char *lcolon, *lsemi, *lcomma;
442 lcolon = strrchr (s, ':');
443 lsemi = strrchr (s, ';');
444 lcomma = strrchr (s, ',');
448 splitat = maxcp (lcolon, lsemi);
450 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
451 && *(splitat) != '\0'
452 && *(splitat + 1) == ' '
453 && (*(splitat + 2) != '}'
454 && *(splitat + 2) != ','
455 && (*(splitat + 2) != '\0')))
457 *(splitat + 1) = '\0';
460 llassertprotect (*tp == NULL || (*tp > osp));
464 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
468 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
469 && *(splitat) != '\0'
470 && *(splitat + 1) == ' '
471 && (*(splitat + 2) != '}'
472 && (*(splitat + 2) != '\0')))
474 *(splitat + 1) = '\0';
477 llassertprotect (*tp == NULL || (*tp > osp));
483 ** Search for any breaking point (at least 4 letters past s)
486 while (*t != ' ' && *t != '\t' && i < MAXSEARCH && t > (s + 4))
492 if (*t != ' ' && *t != '\t')
494 llassertprotect (maxline > 0);
495 t = mstring_copy (s + maxline);
496 *(s + maxline) = '\0';
501 llassertprotect (*tp == NULL || (*tp > osp));
505 mstring_markFree (t);
507 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
516 if (*t == '\0') return;
519 ** returns unqualified as only
524 llassert (*sp != *tp);
533 void limitmessage (/*@only@*/ cstring s, fileloc loc)
535 if (s_mcount > context_getLimit () + 1)
541 cstring flstring = fileloc_unparse (loc);
543 s_lastfileloclen = cstring_length (flstring);
544 cstring_free (saveOneMessage);
545 saveOneMessage = message ("%q: %q", flstring, s);
549 static int parseerrorcount = 0;
551 void cleanupMessages ()
555 if (context_unlimitedMessages ())
561 int unprinted = s_mcount - context_getLimit ();
565 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
568 printError (g_warningstream, saveOneMessage);
570 saveOneMessage = cstring_undefined;
574 if (cstring_isDefined (saveOneMessage))
576 /* cstring_free (saveOneMessage); */
577 saveOneMessage = cstring_undefined;
580 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
581 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
582 s_mcount - context_getLimit ());
591 llgenmsg (/*@only@*/ cstring s, fileloc fl)
593 cstring flstring = fileloc_unparse (fl);
594 s_lastfileloclen = cstring_length (flstring);
597 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
602 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
604 cstring flstring = fileloc_unparse (fl);
605 int indentspaces = context_getLocIndentSpaces ();
608 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s),
615 llgenindentmsgnoloc (/*@only@*/ cstring s)
618 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
623 llgentypeerroraux (char *srcFile, int srcLine,
624 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
625 /*@only@*/ cstring s, fileloc fl)
627 cstring hint = cstring_undefined;
628 flagcode code = ocode;
629 flagcode hcode = INVALID_FLAG;
633 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
634 flagcode_unparse (ocode),
635 exprNode_unparse (e1), exprNode_unparse (e2),
636 ctype_unparse (t1), ctype_unparse (t2)));
638 DPRINTF (("Bool: %s / %s",
639 bool_unparse (ctype_isBool (t1)),
640 bool_unparse (ctype_isBool (t2))));
643 ** Set the flag using the underlying types that didn't match.
646 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
647 ut1 = ctype_baseArrayPtr (ut1);
648 ut2 = ctype_baseArrayPtr (ut2);
651 if (ctype_isRealNumAbstract (ut1) && exprNode_isNumLiteral (e2))
653 hcode = FLG_NUMABSTRACTLIT;
655 else if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
656 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
658 hcode = FLG_FLOATDOUBLE;
660 else if ((exprNode_isCharLiteral (e1) && ctype_isInt (ut2))
661 || (exprNode_isCharLiteral (e2) && ctype_isInt (ut1)))
663 hcode = FLG_CHARINTLITERAL;
665 else if ((exprNode_isNumLiteral (e1) && ctype_isReal (ut2))
666 || (exprNode_isNumLiteral (e2) && ctype_isReal (ut1)))
668 hcode = FLG_NUMLITERAL;
670 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
671 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
672 /* evs 2000-07-24: was ctype_isDirectBool */
676 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
677 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
681 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
682 || (ctype_isChar (ut1) && ctype_isChar (ut2))
683 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
685 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
687 if (ctype_isArbitraryIntegral (ctype_realType (ut1))
688 && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
690 hcode = FLG_MATCHANYINTEGRAL;
692 else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
693 && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
695 hcode = FLG_MATCHANYINTEGRAL;
699 hcode = FLG_IGNORESIGNS;
704 hcode = FLG_IGNOREQUALS;
707 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
709 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
711 hcode = FLG_MATCHANYINTEGRAL;
713 else if (ctype_match (ut2, ctype_ulint))
715 hcode = FLG_LONGUNSIGNEDINTEGRAL;
717 else if (ctype_match (ut2, ctype_lint))
719 hcode = FLG_LONGINTEGRAL;
721 else if (ctype_isInt (ut2))
723 hcode = FLG_MATCHANYINTEGRAL;
730 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
732 ctype tr = ctype_realType (ut1);
734 if (ctype_isArbitraryIntegral (tr))
736 hcode = FLG_MATCHANYINTEGRAL;
738 else if (ctype_match (ut1, ctype_ulint))
740 if (ctype_isUnsignedIntegral (tr))
742 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
744 else if (ctype_isSignedIntegral (tr))
750 hcode = FLG_LONGUNSIGNEDINTEGRAL;
753 else if (ctype_match (ut1, ctype_lint))
755 if (ctype_isSignedIntegral (tr))
757 hcode = FLG_LONGSIGNEDINTEGRAL;
759 else if (ctype_isSignedIntegral (tr))
765 hcode = FLG_LONGINTEGRAL;
768 else if (ctype_isInt (ut1))
770 hcode = FLG_MATCHANYINTEGRAL;
782 if (hcode == INVALID_FLAG)
784 DPRINTF (("[%s] %s - %s / %s",
786 bool_unparse (ctype_isEnum (ut1)),
787 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
788 bool_unparse (ctype_isInt (ut2))));
790 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
792 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
793 ctype ct = uentry_getType (ue1);
795 if (ctype_match (ct, ut2))
798 hint = message ("Underlying types match, but %s is an "
799 "abstract type that is not accessible here.",
803 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
805 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
806 ctype ct = uentry_getType (ue);
808 if (ctype_match (ct, ut1))
810 if (ctype_isNumAbstract (ut2))
812 if (exprNode_isNumLiteral (e1))
814 code = FLG_NUMABSTRACTLIT;
815 hint = message ("Underlying types match, but %s is a "
816 "numabstract type that is not accessible here. "
817 "(Use +numabstractlit to allow numeric literals "
818 "to be used as numabstract type values.)",
823 code = FLG_NUMABSTRACT;
824 hint = message ("Underlying types match, but %s is a "
825 "numabstract type that is not accessible here.",
832 hint = message ("Underlying types match, but %s is an "
833 "abstract type that is not accessible here.",
840 ; /* Not an abstract mismatch. */
844 if (hcode == INVALID_FLAG)
846 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
847 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
851 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
852 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
856 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
857 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
859 hcode = FLG_CHARUNSIGNEDCHAR;
861 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
863 hcode = FLG_RELAXTYPES;
864 DPRINTF (("Setting relax types!"));
868 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
869 ctype_unparse (ut2)));
874 if (cstring_isDefined (hint))
876 if (!context_suppressFlagMsg (ocode, fl))
878 return xllgenhinterror (srcFile, srcLine, code, s, hint, fl);
889 if (hcode != INVALID_FLAG && hcode != ocode)
894 if (llgenerroraux (ocode, srcFile, srcLine, s,
895 flagcodeHint (code), fl, TRUE, FALSE))
899 if (context_flagOn (code, fl))
901 /* The flag is alreay set, something buggy in the flag code */
902 llcontbug (message ("No hint available, flag %s is already set.",
903 flagcode_unparse (code)));
912 llsuppresshint ('-', code);
915 flagcode_recordError (code);
924 xllgentypeerror (char *srcFile, int srcLine,
925 ctype t1, exprNode e1, ctype t2, exprNode e2,
926 /*@only@*/ cstring s, fileloc fl)
928 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
932 xllgenformattypeerror (char *srcFile, int srcLine,
933 ctype t1, exprNode e1, ctype t2, exprNode e2,
934 /*@only@*/ cstring s, fileloc fl)
936 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
939 && ctype_isNumAbstract (t2))
941 if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT, fl))
943 return llgentypeerroraux (srcFile, srcLine, FLG_NUMABSTRACTPRINT, t1, e1, t2, e2, s, fl);
952 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
963 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
965 if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
967 llnosuppresshint (o);
968 flagcode_recordError (o);
974 flagcode_recordSuppressed (o);
980 xllgenhinterror (char *srcFile, int srcLine,
981 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
984 if (!context_suppressFlagMsg (o, fl))
986 if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
988 flagcode_recordError (o);
990 if (context_getFlag (FLG_HINTS))
1003 cstring_free (hint);
1007 cstring_free (hint);
1011 flagcode_recordSuppressed (o);
1016 llrealerror (flagcode code, char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
1018 return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
1022 llgenerroraux (flagcode code,
1023 char *srcFile, int srcLine,
1024 /*@only@*/ cstring s,
1026 fileloc fl, bool iserror, bool indent)
1028 if (context_inSuppressZone (fl))
1034 if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1042 xllforceerror (char *srcFile, int srcLine,
1043 flagcode code, /*@only@*/ cstring s, fileloc fl)
1045 flagcode_recordError (code);
1047 if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1055 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1058 if (g_csvstream != NULL) {
1059 /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1060 fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1061 context_numErrors (),
1062 (int) code, /* flag code */
1063 cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1064 flagcode_priority (code), /* priority */
1065 cstring_toCharsSafe (fileloc_outputFilename (fl)),
1066 fileloc_lineno (fl),
1067 fileloc_column (fl),
1068 cstring_toCharsSafe (s));
1070 if (cstring_isDefined (addtext)) {
1071 fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1073 fprintf (g_csvstream, "\n");
1079 llgenerrorreal (flagcode code, char *srcFile, int srcLine,
1080 /*@only@*/ cstring s,
1082 fileloc fl, bool iserror, bool indent)
1086 /* duplicate message (rescanning a header file */
1088 if (!messageLog_add (context_messageLog (), fl, s))
1090 DPRINTF (("Duplicate message suppressed! %s / %s",
1091 fileloc_unparse (fl), s));
1097 ** If herald has not been displayed, display it before the first message.
1102 if (iserror) context_hasError ();
1104 if (context_unlimitedMessages ())
1111 ** suppress excessive messages:
1116 char *sc = cstring_toCharsSafe (s);
1117 char *tmpmsg = strchr (sc, ':');
1125 char *savechar = tmpmsg;
1131 if (cstring_equal (s_lastmsg, cstring_fromChars (tmpmsg)))
1134 if (s_mcount == (context_getLimit () + 1))
1136 limitmessage (s, fl);
1140 if (s_mcount > (context_getLimit ()))
1150 cstring_free (s_lastmsg);
1151 s_lastmsg = cstring_fromCharsNew (tmpmsg);
1155 DPRINTF (("Here..."));
1157 if (context_hasAliasAnnote ())
1159 char *sc = cstring_toCharsSafe (s);
1160 char *fcolon = strchr (sc, ':');
1161 cstring a = context_getAliasAnnote ();
1166 s = message ("%q (%q)", s, a);
1173 afterColon = cstring_fromCharsNew (fcolon + 1);
1175 s = message ("%q (%q):%q", s, a, afterColon);
1179 if (context_hasMessageAnnote ())
1181 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1186 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1187 s = message ("%q (%q)", s, context_getMessageAnnote ());
1188 /*@=dependenttrans@*/
1195 afterColon = cstring_fromCharsNew (fcolon + 1);
1197 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1198 s = message ("%q (%q):%q", s,
1199 context_getMessageAnnote (), afterColon);
1200 /*@=dependenttrans@*/
1204 context_setNeednl ();
1207 if (context_showFunction ())
1209 cstring fname = fileloc_unparseFilename (g_currentloc);
1211 if (context_inIterDef ())
1213 fprintf (g_warningstream, "%s: (in iter %s)\n",
1214 cstring_toCharsSafe (fname),
1215 cstring_toCharsSafe (context_inFunctionName ()));
1217 else if (context_inIterEnd ())
1219 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1220 cstring_toCharsSafe (fname),
1221 cstring_toCharsSafe (context_inFunctionName ()));
1223 else if (context_inMacro ())
1225 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1226 cstring_toCharsSafe (context_inFunctionName ()));
1230 fprintf (g_warningstream, "%s: (in function %s)\n",
1231 cstring_toCharsSafe (fname),
1232 cstring_toCharsSafe (context_inFunctionName ()));
1235 cstring_free (fname);
1236 context_setShownFunction ();
1239 flstring = fileloc_unparse (fl);
1240 s_lastfileloclen = cstring_length (flstring);
1242 generateCSV (code, s, addtext, fl);
1246 printError (g_warningstream, message (" %q: %q", flstring, s));
1250 printError (g_warningstream, message ("%q: %q", flstring, s));
1253 showSourceLoc (srcFile, srcLine);
1261 ** message contains no '\n'
1262 ** message fits in one line: print it
1263 ** message fits in two lines with 3-space indent after fileloc: print it
1264 ** split line with 5-space indent from left margin: print it
1269 void printMessage (FILE *stream, /*@only@*/ cstring s)
1271 printIndentMessage (stream, s, 0);
1275 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1277 static bool inbody = FALSE;
1278 int maxlen = context_getLineLen ();
1279 char *s = cstring_toCharsSafe (sc);
1282 llassertprotect (!inbody);
1290 llassertprotect (st != olds);
1292 mstring_split (&st, &t, maxlen, &indent);
1293 fprintf (stream, "%s\n", st);
1294 llassertprotect (t != s);
1296 } while (s != NULL) ;
1303 void printError (FILE *stream, /*@only@*/ cstring sc)
1305 int maxlen = context_getLineLen ();
1306 size_t nspaces = s_lastfileloclen + 5;
1307 int nextlen = maxlen - size_toInt (nspaces);
1308 size_t len = cstring_length (sc);
1310 char *s = cstring_toCharsSafe (sc);
1314 DPRINTF (("Print error: [%s]", sc));
1316 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1318 mstring_split (&s, &t, maxlen, &indent);
1320 fprintf (stream, "%s\n", s);
1324 len = mstring_length (t);
1326 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1327 && size_toInt (len) > (nextlen - 1))
1329 fprintf (stream, " %s\n", t);
1333 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1336 for (i = 0; i < size_toInt (nspaces); i++)
1341 spaces[nspaces] = '\0';
1346 mstring_split (&st, &t, nextlen, &indent);
1347 fprintf (stream, "%s%s\n", spaces, st);
1356 DPRINTF (("Here 1: [%s]", sc));
1358 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1360 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1362 if (nspaces < 1) nspaces = 1;
1364 nextlen = size_toInt (maxlen - nspaces);
1366 mstring_split (&s, &t, maxlen, &indent);
1368 fprintf (stream, "%s\n", s);
1372 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1375 for (i = 0; i < size_toInt (nspaces); i++)
1380 spaces[nspaces] = '\0';
1386 mstring_split (&st, &t, nextlen, &indent);
1387 fprintf (stream, "%s%s\n", spaces, st);
1396 nextlen = size_toInt (maxlen - nspaces);
1398 DPRINTF (("Here 2: [%s]", s));
1399 mstring_split (&s, &t, maxlen, &indent);
1400 DPRINTF (("Here 3: [%s] [%s]", s, t));
1402 fprintf (stream, "%s\n", s);
1406 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1409 for (i = 0; i < nspaces; i++)
1414 spaces[nspaces] = '\0';
1419 DPRINTF (("Loop: [%s]", t));
1420 mstring_split (&st, &t, nextlen, &indent);
1421 DPRINTF (("Split: [%s] [%s]", st, t));
1422 fprintf (stream, "%s%s\n", spaces, st);
1423 DPRINTF (("Next..."));
1436 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1439 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1440 fileloc_unparse (g_currentloc), s));
1441 showSourceLoc (srcFile, srcLine);
1448 lclfatalbug (char *msg)
1451 printError (g_errorstream,
1452 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1459 checkParseError (void)
1461 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1463 llfatalerror (message ("%q: Cannot recover from parse error.",
1464 fileloc_unparse (g_currentloc)));
1468 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1471 static int numbugs = 0;
1472 static bool inbug = FALSE;
1476 cstring temps = fileloc_unparseRaw (file, line);
1478 fprintf (g_errorstream,
1479 "%s: Recursive bug detected: %s\n",
1480 cstring_toCharsSafe (temps),
1481 cstring_toCharsSafe (s));
1482 cstring_free (temps);
1491 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1493 llfatalerror (message ("%q: Cannot recover from parse error.",
1494 fileloc_unparse (g_currentloc)));
1497 (void) fflush (g_warningstream);
1499 printError (g_errorstream,
1500 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1501 fileloc_unparse (g_currentloc),
1502 fileloc_unparseRaw (file, line),
1505 /* printCodePoint (); no longer useful */
1510 ** This is confusing, and hardly ever useful.
1514 perror ("Possible system error diagnostic: ");
1525 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1528 (message ("%q: Cannot recover from last bug. "
1529 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1530 fileloc_unparse (g_currentloc)));
1533 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1534 fileloc_free (lastbug);
1535 lastbug = fileloc_copy (g_currentloc);
1541 lclbug (/*@only@*/ cstring s)
1544 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1547 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1552 xllfatalerror (char *srcFile, int srcLine, cstring s)
1555 printError (g_errorstream, s);
1556 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1557 showSourceLoc (srcFile, srcLine);
1562 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1565 (void) fflush (g_warningstream);
1566 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1567 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1568 showSourceLoc (srcFile, srcLine);
1569 (void) fflush (g_warningstream);
1576 return (s_lclerrors > 0);
1580 lclHadNewError (void)
1582 static int lastcall = 0;
1584 if (s_lclerrors > lastcall)
1586 lastcall = s_lclerrors;
1596 lclNumberErrors (void)
1598 return (s_lclerrors);
1602 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1606 if (ltoken_getCode (t) != NOTTOKEN)
1608 cstring loc = ltoken_unparseLoc (t);
1609 s_lastfileloclen = cstring_length (loc);
1611 printError (g_warningstream, message ("%q: %q", loc, msg));
1612 showSourceLoc (srcFile, srcLine);
1616 printError (g_warningstream, msg);
1617 showSourceLoc (srcFile, srcLine);
1622 lclplainerror (/*@only@*/ cstring msg)
1625 printError (g_warningstream, msg);
1629 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1631 if (ltoken_getCode (t) != NOTTOKEN)
1633 cstring loc = ltoken_unparseLoc (t);
1634 s_lastfileloclen = cstring_length (loc);
1635 printError (g_errorstream, message ("%q: %q", loc, msg));
1639 printError (g_errorstream, msg);
1642 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1647 lclplainfatalerror (/*@only@*/ cstring msg)
1649 (void) fflush (g_warningstream);
1650 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1655 lclRedeclarationError (ltoken id)
1657 cstring s = ltoken_getRawString (id);
1660 if (usymtab_existsEither (s))
1662 uentry le = usymtab_lookupEither (s);
1664 lclerror (id, message ("Respecification of %s", s));
1665 llgenindentmsg (message ("Previous specification of %q",
1666 uentry_getName (le)),
1667 uentry_whereSpecified (le));
1671 lclerror (id, message ("Identifier redeclared: %s", s));
1675 void genppllerror (flagcode code, /*@only@*/ cstring s)
1677 if (context_inSuppressZone (g_currentloc))
1683 if (context_getFlag (code))
1687 displayScanClose ();
1692 if (code != FLG_PREPROC)
1694 llsuppresshint ('-', code);
1697 if (!context_isInCommandLine ())
1699 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1709 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1710 /*@only@*/ cstring hint)
1712 if (context_inSuppressZone (g_currentloc))
1715 cstring_free (hint);
1719 if (context_getFlag (code))
1721 generateCSV (code, s, hint, g_currentloc);
1723 context_clearPreprocessing ();
1726 context_setPreprocessing ();
1732 cstring_free (hint);
1737 void ppllerror (/*@only@*/ cstring s)
1739 genppllerror (FLG_PREPROC, s);
1742 void pplldiagmsg (cstring s)
1744 if (!context_isInCommandLine ())
1748 displayScanClose ();
1752 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1760 void loadllmsg (cstring s)
1762 displayScanClose ();
1764 displayScanOpen (cstring_makeLiteral ("< ."));
1767 static void llreportparseerror (/*@only@*/ cstring s)
1769 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1775 llerror (FLG_SYNTAX, s);
1777 fileloc_free (lastparseerror);
1778 lastparseerror = fileloc_copy (g_currentloc);
1782 bool xcppoptgenerror (char *srcFile, int srcLine,
1784 /*@only@*/ cstring s,
1788 fileloc loc = cppReader_getLoc (pfile);
1790 if (context_flagOn (o, loc))
1792 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1794 cppReader_printContainingFiles (pfile);
1808 bool xlloptgenerror (char *srcFile, int srcLine,
1809 flagcode o, /*@only@*/ cstring s, fileloc loc)
1811 DPRINTF (("xllopt: %s", s));
1813 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1815 DPRINTF (("Here we are!"));
1816 llsuppresshint ('-', o);
1818 flagcode_recordError (o);
1823 DPRINTF (("Suppressed!"));
1824 flagcode_recordSuppressed (o);
1829 bool xoptgenerror2 (char *srcFile, int srcLine,
1830 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1832 if (context_suppressFlagMsg (f1, loc))
1834 flagcode_recordSuppressed (f1);
1839 if (context_suppressFlagMsg (f2, loc))
1841 flagcode_recordSuppressed (f2);
1846 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1848 llsuppresshint2 ('-', f1, f2);
1849 flagcode_recordError (f2);
1855 flagcode_recordSuppressed (f2);
1863 bool xoptgenerror2n (char *srcFile, int srcLine,
1864 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1867 if (context_suppressFlagMsg (f1, loc))
1869 flagcode_recordSuppressed (f1);
1874 if (context_suppressNotFlagMsg (f2, loc))
1876 flagcode_recordSuppressed (f2);
1881 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1883 llsuppresshint ('+', f2);
1884 flagcode_recordError (f2);
1889 flagcode_recordSuppressed (f2);
1895 bool xllnoptgenerror (char *srcFile, int srcLine,
1896 flagcode o, /*@only@*/ cstring s, fileloc loc)
1898 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1900 llsuppresshint ('+', o);
1901 flagcode_recordError (o);
1906 flagcode_recordSuppressed (o);
1910 void xllparseerror (char *srcFile, int srcLine, cstring s)
1912 if (context_getFlag (FLG_TRYTORECOVER))
1916 if (parseerrorcount > GIVEUPPARSE)
1918 if (cstring_isDefined (s))
1920 xllfatalerror (srcFile, srcLine,
1921 message ("%q: Parse Error: %q. "
1922 "Too many errors, giving up.",
1923 fileloc_unparse (g_currentloc), s));
1927 xllfatalerror (srcFile, srcLine,
1928 message ("%q: Parse Error. Too many errors, giving up.",
1929 fileloc_unparse (g_currentloc)));
1934 if (cstring_isDefined (s))
1936 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1938 showSourceLoc (srcFile, srcLine);
1942 llreportparseerror (message ("Parse Error. Attempting to continue."));
1943 showSourceLoc (srcFile, srcLine);
1951 if (cstring_isDefined (s))
1953 msg = message ("Parse Error: %q.", s);
1957 msg = message ("Parse Error.");
1962 message ("%q: %s (For help on parse errors, "
1963 "see splint -help parseerrors.)",
1964 fileloc_unparse (g_currentloc), msg));
1968 bool xfsgenerror (char *srcFile, int srcLine,
1969 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1971 if (flagSpec_isOn (fs, fl))
1973 flagcode firston = flagSpec_getFirstOn (fs, fl);
1975 if (llgenerroraux (firston, srcFile, srcLine, s,
1976 flagcodeHint (firston),
1979 llsuppresshint ('-', firston);
1980 flagcode_recordError (firston);
1985 flagcode_recordSuppressed (firston);
1991 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1997 bool doCheck (bool x, cstring pred, cstring file, int line)
2000 llbug (message ("%q: Check Failed: %s",
2001 fileloc_unparseRaw (file, line),
2008 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
2013 #ifndef HAVE_STRERROR
2016 result = strerror (errnum);
2019 /* VAXCRTL's strerror() takes an optional second argument, which only
2020 matters when the first argument is EVMSERR. However, it's simplest
2021 just to pass it unconditionally. `vaxc$errno' is declared in
2022 <errno.h>, and maintained by the library in parallel with `errno'.
2023 We assume that caller's `errnum' either matches the last setting of
2024 `errno' by the library or else does not have the value `EVMSERR'. */
2026 result = strerror (errnum, vaxc$errno);
2031 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2034 return cstring_fromChars (result);
2037 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2042 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2043 fileloc_unparse (g_currentloc),
2044 fileloc_unparseRaw (file, line),
2056 (void) fflush (g_warningstream);
2057 (void) fflush (g_messagestream);
2060 void displayScan (cstring msg)
2064 displayScanClose ();
2067 llassert (!s_scanOpen);
2069 if (context_getFlag (FLG_SHOWSCAN))
2072 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2073 (void) fflush (g_messagestream);
2079 void displayScanOpen (cstring msg)
2083 displayScanClose ();
2086 llassert (!s_scanOpen);
2089 if (context_getFlag (FLG_SHOWSCAN))
2091 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2092 (void) fflush (g_messagestream);
2098 void displayScanContinue (/*@temp@*/ cstring msg)
2100 if (context_getFlag (FLG_SHOWSCAN))
2104 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2105 (void) fflush (g_messagestream);
2110 ** Don't call bug recursively
2113 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2118 void displayScanClose (void)
2122 if (context_getFlag (FLG_SHOWSCAN))
2124 fprintf (g_messagestream, " >\n");
2125 (void) fflush (g_messagestream);
2131 ** Don't call bug recursively
2134 fprintf (stderr, "*** Bug: scan close scan not open\n");