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@*/ ;
46 static int lclerrors = 0;
49 static size_t lastfileloclen = 10;
50 static /*@only@*/ cstring lastmsg = cstring_undefined;
51 static int mcount = 0;
52 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
53 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
54 static /*@only@*/ fileloc lastbug = fileloc_undefined;
55 static bool llgenerrorreal (char *p_srcFile, int p_srcLine,
56 /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
57 /*@modifies g_warningstream@*/ ;
58 static bool llgenerroraux (char *p_srcFile, int p_srcLine,
59 /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
60 /*@modifies g_warningstream@*/ ;
62 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
63 /*@globals lastfileloclen @*/
64 /*@modifies *p_stream@*/ ;
65 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
66 /*@modifies *p_stream@*/ ;
68 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
70 static void showSourceLoc (char *srcFile, int srcLine)
71 /*@modifies g_warningstream@*/
73 if (context_getFlag (FLG_SHOWSOURCELOC)) {
74 llgenhint (message ("%s:%d: Source code error generation point.",
75 cstring_fromChars (srcFile), srcLine));
80 static /*@null@*/ char *
81 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
90 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
93 /* don't exit (EXIT_FAILURE); */
96 static bool s_needsPrepare = TRUE;
98 void prepareMessage ()
100 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
103 if ((context_isPreprocessing () || context_loadingLibrary ())
105 && context_getFlag (FLG_SHOWSCAN))
109 s_needsPrepare = FALSE;
115 void closeMessage (void)
117 if (context_isPreprocessing ()
118 && context_getFlag (FLG_SHOWSCAN))
121 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
122 llassertprotect (!s_needsPrepare);
123 s_needsPrepare = TRUE;
132 llmsg (/*@only@*/ cstring s)
134 context_setNeednl ();
136 printMessage (g_messagestream, s);
141 lldiagmsg (/*@only@*/ cstring s)
143 static bool inmsg = FALSE;
147 fprintf (g_errorstream,
148 "Recursive message call detected: %s\n",
149 cstring_toCharsSafe (s));
155 context_setNeednl ();
157 printMessage (g_messagestream, s);
164 llmsgplain (/*@only@*/ cstring s)
166 context_setNeednl ();
168 printMessage (g_messagestream, s);
172 void llerror_flagWarning (cstring s)
174 if (context_getFlag (FLG_WARNFLAGS))
178 if (fileloc_isBuiltin (g_currentloc))
180 llmsg (message ("Warning: %q", s));
184 llgenmsg (message ("Warning: %q", s), g_currentloc);
194 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
196 int indent = context_getIndentSpaces () - 1;
198 if (indent < 0) indent = 0;
200 context_setNeednl ();
201 printIndentMessage (g_warningstream, s, indent);
207 if (context_getFlag (FLG_HINTS) &&
208 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
219 llshowhint (flagcode f)
221 if (context_getFlag (FLG_HINTS))
223 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
225 cstring desc = flagcodeHint (f);
227 if (cstring_isDefined (desc))
229 llgenhint (cstring_copy (desc));
236 llsuppresshint2 (char c, flagcode f1, flagcode f2)
239 if (context_getFlag (FLG_HINTS))
241 if ((flagcode_numReported (f1) == 0
242 || flagcode_numReported (f2) == 0)
243 || context_getFlag (FLG_FORCEHINTS))
245 cstring desc = flagcodeHint (f1);
246 context_setNeednl ();
249 if (cstring_isUndefined (desc))
251 desc = flagcodeHint (f2);
254 if (flagcode_isNamePrefixFlag (f1))
259 if (flagcode_isNamePrefixFlag (f2))
266 if (cstring_isDefined (desc))
268 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
270 flagcode_unparse (f1)));
274 llgenhint (message ("(Use %h%s to inhibit warning)",
275 c, flagcode_unparse (f1)));
280 if (cstring_isDefined (desc))
282 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
284 flagcode_unparse (f1),
286 flagcode_unparse (f2)));
290 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
291 flagcode_unparse (f1),
292 c, flagcode_unparse (f2)));
300 llsuppresshint (char c, flagcode f)
302 if (context_getFlag (FLG_HINTS))
304 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
306 cstring desc = flagcodeHint (f);
307 context_setNeednl ();
310 if (flagcode_isNamePrefixFlag (f))
315 if (cstring_isDefined (desc))
317 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
318 flagcode_unparse (f)));
322 llgenhint (message ("(Use %h%s to inhibit warning)", c,
323 flagcode_unparse (f)));
330 llnosuppresshint (flagcode f)
332 if (context_getFlag (FLG_FORCEHINTS))
334 cstring desc = flagcodeHint (f);
335 context_setNeednl ();
338 if (cstring_isDefined (desc))
340 printError (g_warningstream, message (" %s", desc));
345 /*@constant int MAXSEARCH; @*/
346 # define MAXSEARCH 20
348 /*@constant int MINLINE; @*/
351 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
354 mstring_split (/*@returned@*/ char **sp,
355 /*@out@*/ nd_charp *tp,
356 int maxline, /*@in@*/ int *indentchars)
365 DPRINTF (("Split: %s / %d", *sp, maxline));
367 if (maxline < MINLINELEN)
369 maxline = MINLINELEN;
372 if (*indentchars > 0)
374 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
378 nl = strchr (s, '\n');
383 ** if there is a newline in first maxline characters, split there
384 ** if line len is <= maxline, return no split
385 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
386 ** split there unless the ' ' is followed by a '}', then
388 ** of the ';' is inside quotation marks
389 ** if there is a space or tab in last maxsearch characters, split there
390 ** else, split at maxline
392 ** special code: slash [1-9] after a newline means indent the rest <n> chars
396 if ((nl != NULL) && ((nl - s) < maxline))
403 llassertprotect (*tp == NULL || (*tp > osp));
407 if (*t >= '\1' && *t <= '\7')
409 *indentchars += (int) (*t - '\1') + 1;
416 else if (size_toInt (strlen (s)) < maxline)
418 llassertprotect (*tp == NULL || (*tp > osp));
425 char *lcolon, *lsemi, *lcomma;
434 lcolon = strrchr (s, ':');
435 lsemi = strrchr (s, ';');
436 lcomma = strrchr (s, ',');
440 splitat = maxcp (lcolon, lsemi);
442 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
443 && *(splitat) != '\0'
444 && *(splitat + 1) == ' '
445 && (*(splitat + 2) != '}'
446 && *(splitat + 2) != ','
447 && (*(splitat + 2) != '\0')))
449 *(splitat + 1) = '\0';
452 llassertprotect (*tp == NULL || (*tp > osp));
456 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
460 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
461 && *(splitat) != '\0'
462 && *(splitat + 1) == ' '
463 && (*(splitat + 2) != '}'
464 && (*(splitat + 2) != '\0')))
466 *(splitat + 1) = '\0';
469 llassertprotect (*tp == NULL || (*tp > osp));
474 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
480 if (*t != ' ' && *t != '\t')
482 llassertprotect (maxline > 0);
483 t = mstring_copy (s + maxline);
484 *(s + maxline) = '\0';
489 llassertprotect (*tp == NULL || (*tp > osp));
493 mstring_markFree (t);
495 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
504 if (*t == '\0') return;
507 ** returns unqualified as only
513 /* Hack to prevent error case for wierd strings. */
519 llassertprotect (*tp == NULL || (*tp > osp));
530 void limitmessage (/*@only@*/ cstring s, fileloc loc)
532 if (mcount > context_getLimit () + 1)
538 cstring flstring = fileloc_unparse (loc);
540 lastfileloclen = cstring_length (flstring);
541 cstring_free (saveOneMessage);
542 saveOneMessage = message ("%q: %q", flstring, s);
546 static int parseerrorcount = 0;
548 void cleanupMessages ()
552 if (context_unlimitedMessages ())
558 int unprinted = mcount - context_getLimit ();
562 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
565 printError (g_warningstream, saveOneMessage);
567 saveOneMessage = cstring_undefined;
571 if (cstring_isDefined (saveOneMessage))
573 /* cstring_free (saveOneMessage); */
574 saveOneMessage = cstring_undefined;
577 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
578 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
579 mcount - context_getLimit ());
588 llgenmsg (/*@only@*/ cstring s, fileloc fl)
590 cstring flstring = fileloc_unparse (fl);
591 lastfileloclen = cstring_length (flstring);
594 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
599 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
601 cstring flstring = fileloc_unparse (fl);
604 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
609 llgenindentmsgnoloc (/*@only@*/ cstring s)
612 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
617 llgentypeerroraux (char *srcFile, int srcLine,
618 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
619 /*@only@*/ cstring s, fileloc fl)
621 cstring hint = cstring_undefined;
622 flagcode code = ocode;
623 flagcode hcode = INVALID_FLAG;
627 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
628 flagcode_unparse (ocode),
629 exprNode_unparse (e1), exprNode_unparse (e2),
630 ctype_unparse (t1), ctype_unparse (t2)));
632 DPRINTF (("Bool: %s / %s",
633 bool_unparse (ctype_isBool (t1)),
634 bool_unparse (ctype_isBool (t2))));
637 ** Set the flag using the underlying types that didn't match.
640 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
641 ut1 = ctype_baseArrayPtr (ut1);
642 ut2 = ctype_baseArrayPtr (ut2);
645 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
646 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
648 hcode = FLG_FLOATDOUBLE;
650 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
651 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
653 hcode = FLG_CHARINTLITERAL;
655 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
656 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
658 hcode = FLG_NUMLITERAL;
660 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
661 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
662 /* evs 2000-07-24: was ctype_isDirectBool */
666 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
667 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
671 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
672 || (ctype_isChar (ut1) && ctype_isChar (ut2))
673 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
675 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
677 hcode = FLG_IGNORESIGNS;
681 hcode = FLG_IGNOREQUALS;
684 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
686 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
688 hcode = FLG_MATCHANYINTEGRAL;
690 else if (ctype_match (ut2, ctype_ulint))
692 hcode = FLG_LONGUNSIGNEDINTEGRAL;
694 else if (ctype_match (ut2, ctype_lint))
696 hcode = FLG_LONGINTEGRAL;
698 else if (ctype_isInt (ut2))
700 hcode = FLG_MATCHANYINTEGRAL;
707 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
709 ctype tr = ctype_realType (ut1);
711 if (ctype_isArbitraryIntegral (tr))
713 hcode = FLG_MATCHANYINTEGRAL;
715 else if (ctype_match (ut1, ctype_ulint))
717 if (ctype_isUnsignedIntegral (tr))
719 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
721 else if (ctype_isSignedIntegral (tr))
727 hcode = FLG_LONGUNSIGNEDINTEGRAL;
730 else if (ctype_match (ut1, ctype_lint))
732 if (ctype_isSignedIntegral (tr))
734 hcode = FLG_LONGSIGNEDINTEGRAL;
736 else if (ctype_isSignedIntegral (tr))
742 hcode = FLG_LONGINTEGRAL;
745 else if (ctype_isInt (ut1))
747 hcode = FLG_MATCHANYINTEGRAL;
759 if (hcode == INVALID_FLAG)
761 DPRINTF (("[%s] %s - %s / %s",
763 bool_unparse (ctype_isEnum (ut1)),
764 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
765 bool_unparse (ctype_isInt (ut2))));
767 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
769 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
770 ctype ct = uentry_getType (ue1);
772 if (ctype_match (ct, ut2))
775 hint = message ("Underlying types match, but %s is an "
776 "abstract type that is not accessible here.",
780 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
782 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
783 ctype ct = uentry_getType (ue);
785 if (ctype_match (ct, ut1))
788 hint = message ("Underlying types match, but %s is an "
789 "abstract type that is not accessible here.",
795 ; /* Not an abstract mismatch. */
799 if (hcode == INVALID_FLAG)
801 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
802 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
806 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
807 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
811 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
812 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
814 hcode = FLG_CHARUNSIGNEDCHAR;
816 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
818 hcode = FLG_RELAXTYPES;
819 DPRINTF (("Setting relax types!"));
823 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
824 ctype_unparse (ut2)));
829 if (cstring_isDefined (hint))
831 if (!context_suppressFlagMsg (ocode, fl))
833 return llgenhinterror (code, s, hint, fl);
844 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
846 if (hcode != INVALID_FLAG && hcode != ocode)
854 llsuppresshint ('-', code);
857 flagcode_recordError (code);
866 xllgentypeerror (char *srcFile, int srcLine,
867 ctype t1, exprNode e1, ctype t2, exprNode e2,
868 /*@only@*/ cstring s, fileloc fl)
870 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
874 xllgenformattypeerror (char *srcFile, int srcLine,
875 ctype t1, exprNode e1, ctype t2, exprNode e2,
876 /*@only@*/ cstring s, fileloc fl)
878 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
880 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
890 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
892 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
894 llnosuppresshint (o);
895 flagcode_recordError (o);
901 flagcode_recordSuppressed (o);
907 xllgenhinterror (char *srcFile, int srcLine,
908 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
911 if (!context_suppressFlagMsg (o, fl))
913 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
915 flagcode_recordError (o);
917 if (context_getFlag (FLG_HINTS))
938 flagcode_recordSuppressed (o);
943 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
945 return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
949 llgenerroraux (char *srcFile, int srcLine,
950 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
952 if (context_inSuppressZone (fl))
958 if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
966 xllforceerror (char *srcFile, int srcLine,
967 flagcode code, /*@only@*/ cstring s, fileloc fl)
969 flagcode_recordError (code);
971 if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
980 llgenerrorreal (char *srcFile, int srcLine,
981 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
985 /* duplicate message (rescanning a header file */
987 if (!messageLog_add (context_messageLog (), fl, s))
989 DPRINTF (("Duplicate message suppressed! %s / %s",
990 fileloc_unparse (fl), s));
996 ** If herald has not been displayed, display it before the first message.
1001 if (iserror) context_hasError ();
1003 if (context_unlimitedMessages ())
1010 ** suppress excessive messages:
1015 char *sc = cstring_toCharsSafe (s);
1016 char *tmpmsg = strchr (sc, ':');
1024 char *savechar = tmpmsg;
1030 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1033 if (mcount == (context_getLimit () + 1))
1035 limitmessage (s, fl);
1039 if (mcount > (context_getLimit ()))
1049 cstring_free (lastmsg);
1050 lastmsg = cstring_fromCharsNew (tmpmsg);
1054 DPRINTF (("Here..."));
1056 if (context_hasAliasAnnote ())
1058 char *sc = cstring_toCharsSafe (s);
1059 char *fcolon = strchr (sc, ':');
1060 cstring a = context_getAliasAnnote ();
1065 s = message ("%q (%q)", s, a);
1072 afterColon = cstring_fromCharsNew (fcolon + 1);
1074 s = message ("%q (%q):%q", s, a, afterColon);
1078 if (context_hasMessageAnnote ())
1080 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1085 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1086 s = message ("%q (%q)", s, context_getMessageAnnote ());
1087 /*@=dependenttrans@*/
1094 afterColon = cstring_fromCharsNew (fcolon + 1);
1096 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1097 s = message ("%q (%q):%q", s,
1098 context_getMessageAnnote (), afterColon);
1099 /*@=dependenttrans@*/
1103 context_setNeednl ();
1106 if (context_showFunction ())
1108 cstring fname = fileloc_unparseFilename (g_currentloc);
1110 if (context_inIterDef ())
1112 fprintf (g_warningstream, "%s: (in iter %s)\n",
1113 cstring_toCharsSafe (fname),
1114 cstring_toCharsSafe (context_inFunctionName ()));
1116 else if (context_inIterEnd ())
1118 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1119 cstring_toCharsSafe (fname),
1120 cstring_toCharsSafe (context_inFunctionName ()));
1122 else if (context_inMacro ())
1124 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1125 cstring_toCharsSafe (context_inFunctionName ()));
1129 fprintf (g_warningstream, "%s: (in function %s)\n",
1130 cstring_toCharsSafe (fname),
1131 cstring_toCharsSafe (context_inFunctionName ()));
1134 cstring_free (fname);
1135 context_setShownFunction ();
1138 flstring = fileloc_unparse (fl);
1139 lastfileloclen = cstring_length (flstring);
1143 printError (g_warningstream, message (" %q: %q", flstring, s));
1147 printError (g_warningstream, message ("%q: %q", flstring, s));
1150 showSourceLoc (srcFile, srcLine);
1157 ** message contains no '\n'
1158 ** message fits in one line: print it
1159 ** message fits in two lines with 3-space indent after fileloc: print it
1160 ** split line with 5-space indent from left margin: print it
1165 void printMessage (FILE *stream, /*@only@*/ cstring s)
1167 printIndentMessage (stream, s, 0);
1171 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1173 static bool inbody = FALSE;
1174 int maxlen = context_getLineLen ();
1175 char *s = cstring_toCharsSafe (sc);
1178 llassertprotect (!inbody);
1186 llassertprotect (st != olds);
1188 mstring_split (&st, &t, maxlen, &indent);
1189 fprintf (stream, "%s\n", st);
1190 llassertprotect (t != s);
1192 } while (s != NULL) ;
1199 void printError (FILE *stream, /*@only@*/ cstring sc)
1201 int maxlen = context_getLineLen ();
1202 size_t nspaces = lastfileloclen + 5;
1203 int nextlen = maxlen - nspaces;
1204 size_t len = cstring_length (sc);
1206 char *s = cstring_toCharsSafe (sc);
1210 DPRINTF (("Print error: [%s]", sc));
1212 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1214 mstring_split (&s, &t, maxlen, &indent);
1216 fprintf (stream, "%s\n", s);
1220 len = mstring_length (t);
1222 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1223 && size_toInt (len) > (nextlen - 1))
1225 fprintf (stream, " %s\n", t);
1229 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1232 for (i = 0; i < size_toInt (nspaces); i++)
1237 spaces[nspaces] = '\0';
1242 mstring_split (&st, &t, nextlen, &indent);
1243 fprintf (stream, "%s%s\n", spaces, st);
1252 DPRINTF (("Here 1: [%s]", sc));
1254 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1256 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1258 if (nspaces < 1) nspaces = 1;
1260 nextlen = maxlen - nspaces;
1262 mstring_split (&s, &t, maxlen, &indent);
1264 fprintf (stream, "%s\n", s);
1268 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1271 for (i = 0; i < size_toInt (nspaces); i++)
1276 spaces[nspaces] = '\0';
1282 mstring_split (&st, &t, nextlen, &indent);
1283 fprintf (stream, "%s%s\n", spaces, st);
1292 nextlen = maxlen - nspaces;
1294 DPRINTF (("Here 2: [%s]", s));
1295 mstring_split (&s, &t, maxlen, &indent);
1296 DPRINTF (("Here 3: [%s] [%s]", s, t));
1298 fprintf (stream, "%s\n", s);
1302 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1305 for (i = 0; i < nspaces; i++)
1310 spaces[nspaces] = '\0';
1315 DPRINTF (("Loop: [%s]", t));
1316 mstring_split (&st, &t, nextlen, &indent);
1317 DPRINTF (("Split: [%s] [%s]", st, t));
1318 fprintf (stream, "%s%s\n", spaces, st);
1319 DPRINTF (("Next..."));
1332 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1335 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1336 fileloc_unparse (g_currentloc), s));
1337 showSourceLoc (srcFile, srcLine);
1345 lclfatalbug (char *msg)
1348 printError (g_errorstream,
1349 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1357 checkParseError (void)
1359 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1361 llfatalerror (message ("%q: Cannot recover from parse error.",
1362 fileloc_unparse (g_currentloc)));
1366 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1369 static int numbugs = 0;
1370 static bool inbug = FALSE;
1374 cstring temps = fileloc_unparseRaw (file, line);
1376 fprintf (g_errorstream,
1377 "%s: Recursive bug detected: %s\n",
1378 cstring_toCharsSafe (temps),
1379 cstring_toCharsSafe (s));
1380 cstring_free (temps);
1389 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1391 llfatalerror (message ("%q: Cannot recover from parse error.",
1392 fileloc_unparse (g_currentloc)));
1395 (void) fflush (g_warningstream);
1397 printError (g_errorstream,
1398 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1399 fileloc_unparse (g_currentloc),
1400 fileloc_unparseRaw (file, line),
1403 /* printCodePoint (); no longer useful */
1409 perror ("Possible system error diagnostic: ");
1417 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1420 (message ("%q: Cannot recover from last bug. "
1421 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1422 fileloc_unparse (g_currentloc)));
1425 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1426 fileloc_free (lastbug);
1427 lastbug = fileloc_copy (g_currentloc);
1434 lclbug (/*@only@*/ cstring s)
1437 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1440 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1446 llfatalerror (cstring s)
1449 printError (g_errorstream, s);
1450 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1455 llfatalerrorLoc (/*@only@*/ cstring s)
1458 (void) fflush (g_warningstream);
1459 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1460 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1461 (void) fflush (g_warningstream);
1469 return (lclerrors > 0);
1473 lclHadNewError (void)
1475 static int lastcall = 0;
1477 if (lclerrors > lastcall)
1479 lastcall = lclerrors;
1489 lclNumberErrors (void)
1495 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1499 if (ltoken_getCode (t) != NOTTOKEN)
1501 cstring loc = ltoken_unparseLoc (t);
1502 lastfileloclen = cstring_length (loc);
1504 printError (g_warningstream, message ("%q: %q", loc, msg));
1505 showSourceLoc (srcFile, srcLine);
1509 printError (g_warningstream, msg);
1510 showSourceLoc (srcFile, srcLine);
1515 lclplainerror (/*@only@*/ cstring msg)
1518 printError (g_warningstream, msg);
1522 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1524 if (ltoken_getCode (t) != NOTTOKEN)
1526 cstring loc = ltoken_unparseLoc (t);
1527 lastfileloclen = cstring_length (loc);
1528 printError (g_errorstream, message ("%q: %q", loc, msg));
1532 printError (g_errorstream, msg);
1535 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1540 lclplainfatalerror (/*@only@*/ cstring msg)
1542 (void) fflush (g_warningstream);
1543 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1548 lclRedeclarationError (ltoken id)
1550 cstring s = ltoken_getRawString (id);
1553 if (usymtab_existsEither (s))
1555 uentry le = usymtab_lookupEither (s);
1557 lclerror (id, message ("Respecification of %s", s));
1558 llgenindentmsg (message ("Previous specification of %q",
1559 uentry_getName (le)),
1560 uentry_whereSpecified (le));
1564 lclerror (id, message ("Identifier redeclared: %s", s));
1569 void genppllerror (flagcode code, /*@only@*/ cstring s)
1571 if (context_inSuppressZone (g_currentloc))
1577 if (context_getFlag (code))
1579 if (!context_isInCommandLine ())
1581 displayScanClose ();
1586 if (code != FLG_PREPROC)
1588 llsuppresshint ('-', code);
1591 if (!context_isInCommandLine ())
1593 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1603 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1604 /*@only@*/ cstring hint)
1606 if (context_inSuppressZone (g_currentloc))
1609 cstring_free (hint);
1613 if (context_getFlag (code))
1616 context_clearPreprocessing ();
1619 context_setPreprocessing ();
1625 cstring_free (hint);
1630 void ppllerror (/*@only@*/ cstring s)
1632 genppllerror (FLG_PREPROC, s);
1635 void pplldiagmsg (cstring s)
1637 if (!context_isInCommandLine ())
1639 displayScanClose ();
1641 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1649 void loadllmsg (cstring s)
1651 displayScanClose ();
1653 displayScanOpen (cstring_makeLiteral ("< ."));
1656 static void llreportparseerror (/*@only@*/ cstring s)
1658 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1664 llerror (FLG_SYNTAX, s);
1666 fileloc_free (lastparseerror);
1667 lastparseerror = fileloc_copy (g_currentloc);
1671 bool xcppoptgenerror (char *srcFile, int srcLine,
1673 /*@only@*/ cstring s,
1677 fileloc loc = cppReader_getLoc (pfile);
1679 if (context_flagOn (o, loc))
1681 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1683 cppReader_printContainingFiles (pfile);
1697 bool xlloptgenerror (char *srcFile, int srcLine,
1698 flagcode o, /*@only@*/ cstring s, fileloc loc)
1700 DPRINTF (("xllopt: %s", s));
1702 if (llrealerror (srcFile, srcLine, s, loc))
1704 DPRINTF (("Here we are!"));
1705 llsuppresshint ('-', o);
1707 flagcode_recordError (o);
1712 DPRINTF (("Suppressed!"));
1713 flagcode_recordSuppressed (o);
1718 bool xoptgenerror2 (char *srcFile, int srcLine,
1719 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1721 if (context_suppressFlagMsg (f1, loc))
1723 flagcode_recordSuppressed (f1);
1728 if (context_suppressFlagMsg (f2, loc))
1730 flagcode_recordSuppressed (f2);
1735 if (llrealerror (srcFile, srcLine, s, loc))
1737 llsuppresshint2 ('-', f1, f2);
1738 flagcode_recordError (f2);
1744 flagcode_recordSuppressed (f2);
1752 bool xoptgenerror2n (char *srcFile, int srcLine,
1753 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1756 if (context_suppressFlagMsg (f1, loc))
1758 flagcode_recordSuppressed (f1);
1763 if (context_suppressNotFlagMsg (f2, loc))
1765 flagcode_recordSuppressed (f2);
1770 if (llrealerror (srcFile, srcLine, s, loc))
1772 llsuppresshint ('+', f2);
1773 flagcode_recordError (f2);
1778 flagcode_recordSuppressed (f2);
1784 bool xllnoptgenerror (char *srcFile, int srcLine,
1785 flagcode o, /*@only@*/ cstring s, fileloc loc)
1787 if (llrealerror (srcFile, srcLine, s, loc))
1789 llsuppresshint ('+', o);
1790 flagcode_recordError (o);
1795 flagcode_recordSuppressed (o);
1799 void llparseerror (cstring s)
1801 if (context_getFlag (FLG_TRYTORECOVER))
1805 if (parseerrorcount > GIVEUPPARSE)
1807 if (cstring_isDefined (s))
1809 llfatalerror (message ("%q: Parse Error: %q. "
1810 "Too many errors, giving up.",
1811 fileloc_unparse (g_currentloc), s));
1815 llfatalerror (message ("%q: Parse Error. Too many errors, giving up.",
1816 fileloc_unparse (g_currentloc)));
1821 if (cstring_isDefined (s))
1823 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1828 llreportparseerror (message ("Parse Error. Attempting to continue."));
1836 if (cstring_isDefined (s))
1838 msg = message ("Parse Error: %q.", s);
1842 msg = message ("Parse Error.");
1846 (message ("%q: %s (For help on parse errors, "
1847 "see splint -help parseerrors.)",
1848 fileloc_unparse (g_currentloc), msg));
1852 bool xfsgenerror (char *srcFile, int srcLine,
1853 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1855 if (flagSpec_isOn (fs, fl))
1857 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1859 llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1860 flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1865 flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1871 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1877 bool doCheck (bool x, cstring pred, cstring file, int line)
1880 llbug (message ("%q: Check Failed: %s",
1881 fileloc_unparseRaw (file, line),
1888 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1893 #ifndef HAVE_STRERROR
1896 result = strerror (errnum);
1899 /* VAXCRTL's strerror() takes an optional second argument, which only
1900 matters when the first argument is EVMSERR. However, it's simplest
1901 just to pass it unconditionally. `vaxc$errno' is declared in
1902 <errno.h>, and maintained by the library in parallel with `errno'.
1903 We assume that caller's `errnum' either matches the last setting of
1904 `errno' by the library or else does not have the value `EVMSERR'. */
1906 result = strerror (errnum, vaxc$errno);
1911 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1914 return cstring_fromChars (result);
1917 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1922 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1923 fileloc_unparse (g_currentloc),
1924 fileloc_unparseRaw (file, line),
1936 (void) fflush (g_warningstream);
1937 (void) fflush (g_messagestream);
1940 static bool s_scanOpen = FALSE;
1942 void displayScan (cstring msg)
1944 llassert (!s_scanOpen);
1946 if (context_getFlag (FLG_SHOWSCAN))
1948 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
1949 (void) fflush (g_messagestream);
1955 void displayScanOpen (cstring msg)
1957 llassert (!s_scanOpen);
1960 if (context_getFlag (FLG_SHOWSCAN))
1962 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
1963 (void) fflush (g_messagestream);
1969 void displayScanContinue (/*@temp@*/ cstring msg)
1971 if (context_getFlag (FLG_SHOWSCAN))
1973 llassert (s_scanOpen);
1974 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
1975 (void) fflush (g_messagestream);
1979 void displayScanClose (void)
1981 llassert (s_scanOpen);
1983 if (context_getFlag (FLG_SHOWSCAN))
1985 fprintf (g_messagestream, " >\n");
1986 (void) fflush (g_messagestream);