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 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 (flagcode p_code,
53 char *p_srcFile, int p_srcLine,
54 /*@only@*/ cstring p_s,
55 /*@temp@*/ cstring p_addtext,
56 fileloc p_fl, bool p_iserror, bool p_indent)
57 /*@modifies g_warningstream@*/ ;
58 static bool llgenerroraux (flagcode p_code, char *p_srcFile, int p_srcLine,
59 /*@only@*/ cstring p_s,
60 /*@temp@*/ cstring p_addtext,
61 fileloc p_fl, bool p_iserror, bool p_indent)
62 /*@modifies g_warningstream@*/ ;
64 static void generateCSV (flagcode p_code, cstring p_s, cstring p_addtext, fileloc p_fl)
65 /*@modifies g_csvstream@*/ ;
67 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
68 /*@globals lastfileloclen @*/
69 /*@modifies *p_stream@*/ ;
70 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
71 /*@modifies *p_stream@*/ ;
73 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
75 static void showSourceLoc (char *srcFile, int srcLine)
76 /*@modifies g_warningstream@*/
78 if (context_getFlag (FLG_SHOWSOURCELOC)) {
79 llgenhint (message ("%s:%d: Source code error generation point.",
80 cstring_fromChars (srcFile), srcLine));
85 static /*@null@*/ char *
86 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
95 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
98 /* don't exit (EXIT_FAILURE); */
101 static bool s_needsPrepare = TRUE;
103 void prepareMessage ()
105 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
108 if ((context_isPreprocessing () || context_loadingLibrary ())
110 && context_getFlag (FLG_SHOWSCAN))
114 s_needsPrepare = FALSE;
120 void closeMessage (void)
122 if (context_isPreprocessing ()
123 && context_getFlag (FLG_SHOWSCAN))
126 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
127 llassertprotect (!s_needsPrepare);
128 s_needsPrepare = TRUE;
137 llmsg (/*@only@*/ cstring s)
139 context_setNeednl ();
141 printMessage (g_messagestream, s);
146 lldiagmsg (/*@only@*/ cstring s)
148 static bool inmsg = FALSE;
152 fprintf (g_errorstream,
153 "Recursive message call detected: %s\n",
154 cstring_toCharsSafe (s));
160 context_setNeednl ();
162 printMessage (g_messagestream, s);
169 llmsgplain (/*@only@*/ cstring s)
171 context_setNeednl ();
173 printMessage (g_messagestream, s);
177 void llerror_flagWarning (cstring s)
179 if (context_getFlag (FLG_WARNFLAGS))
181 llgenmsg (s, g_currentloc);
190 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
192 int indent = context_getIndentSpaces () - 1;
194 if (indent < 0) indent = 0;
196 context_setNeednl ();
197 printIndentMessage (g_warningstream, s, indent);
203 if (context_getFlag (FLG_HINTS) &&
204 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
215 llshowhint (flagcode f)
217 if (context_getFlag (FLG_HINTS))
219 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
221 cstring desc = flagcodeHint (f);
223 if (cstring_isDefined (desc))
225 llgenhint (cstring_copy (desc));
232 llsuppresshint2 (char c, flagcode f1, flagcode f2)
235 if (context_getFlag (FLG_HINTS))
237 if ((flagcode_numReported (f1) == 0
238 || flagcode_numReported (f2) == 0)
239 || context_getFlag (FLG_FORCEHINTS))
241 cstring desc = flagcodeHint (f1);
242 context_setNeednl ();
245 if (cstring_isUndefined (desc))
247 desc = flagcodeHint (f2);
250 if (flagcode_isNamePrefixFlag (f1))
255 if (flagcode_isNamePrefixFlag (f2))
262 if (cstring_isDefined (desc))
264 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
266 flagcode_unparse (f1)));
270 llgenhint (message ("(Use %h%s to inhibit warning)",
271 c, flagcode_unparse (f1)));
276 if (cstring_isDefined (desc))
278 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
280 flagcode_unparse (f1),
282 flagcode_unparse (f2)));
286 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
287 flagcode_unparse (f1),
288 c, flagcode_unparse (f2)));
296 llsuppresshint (char c, flagcode f)
298 if (context_getFlag (FLG_HINTS))
300 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
302 cstring desc = flagcodeHint (f);
303 context_setNeednl ();
306 if (flagcode_isNamePrefixFlag (f))
311 if (cstring_isDefined (desc))
313 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
314 flagcode_unparse (f)));
318 llgenhint (message ("(Use %h%s to inhibit warning)", c,
319 flagcode_unparse (f)));
326 llnosuppresshint (flagcode f)
328 if (context_getFlag (FLG_FORCEHINTS))
330 cstring desc = flagcodeHint (f);
331 context_setNeednl ();
334 if (cstring_isDefined (desc))
336 printError (g_warningstream, message (" %s", desc));
341 /*@constant int MAXSEARCH; @*/
342 # define MAXSEARCH 20
344 /*@constant int MINLINE; @*/
347 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
350 mstring_split (/*@returned@*/ char **sp,
351 /*@out@*/ nd_charp *tp,
352 int maxline, /*@in@*/ int *indentchars)
361 DPRINTF (("Split: %s / %d", *sp, maxline));
363 if (maxline < MINLINELEN)
365 maxline = MINLINELEN;
368 if (*indentchars > 0)
370 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
374 nl = strchr (s, '\n');
379 ** if there is a newline in first maxline characters, split there
380 ** if line len is <= maxline, return no split
381 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
382 ** split there unless the ' ' is followed by a '}', then
384 ** of the ';' is inside quotation marks
385 ** if there is a space or tab in last maxsearch characters, split there
386 ** else, split at maxline
388 ** special code: slash [1-9] after a newline means indent the rest <n> chars
392 if ((nl != NULL) && ((nl - s) < maxline))
399 llassertprotect (*tp == NULL || (*tp > osp));
403 if (*t >= '\1' && *t <= '\7')
405 *indentchars += (int) (*t - '\1') + 1;
412 else if (size_toInt (strlen (s)) < maxline)
414 llassertprotect (*tp == NULL || (*tp > osp));
421 char *lcolon, *lsemi, *lcomma;
430 lcolon = strrchr (s, ':');
431 lsemi = strrchr (s, ';');
432 lcomma = strrchr (s, ',');
436 splitat = maxcp (lcolon, lsemi);
438 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
439 && *(splitat) != '\0'
440 && *(splitat + 1) == ' '
441 && (*(splitat + 2) != '}'
442 && *(splitat + 2) != ','
443 && (*(splitat + 2) != '\0')))
445 *(splitat + 1) = '\0';
448 llassertprotect (*tp == NULL || (*tp > osp));
452 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
456 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
457 && *(splitat) != '\0'
458 && *(splitat + 1) == ' '
459 && (*(splitat + 2) != '}'
460 && (*(splitat + 2) != '\0')))
462 *(splitat + 1) = '\0';
465 llassertprotect (*tp == NULL || (*tp > osp));
470 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
476 if (*t != ' ' && *t != '\t')
478 llassertprotect (maxline > 0);
479 t = mstring_copy (s + maxline);
480 *(s + maxline) = '\0';
485 llassertprotect (*tp == NULL || (*tp > osp));
489 mstring_markFree (t);
491 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
500 if (*t == '\0') return;
503 ** returns unqualified as only
509 /* Hack to prevent error case for wierd strings. */
515 llassertprotect (*tp == NULL || (*tp > osp));
526 void limitmessage (/*@only@*/ cstring s, fileloc loc)
528 if (mcount > context_getLimit () + 1)
534 cstring flstring = fileloc_unparse (loc);
536 lastfileloclen = cstring_length (flstring);
537 cstring_free (saveOneMessage);
538 saveOneMessage = message ("%q: %q", flstring, s);
542 static int parseerrorcount = 0;
544 void cleanupMessages ()
548 if (context_unlimitedMessages ())
554 int unprinted = mcount - context_getLimit ();
558 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
561 printError (g_warningstream, saveOneMessage);
563 saveOneMessage = cstring_undefined;
567 if (cstring_isDefined (saveOneMessage))
569 /* cstring_free (saveOneMessage); */
570 saveOneMessage = cstring_undefined;
573 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
574 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
575 mcount - context_getLimit ());
584 llgenmsg (/*@only@*/ cstring s, fileloc fl)
586 cstring flstring = fileloc_unparse (fl);
587 lastfileloclen = cstring_length (flstring);
590 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
595 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
597 cstring flstring = fileloc_unparse (fl);
598 int indentspaces = context_getLocIndentSpaces ();
601 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s),
608 llgenindentmsgnoloc (/*@only@*/ cstring s)
611 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
616 llgentypeerroraux (char *srcFile, int srcLine,
617 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
618 /*@only@*/ cstring s, fileloc fl)
620 cstring hint = cstring_undefined;
621 flagcode code = ocode;
622 flagcode hcode = INVALID_FLAG;
626 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
627 flagcode_unparse (ocode),
628 exprNode_unparse (e1), exprNode_unparse (e2),
629 ctype_unparse (t1), ctype_unparse (t2)));
631 DPRINTF (("Bool: %s / %s",
632 bool_unparse (ctype_isBool (t1)),
633 bool_unparse (ctype_isBool (t2))));
636 ** Set the flag using the underlying types that didn't match.
639 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
640 ut1 = ctype_baseArrayPtr (ut1);
641 ut2 = ctype_baseArrayPtr (ut2);
644 if (ctype_isRealNumAbstract (ut1) && exprNode_isNumLiteral (e2))
646 hcode = FLG_NUMABSTRACTLIT;
648 else if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
649 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
651 hcode = FLG_FLOATDOUBLE;
653 else if ((exprNode_isCharLiteral (e1) && ctype_isInt (ut2))
654 || (exprNode_isCharLiteral (e2) && ctype_isInt (ut1)))
656 hcode = FLG_CHARINTLITERAL;
658 else if ((exprNode_isNumLiteral (e1) && ctype_isReal (ut2))
659 || (exprNode_isNumLiteral (e2) && ctype_isReal (ut1)))
661 hcode = FLG_NUMLITERAL;
663 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
664 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
665 /* evs 2000-07-24: was ctype_isDirectBool */
669 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
670 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
674 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
675 || (ctype_isChar (ut1) && ctype_isChar (ut2))
676 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
678 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
680 if (ctype_isArbitraryIntegral (ctype_realType (ut1))
681 && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
683 hcode = FLG_MATCHANYINTEGRAL;
685 else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
686 && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
688 hcode = FLG_MATCHANYINTEGRAL;
692 hcode = FLG_IGNORESIGNS;
697 hcode = FLG_IGNOREQUALS;
700 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
702 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
704 hcode = FLG_MATCHANYINTEGRAL;
706 else if (ctype_match (ut2, ctype_ulint))
708 hcode = FLG_LONGUNSIGNEDINTEGRAL;
710 else if (ctype_match (ut2, ctype_lint))
712 hcode = FLG_LONGINTEGRAL;
714 else if (ctype_isInt (ut2))
716 hcode = FLG_MATCHANYINTEGRAL;
723 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
725 ctype tr = ctype_realType (ut1);
727 if (ctype_isArbitraryIntegral (tr))
729 hcode = FLG_MATCHANYINTEGRAL;
731 else if (ctype_match (ut1, ctype_ulint))
733 if (ctype_isUnsignedIntegral (tr))
735 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
737 else if (ctype_isSignedIntegral (tr))
743 hcode = FLG_LONGUNSIGNEDINTEGRAL;
746 else if (ctype_match (ut1, ctype_lint))
748 if (ctype_isSignedIntegral (tr))
750 hcode = FLG_LONGSIGNEDINTEGRAL;
752 else if (ctype_isSignedIntegral (tr))
758 hcode = FLG_LONGINTEGRAL;
761 else if (ctype_isInt (ut1))
763 hcode = FLG_MATCHANYINTEGRAL;
775 if (hcode == INVALID_FLAG)
777 DPRINTF (("[%s] %s - %s / %s",
779 bool_unparse (ctype_isEnum (ut1)),
780 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
781 bool_unparse (ctype_isInt (ut2))));
783 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
785 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
786 ctype ct = uentry_getType (ue1);
788 if (ctype_match (ct, ut2))
791 hint = message ("Underlying types match, but %s is an "
792 "abstract type that is not accessible here.",
796 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
798 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
799 ctype ct = uentry_getType (ue);
801 if (ctype_match (ct, ut1))
803 if (ctype_isNumAbstract (ut2))
805 if (exprNode_isNumLiteral (e1))
807 code = FLG_NUMABSTRACTLIT;
808 hint = message ("Underlying types match, but %s is a "
809 "numabstract type that is not accessible here. "
810 "(Use +numabstractlit to allow numeric literals "
811 "to be used as numabstract type values.)",
816 code = FLG_NUMABSTRACT;
817 hint = message ("Underlying types match, but %s is a "
818 "numabstract type that is not accessible here.",
825 hint = message ("Underlying types match, but %s is an "
826 "abstract type that is not accessible here.",
833 ; /* Not an abstract mismatch. */
837 if (hcode == INVALID_FLAG)
839 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
840 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
844 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
845 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
849 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
850 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
852 hcode = FLG_CHARUNSIGNEDCHAR;
854 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
856 hcode = FLG_RELAXTYPES;
857 DPRINTF (("Setting relax types!"));
861 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
862 ctype_unparse (ut2)));
867 if (cstring_isDefined (hint))
869 if (!context_suppressFlagMsg (ocode, fl))
871 return xllgenhinterror (srcFile, srcLine, code, s, hint, fl);
882 if (hcode != INVALID_FLAG && hcode != ocode)
887 if (llgenerroraux (ocode, srcFile, srcLine, s,
888 flagcodeHint (code), fl, TRUE, FALSE))
892 if (context_flagOn (code, fl))
894 /* The flag is alreay set, something buggy in the flag code */
895 llcontbug (message ("No hint available, flag %s is already set.",
896 flagcode_unparse (code)));
905 llsuppresshint ('-', code);
908 flagcode_recordError (code);
917 xllgentypeerror (char *srcFile, int srcLine,
918 ctype t1, exprNode e1, ctype t2, exprNode e2,
919 /*@only@*/ cstring s, fileloc fl)
921 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
925 xllgenformattypeerror (char *srcFile, int srcLine,
926 ctype t1, exprNode e1, ctype t2, exprNode e2,
927 /*@only@*/ cstring s, fileloc fl)
929 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
932 && ctype_isNumAbstract (t2))
934 if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT, fl))
936 return llgentypeerroraux (srcFile, srcLine, FLG_NUMABSTRACTPRINT, t1, e1, t2, e2, s, fl);
945 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
956 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
958 if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
960 llnosuppresshint (o);
961 flagcode_recordError (o);
967 flagcode_recordSuppressed (o);
973 xllgenhinterror (char *srcFile, int srcLine,
974 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
977 if (!context_suppressFlagMsg (o, fl))
979 if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
981 flagcode_recordError (o);
983 if (context_getFlag (FLG_HINTS))
1000 cstring_free (hint);
1004 flagcode_recordSuppressed (o);
1009 llrealerror (flagcode code, char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
1011 return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
1015 llgenerroraux (flagcode code,
1016 char *srcFile, int srcLine,
1017 /*@only@*/ cstring s,
1019 fileloc fl, bool iserror, bool indent)
1021 if (context_inSuppressZone (fl))
1027 if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1035 xllforceerror (char *srcFile, int srcLine,
1036 flagcode code, /*@only@*/ cstring s, fileloc fl)
1038 flagcode_recordError (code);
1040 if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1048 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1051 if (g_csvstream != NULL) {
1052 /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1053 fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1054 context_numErrors (),
1055 (int) code, /* flag code */
1056 cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1057 flagcode_priority (code), /* priority */
1058 cstring_toCharsSafe (fileloc_outputFilename (fl)),
1059 fileloc_lineno (fl),
1060 fileloc_column (fl),
1061 cstring_toCharsSafe (s));
1063 if (cstring_isDefined (addtext)) {
1064 fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1066 fprintf (g_csvstream, "\n");
1072 llgenerrorreal (flagcode code, char *srcFile, int srcLine,
1073 /*@only@*/ cstring s,
1075 fileloc fl, bool iserror, bool indent)
1079 /* duplicate message (rescanning a header file */
1081 if (!messageLog_add (context_messageLog (), fl, s))
1083 DPRINTF (("Duplicate message suppressed! %s / %s",
1084 fileloc_unparse (fl), s));
1090 ** If herald has not been displayed, display it before the first message.
1095 if (iserror) context_hasError ();
1097 if (context_unlimitedMessages ())
1104 ** suppress excessive messages:
1109 char *sc = cstring_toCharsSafe (s);
1110 char *tmpmsg = strchr (sc, ':');
1118 char *savechar = tmpmsg;
1124 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1127 if (mcount == (context_getLimit () + 1))
1129 limitmessage (s, fl);
1133 if (mcount > (context_getLimit ()))
1143 cstring_free (lastmsg);
1144 lastmsg = cstring_fromCharsNew (tmpmsg);
1148 DPRINTF (("Here..."));
1150 if (context_hasAliasAnnote ())
1152 char *sc = cstring_toCharsSafe (s);
1153 char *fcolon = strchr (sc, ':');
1154 cstring a = context_getAliasAnnote ();
1159 s = message ("%q (%q)", s, a);
1166 afterColon = cstring_fromCharsNew (fcolon + 1);
1168 s = message ("%q (%q):%q", s, a, afterColon);
1172 if (context_hasMessageAnnote ())
1174 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1179 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1180 s = message ("%q (%q)", s, context_getMessageAnnote ());
1181 /*@=dependenttrans@*/
1188 afterColon = cstring_fromCharsNew (fcolon + 1);
1190 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1191 s = message ("%q (%q):%q", s,
1192 context_getMessageAnnote (), afterColon);
1193 /*@=dependenttrans@*/
1197 context_setNeednl ();
1200 if (context_showFunction ())
1202 cstring fname = fileloc_unparseFilename (g_currentloc);
1204 if (context_inIterDef ())
1206 fprintf (g_warningstream, "%s: (in iter %s)\n",
1207 cstring_toCharsSafe (fname),
1208 cstring_toCharsSafe (context_inFunctionName ()));
1210 else if (context_inIterEnd ())
1212 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1213 cstring_toCharsSafe (fname),
1214 cstring_toCharsSafe (context_inFunctionName ()));
1216 else if (context_inMacro ())
1218 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1219 cstring_toCharsSafe (context_inFunctionName ()));
1223 fprintf (g_warningstream, "%s: (in function %s)\n",
1224 cstring_toCharsSafe (fname),
1225 cstring_toCharsSafe (context_inFunctionName ()));
1228 cstring_free (fname);
1229 context_setShownFunction ();
1232 flstring = fileloc_unparse (fl);
1233 lastfileloclen = cstring_length (flstring);
1235 generateCSV (code, s, addtext, fl);
1239 printError (g_warningstream, message (" %q: %q", flstring, s));
1243 printError (g_warningstream, message ("%q: %q", flstring, s));
1246 showSourceLoc (srcFile, srcLine);
1254 ** message contains no '\n'
1255 ** message fits in one line: print it
1256 ** message fits in two lines with 3-space indent after fileloc: print it
1257 ** split line with 5-space indent from left margin: print it
1262 void printMessage (FILE *stream, /*@only@*/ cstring s)
1264 printIndentMessage (stream, s, 0);
1268 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1270 static bool inbody = FALSE;
1271 int maxlen = context_getLineLen ();
1272 char *s = cstring_toCharsSafe (sc);
1275 llassertprotect (!inbody);
1283 llassertprotect (st != olds);
1285 mstring_split (&st, &t, maxlen, &indent);
1286 fprintf (stream, "%s\n", st);
1287 llassertprotect (t != s);
1289 } while (s != NULL) ;
1296 void printError (FILE *stream, /*@only@*/ cstring sc)
1298 int maxlen = context_getLineLen ();
1299 size_t nspaces = lastfileloclen + 5;
1300 int nextlen = maxlen - size_toInt (nspaces);
1301 size_t len = cstring_length (sc);
1303 char *s = cstring_toCharsSafe (sc);
1307 DPRINTF (("Print error: [%s]", sc));
1309 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1311 mstring_split (&s, &t, maxlen, &indent);
1313 fprintf (stream, "%s\n", s);
1317 len = mstring_length (t);
1319 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1320 && size_toInt (len) > (nextlen - 1))
1322 fprintf (stream, " %s\n", t);
1326 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1329 for (i = 0; i < size_toInt (nspaces); i++)
1334 spaces[nspaces] = '\0';
1339 mstring_split (&st, &t, nextlen, &indent);
1340 fprintf (stream, "%s%s\n", spaces, st);
1349 DPRINTF (("Here 1: [%s]", sc));
1351 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1353 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1355 if (nspaces < 1) nspaces = 1;
1357 nextlen = size_toInt (maxlen - nspaces);
1359 mstring_split (&s, &t, maxlen, &indent);
1361 fprintf (stream, "%s\n", s);
1365 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1368 for (i = 0; i < size_toInt (nspaces); i++)
1373 spaces[nspaces] = '\0';
1379 mstring_split (&st, &t, nextlen, &indent);
1380 fprintf (stream, "%s%s\n", spaces, st);
1389 nextlen = size_toInt (maxlen - nspaces);
1391 DPRINTF (("Here 2: [%s]", s));
1392 mstring_split (&s, &t, maxlen, &indent);
1393 DPRINTF (("Here 3: [%s] [%s]", s, t));
1395 fprintf (stream, "%s\n", s);
1399 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1402 for (i = 0; i < nspaces; i++)
1407 spaces[nspaces] = '\0';
1412 DPRINTF (("Loop: [%s]", t));
1413 mstring_split (&st, &t, nextlen, &indent);
1414 DPRINTF (("Split: [%s] [%s]", st, t));
1415 fprintf (stream, "%s%s\n", spaces, st);
1416 DPRINTF (("Next..."));
1429 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1432 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1433 fileloc_unparse (g_currentloc), s));
1434 showSourceLoc (srcFile, srcLine);
1441 lclfatalbug (char *msg)
1444 printError (g_errorstream,
1445 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1452 checkParseError (void)
1454 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1456 llfatalerror (message ("%q: Cannot recover from parse error.",
1457 fileloc_unparse (g_currentloc)));
1461 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1464 static int numbugs = 0;
1465 static bool inbug = FALSE;
1469 cstring temps = fileloc_unparseRaw (file, line);
1471 fprintf (g_errorstream,
1472 "%s: Recursive bug detected: %s\n",
1473 cstring_toCharsSafe (temps),
1474 cstring_toCharsSafe (s));
1475 cstring_free (temps);
1484 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1486 llfatalerror (message ("%q: Cannot recover from parse error.",
1487 fileloc_unparse (g_currentloc)));
1490 (void) fflush (g_warningstream);
1492 printError (g_errorstream,
1493 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1494 fileloc_unparse (g_currentloc),
1495 fileloc_unparseRaw (file, line),
1498 /* printCodePoint (); no longer useful */
1503 ** This is confusing, and hardly ever useful.
1507 perror ("Possible system error diagnostic: ");
1518 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1521 (message ("%q: Cannot recover from last bug. "
1522 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1523 fileloc_unparse (g_currentloc)));
1526 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1527 fileloc_free (lastbug);
1528 lastbug = fileloc_copy (g_currentloc);
1534 lclbug (/*@only@*/ cstring s)
1537 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1540 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1545 xllfatalerror (char *srcFile, int srcLine, cstring s)
1548 printError (g_errorstream, s);
1549 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1550 showSourceLoc (srcFile, srcLine);
1555 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1558 (void) fflush (g_warningstream);
1559 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1560 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1561 showSourceLoc (srcFile, srcLine);
1562 (void) fflush (g_warningstream);
1569 return (lclerrors > 0);
1573 lclHadNewError (void)
1575 static int lastcall = 0;
1577 if (lclerrors > lastcall)
1579 lastcall = lclerrors;
1589 lclNumberErrors (void)
1595 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1599 if (ltoken_getCode (t) != NOTTOKEN)
1601 cstring loc = ltoken_unparseLoc (t);
1602 lastfileloclen = cstring_length (loc);
1604 printError (g_warningstream, message ("%q: %q", loc, msg));
1605 showSourceLoc (srcFile, srcLine);
1609 printError (g_warningstream, msg);
1610 showSourceLoc (srcFile, srcLine);
1615 lclplainerror (/*@only@*/ cstring msg)
1618 printError (g_warningstream, msg);
1622 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1624 if (ltoken_getCode (t) != NOTTOKEN)
1626 cstring loc = ltoken_unparseLoc (t);
1627 lastfileloclen = cstring_length (loc);
1628 printError (g_errorstream, message ("%q: %q", loc, msg));
1632 printError (g_errorstream, msg);
1635 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1640 lclplainfatalerror (/*@only@*/ cstring msg)
1642 (void) fflush (g_warningstream);
1643 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1648 lclRedeclarationError (ltoken id)
1650 cstring s = ltoken_getRawString (id);
1653 if (usymtab_existsEither (s))
1655 uentry le = usymtab_lookupEither (s);
1657 lclerror (id, message ("Respecification of %s", s));
1658 llgenindentmsg (message ("Previous specification of %q",
1659 uentry_getName (le)),
1660 uentry_whereSpecified (le));
1664 lclerror (id, message ("Identifier redeclared: %s", s));
1668 void genppllerror (flagcode code, /*@only@*/ cstring s)
1670 if (context_inSuppressZone (g_currentloc))
1676 if (context_getFlag (code))
1678 if (!context_isInCommandLine ())
1680 displayScanClose ();
1685 if (code != FLG_PREPROC)
1687 llsuppresshint ('-', code);
1690 if (!context_isInCommandLine ())
1692 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1702 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1703 /*@only@*/ cstring hint)
1705 if (context_inSuppressZone (g_currentloc))
1708 cstring_free (hint);
1712 if (context_getFlag (code))
1714 generateCSV (code, s, hint, g_currentloc);
1716 context_clearPreprocessing ();
1719 context_setPreprocessing ();
1725 cstring_free (hint);
1730 void ppllerror (/*@only@*/ cstring s)
1732 genppllerror (FLG_PREPROC, s);
1735 void pplldiagmsg (cstring s)
1737 if (!context_isInCommandLine ())
1739 displayScanClose ();
1741 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1749 void loadllmsg (cstring s)
1751 displayScanClose ();
1753 displayScanOpen (cstring_makeLiteral ("< ."));
1756 static void llreportparseerror (/*@only@*/ cstring s)
1758 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1764 llerror (FLG_SYNTAX, s);
1766 fileloc_free (lastparseerror);
1767 lastparseerror = fileloc_copy (g_currentloc);
1771 bool xcppoptgenerror (char *srcFile, int srcLine,
1773 /*@only@*/ cstring s,
1777 fileloc loc = cppReader_getLoc (pfile);
1779 if (context_flagOn (o, loc))
1781 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1783 cppReader_printContainingFiles (pfile);
1797 bool xlloptgenerror (char *srcFile, int srcLine,
1798 flagcode o, /*@only@*/ cstring s, fileloc loc)
1800 DPRINTF (("xllopt: %s", s));
1802 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1804 DPRINTF (("Here we are!"));
1805 llsuppresshint ('-', o);
1807 flagcode_recordError (o);
1812 DPRINTF (("Suppressed!"));
1813 flagcode_recordSuppressed (o);
1818 bool xoptgenerror2 (char *srcFile, int srcLine,
1819 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1821 if (context_suppressFlagMsg (f1, loc))
1823 flagcode_recordSuppressed (f1);
1828 if (context_suppressFlagMsg (f2, loc))
1830 flagcode_recordSuppressed (f2);
1835 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1837 llsuppresshint2 ('-', f1, f2);
1838 flagcode_recordError (f2);
1844 flagcode_recordSuppressed (f2);
1852 bool xoptgenerror2n (char *srcFile, int srcLine,
1853 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1856 if (context_suppressFlagMsg (f1, loc))
1858 flagcode_recordSuppressed (f1);
1863 if (context_suppressNotFlagMsg (f2, loc))
1865 flagcode_recordSuppressed (f2);
1870 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1872 llsuppresshint ('+', f2);
1873 flagcode_recordError (f2);
1878 flagcode_recordSuppressed (f2);
1884 bool xllnoptgenerror (char *srcFile, int srcLine,
1885 flagcode o, /*@only@*/ cstring s, fileloc loc)
1887 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1889 llsuppresshint ('+', o);
1890 flagcode_recordError (o);
1895 flagcode_recordSuppressed (o);
1899 void xllparseerror (char *srcFile, int srcLine, cstring s)
1901 if (context_getFlag (FLG_TRYTORECOVER))
1905 if (parseerrorcount > GIVEUPPARSE)
1907 if (cstring_isDefined (s))
1909 xllfatalerror (srcFile, srcLine,
1910 message ("%q: Parse Error: %q. "
1911 "Too many errors, giving up.",
1912 fileloc_unparse (g_currentloc), s));
1916 xllfatalerror (srcFile, srcLine,
1917 message ("%q: Parse Error. Too many errors, giving up.",
1918 fileloc_unparse (g_currentloc)));
1923 if (cstring_isDefined (s))
1925 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1927 showSourceLoc (srcFile, srcLine);
1931 llreportparseerror (message ("Parse Error. Attempting to continue."));
1932 showSourceLoc (srcFile, srcLine);
1940 if (cstring_isDefined (s))
1942 msg = message ("Parse Error: %q.", s);
1946 msg = message ("Parse Error.");
1951 message ("%q: %s (For help on parse errors, "
1952 "see splint -help parseerrors.)",
1953 fileloc_unparse (g_currentloc), msg));
1957 bool xfsgenerror (char *srcFile, int srcLine,
1958 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1960 if (flagSpec_isOn (fs, fl))
1962 flagcode firston = flagSpec_getFirstOn (fs, fl);
1964 if (llgenerroraux (firston, srcFile, srcLine, s,
1965 flagcodeHint (firston),
1968 llsuppresshint ('-', firston);
1969 flagcode_recordError (firston);
1974 flagcode_recordSuppressed (firston);
1980 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1986 bool doCheck (bool x, cstring pred, cstring file, int line)
1989 llbug (message ("%q: Check Failed: %s",
1990 fileloc_unparseRaw (file, line),
1997 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
2002 #ifndef HAVE_STRERROR
2005 result = strerror (errnum);
2008 /* VAXCRTL's strerror() takes an optional second argument, which only
2009 matters when the first argument is EVMSERR. However, it's simplest
2010 just to pass it unconditionally. `vaxc$errno' is declared in
2011 <errno.h>, and maintained by the library in parallel with `errno'.
2012 We assume that caller's `errnum' either matches the last setting of
2013 `errno' by the library or else does not have the value `EVMSERR'. */
2015 result = strerror (errnum, vaxc$errno);
2020 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2023 return cstring_fromChars (result);
2026 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2031 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2032 fileloc_unparse (g_currentloc),
2033 fileloc_unparseRaw (file, line),
2045 (void) fflush (g_warningstream);
2046 (void) fflush (g_messagestream);
2049 static bool s_scanOpen = FALSE;
2051 void displayScan (cstring msg)
2055 displayScanClose ();
2058 llassert (!s_scanOpen);
2060 if (context_getFlag (FLG_SHOWSCAN))
2063 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2064 (void) fflush (g_messagestream);
2070 void displayScanOpen (cstring msg)
2074 displayScanClose ();
2077 llassert (!s_scanOpen);
2080 if (context_getFlag (FLG_SHOWSCAN))
2082 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2083 (void) fflush (g_messagestream);
2089 void displayScanContinue (/*@temp@*/ cstring msg)
2091 if (context_getFlag (FLG_SHOWSCAN))
2095 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2096 (void) fflush (g_messagestream);
2101 ** Don't call bug recursively
2104 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2109 void displayScanClose (void)
2113 if (context_getFlag (FLG_SHOWSCAN))
2115 fprintf (g_messagestream, " >\n");
2116 (void) fflush (g_messagestream);
2122 ** Don't call bug recursively
2125 fprintf (stderr, "*** Bug: scan close scan not open\n");