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))
176 llgenmsg (s, g_currentloc);
185 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
187 int indent = context_getIndentSpaces () - 1;
189 if (indent < 0) indent = 0;
191 context_setNeednl ();
192 printIndentMessage (g_warningstream, s, indent);
198 if (context_getFlag (FLG_HINTS) &&
199 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
210 llshowhint (flagcode f)
212 if (context_getFlag (FLG_HINTS))
214 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
216 cstring desc = flagcodeHint (f);
218 if (cstring_isDefined (desc))
220 llgenhint (cstring_copy (desc));
227 llsuppresshint2 (char c, flagcode f1, flagcode f2)
230 if (context_getFlag (FLG_HINTS))
232 if ((flagcode_numReported (f1) == 0
233 || flagcode_numReported (f2) == 0)
234 || context_getFlag (FLG_FORCEHINTS))
236 cstring desc = flagcodeHint (f1);
237 context_setNeednl ();
240 if (cstring_isUndefined (desc))
242 desc = flagcodeHint (f2);
245 if (flagcode_isNamePrefixFlag (f1))
250 if (flagcode_isNamePrefixFlag (f2))
257 if (cstring_isDefined (desc))
259 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
261 flagcode_unparse (f1)));
265 llgenhint (message ("(Use %h%s to inhibit warning)",
266 c, flagcode_unparse (f1)));
271 if (cstring_isDefined (desc))
273 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
275 flagcode_unparse (f1),
277 flagcode_unparse (f2)));
281 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
282 flagcode_unparse (f1),
283 c, flagcode_unparse (f2)));
291 llsuppresshint (char c, flagcode f)
293 if (context_getFlag (FLG_HINTS))
295 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
297 cstring desc = flagcodeHint (f);
298 context_setNeednl ();
301 if (flagcode_isNamePrefixFlag (f))
306 if (cstring_isDefined (desc))
308 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
309 flagcode_unparse (f)));
313 llgenhint (message ("(Use %h%s to inhibit warning)", c,
314 flagcode_unparse (f)));
321 llnosuppresshint (flagcode f)
323 if (context_getFlag (FLG_FORCEHINTS))
325 cstring desc = flagcodeHint (f);
326 context_setNeednl ();
329 if (cstring_isDefined (desc))
331 printError (g_warningstream, message (" %s", desc));
336 /*@constant int MAXSEARCH; @*/
337 # define MAXSEARCH 20
339 /*@constant int MINLINE; @*/
342 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
345 mstring_split (/*@returned@*/ char **sp,
346 /*@out@*/ nd_charp *tp,
347 int maxline, /*@in@*/ int *indentchars)
356 DPRINTF (("Split: %s / %d", *sp, maxline));
358 if (maxline < MINLINELEN)
360 maxline = MINLINELEN;
363 if (*indentchars > 0)
365 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
369 nl = strchr (s, '\n');
374 ** if there is a newline in first maxline characters, split there
375 ** if line len is <= maxline, return no split
376 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
377 ** split there unless the ' ' is followed by a '}', then
379 ** of the ';' is inside quotation marks
380 ** if there is a space or tab in last maxsearch characters, split there
381 ** else, split at maxline
383 ** special code: slash [1-9] after a newline means indent the rest <n> chars
387 if ((nl != NULL) && ((nl - s) < maxline))
394 llassertprotect (*tp == NULL || (*tp > osp));
398 if (*t >= '\1' && *t <= '\7')
400 *indentchars += (int) (*t - '\1') + 1;
407 else if (size_toInt (strlen (s)) < maxline)
409 llassertprotect (*tp == NULL || (*tp > osp));
416 char *lcolon, *lsemi, *lcomma;
425 lcolon = strrchr (s, ':');
426 lsemi = strrchr (s, ';');
427 lcomma = strrchr (s, ',');
431 splitat = maxcp (lcolon, lsemi);
433 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
434 && *(splitat) != '\0'
435 && *(splitat + 1) == ' '
436 && (*(splitat + 2) != '}'
437 && *(splitat + 2) != ','
438 && (*(splitat + 2) != '\0')))
440 *(splitat + 1) = '\0';
443 llassertprotect (*tp == NULL || (*tp > osp));
447 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
451 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
452 && *(splitat) != '\0'
453 && *(splitat + 1) == ' '
454 && (*(splitat + 2) != '}'
455 && (*(splitat + 2) != '\0')))
457 *(splitat + 1) = '\0';
460 llassertprotect (*tp == NULL || (*tp > osp));
465 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
471 if (*t != ' ' && *t != '\t')
473 llassertprotect (maxline > 0);
474 t = mstring_copy (s + maxline);
475 *(s + maxline) = '\0';
480 llassertprotect (*tp == NULL || (*tp > osp));
484 mstring_markFree (t);
486 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
495 if (*t == '\0') return;
498 ** returns unqualified as only
504 /* Hack to prevent error case for wierd strings. */
510 llassertprotect (*tp == NULL || (*tp > osp));
521 void limitmessage (/*@only@*/ cstring s, fileloc loc)
523 if (mcount > context_getLimit () + 1)
529 cstring flstring = fileloc_unparse (loc);
531 lastfileloclen = cstring_length (flstring);
532 cstring_free (saveOneMessage);
533 saveOneMessage = message ("%q: %q", flstring, s);
537 static int parseerrorcount = 0;
539 void cleanupMessages ()
543 if (context_unlimitedMessages ())
549 int unprinted = mcount - context_getLimit ();
553 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
556 printError (g_warningstream, saveOneMessage);
558 saveOneMessage = cstring_undefined;
562 if (cstring_isDefined (saveOneMessage))
564 /* cstring_free (saveOneMessage); */
565 saveOneMessage = cstring_undefined;
568 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
569 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
570 mcount - context_getLimit ());
579 llgenmsg (/*@only@*/ cstring s, fileloc fl)
581 cstring flstring = fileloc_unparse (fl);
582 lastfileloclen = cstring_length (flstring);
585 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
590 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
592 cstring flstring = fileloc_unparse (fl);
595 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
600 llgenindentmsgnoloc (/*@only@*/ cstring s)
603 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
608 llgentypeerroraux (char *srcFile, int srcLine,
609 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
610 /*@only@*/ cstring s, fileloc fl)
612 cstring hint = cstring_undefined;
613 flagcode code = ocode;
614 flagcode hcode = INVALID_FLAG;
618 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
619 flagcode_unparse (ocode),
620 exprNode_unparse (e1), exprNode_unparse (e2),
621 ctype_unparse (t1), ctype_unparse (t2)));
623 DPRINTF (("Bool: %s / %s",
624 bool_unparse (ctype_isBool (t1)),
625 bool_unparse (ctype_isBool (t2))));
628 ** Set the flag using the underlying types that didn't match.
631 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
632 ut1 = ctype_baseArrayPtr (ut1);
633 ut2 = ctype_baseArrayPtr (ut2);
636 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
637 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
639 hcode = FLG_FLOATDOUBLE;
641 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
642 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
644 hcode = FLG_CHARINTLITERAL;
646 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
647 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
649 hcode = FLG_NUMLITERAL;
651 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
652 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
653 /* evs 2000-07-24: was ctype_isDirectBool */
657 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
658 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
662 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
663 || (ctype_isChar (ut1) && ctype_isChar (ut2))
664 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
666 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
668 hcode = FLG_IGNORESIGNS;
672 hcode = FLG_IGNOREQUALS;
675 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
677 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
679 hcode = FLG_MATCHANYINTEGRAL;
681 else if (ctype_match (ut2, ctype_ulint))
683 hcode = FLG_LONGUNSIGNEDINTEGRAL;
685 else if (ctype_match (ut2, ctype_lint))
687 hcode = FLG_LONGINTEGRAL;
689 else if (ctype_isInt (ut2))
691 hcode = FLG_MATCHANYINTEGRAL;
698 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
700 ctype tr = ctype_realType (ut1);
702 if (ctype_isArbitraryIntegral (tr))
704 hcode = FLG_MATCHANYINTEGRAL;
706 else if (ctype_match (ut1, ctype_ulint))
708 if (ctype_isUnsignedIntegral (tr))
710 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
712 else if (ctype_isSignedIntegral (tr))
718 hcode = FLG_LONGUNSIGNEDINTEGRAL;
721 else if (ctype_match (ut1, ctype_lint))
723 if (ctype_isSignedIntegral (tr))
725 hcode = FLG_LONGSIGNEDINTEGRAL;
727 else if (ctype_isSignedIntegral (tr))
733 hcode = FLG_LONGINTEGRAL;
736 else if (ctype_isInt (ut1))
738 hcode = FLG_MATCHANYINTEGRAL;
750 if (hcode == INVALID_FLAG)
752 DPRINTF (("[%s] %s - %s / %s",
754 bool_unparse (ctype_isEnum (ut1)),
755 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
756 bool_unparse (ctype_isInt (ut2))));
758 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
760 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
761 ctype ct = uentry_getType (ue1);
763 if (ctype_match (ct, ut2))
766 hint = message ("Underlying types match, but %s is an "
767 "abstract type that is not accessible here.",
771 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
773 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
774 ctype ct = uentry_getType (ue);
776 if (ctype_match (ct, ut1))
779 hint = message ("Underlying types match, but %s is an "
780 "abstract type that is not accessible here.",
786 ; /* Not an abstract mismatch. */
790 if (hcode == INVALID_FLAG)
792 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
793 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
797 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
798 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
802 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
803 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
805 hcode = FLG_CHARUNSIGNEDCHAR;
807 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
809 hcode = FLG_RELAXTYPES;
810 DPRINTF (("Setting relax types!"));
814 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
815 ctype_unparse (ut2)));
820 if (cstring_isDefined (hint))
822 if (!context_suppressFlagMsg (ocode, fl))
824 return llgenhinterror (code, s, hint, fl);
835 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
837 if (hcode != INVALID_FLAG && hcode != ocode)
845 llsuppresshint ('-', code);
848 flagcode_recordError (code);
857 xllgentypeerror (char *srcFile, int srcLine,
858 ctype t1, exprNode e1, ctype t2, exprNode e2,
859 /*@only@*/ cstring s, fileloc fl)
861 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
865 xllgenformattypeerror (char *srcFile, int srcLine,
866 ctype t1, exprNode e1, ctype t2, exprNode e2,
867 /*@only@*/ cstring s, fileloc fl)
869 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
871 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
881 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
883 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
885 llnosuppresshint (o);
886 flagcode_recordError (o);
892 flagcode_recordSuppressed (o);
898 xllgenhinterror (char *srcFile, int srcLine,
899 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
902 if (!context_suppressFlagMsg (o, fl))
904 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
906 flagcode_recordError (o);
908 if (context_getFlag (FLG_HINTS))
929 flagcode_recordSuppressed (o);
934 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
936 return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
940 llgenerroraux (char *srcFile, int srcLine,
941 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
943 if (context_inSuppressZone (fl))
949 if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
957 xllforceerror (char *srcFile, int srcLine,
958 flagcode code, /*@only@*/ cstring s, fileloc fl)
960 flagcode_recordError (code);
962 if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
971 llgenerrorreal (char *srcFile, int srcLine,
972 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
976 /* duplicate message (rescanning a header file */
978 if (!messageLog_add (context_messageLog (), fl, s))
980 DPRINTF (("Duplicate message suppressed! %s / %s",
981 fileloc_unparse (fl), s));
987 ** If herald has not been displayed, display it before the first message.
992 if (iserror) context_hasError ();
994 if (context_unlimitedMessages ())
1001 ** suppress excessive messages:
1006 char *sc = cstring_toCharsSafe (s);
1007 char *tmpmsg = strchr (sc, ':');
1015 char *savechar = tmpmsg;
1021 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1024 if (mcount == (context_getLimit () + 1))
1026 limitmessage (s, fl);
1030 if (mcount > (context_getLimit ()))
1040 cstring_free (lastmsg);
1041 lastmsg = cstring_fromCharsNew (tmpmsg);
1045 DPRINTF (("Here..."));
1047 if (context_hasAliasAnnote ())
1049 char *sc = cstring_toCharsSafe (s);
1050 char *fcolon = strchr (sc, ':');
1051 cstring a = context_getAliasAnnote ();
1056 s = message ("%q (%q)", s, a);
1063 afterColon = cstring_fromCharsNew (fcolon + 1);
1065 s = message ("%q (%q):%q", s, a, afterColon);
1069 if (context_hasMessageAnnote ())
1071 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1076 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1077 s = message ("%q (%q)", s, context_getMessageAnnote ());
1078 /*@=dependenttrans@*/
1085 afterColon = cstring_fromCharsNew (fcolon + 1);
1087 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1088 s = message ("%q (%q):%q", s,
1089 context_getMessageAnnote (), afterColon);
1090 /*@=dependenttrans@*/
1094 context_setNeednl ();
1097 if (context_showFunction ())
1099 cstring fname = fileloc_unparseFilename (g_currentloc);
1101 if (context_inIterDef ())
1103 fprintf (g_warningstream, "%s: (in iter %s)\n",
1104 cstring_toCharsSafe (fname),
1105 cstring_toCharsSafe (context_inFunctionName ()));
1107 else if (context_inIterEnd ())
1109 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1110 cstring_toCharsSafe (fname),
1111 cstring_toCharsSafe (context_inFunctionName ()));
1113 else if (context_inMacro ())
1115 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1116 cstring_toCharsSafe (context_inFunctionName ()));
1120 fprintf (g_warningstream, "%s: (in function %s)\n",
1121 cstring_toCharsSafe (fname),
1122 cstring_toCharsSafe (context_inFunctionName ()));
1125 cstring_free (fname);
1126 context_setShownFunction ();
1129 flstring = fileloc_unparse (fl);
1130 lastfileloclen = cstring_length (flstring);
1134 printError (g_warningstream, message (" %q: %q", flstring, s));
1138 printError (g_warningstream, message ("%q: %q", flstring, s));
1141 showSourceLoc (srcFile, srcLine);
1148 ** message contains no '\n'
1149 ** message fits in one line: print it
1150 ** message fits in two lines with 3-space indent after fileloc: print it
1151 ** split line with 5-space indent from left margin: print it
1156 void printMessage (FILE *stream, /*@only@*/ cstring s)
1158 printIndentMessage (stream, s, 0);
1162 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1164 static bool inbody = FALSE;
1165 int maxlen = context_getLineLen ();
1166 char *s = cstring_toCharsSafe (sc);
1169 llassertprotect (!inbody);
1177 llassertprotect (st != olds);
1179 mstring_split (&st, &t, maxlen, &indent);
1180 fprintf (stream, "%s\n", st);
1181 llassertprotect (t != s);
1183 } while (s != NULL) ;
1190 void printError (FILE *stream, /*@only@*/ cstring sc)
1192 int maxlen = context_getLineLen ();
1193 size_t nspaces = lastfileloclen + 5;
1194 int nextlen = maxlen - nspaces;
1195 size_t len = cstring_length (sc);
1197 char *s = cstring_toCharsSafe (sc);
1201 DPRINTF (("Print error: [%s]", sc));
1203 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1205 mstring_split (&s, &t, maxlen, &indent);
1207 fprintf (stream, "%s\n", s);
1211 len = mstring_length (t);
1213 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1214 && size_toInt (len) > (nextlen - 1))
1216 fprintf (stream, " %s\n", t);
1220 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1223 for (i = 0; i < size_toInt (nspaces); i++)
1228 spaces[nspaces] = '\0';
1233 mstring_split (&st, &t, nextlen, &indent);
1234 fprintf (stream, "%s%s\n", spaces, st);
1243 DPRINTF (("Here 1: [%s]", sc));
1245 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1247 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1249 if (nspaces < 1) nspaces = 1;
1251 nextlen = maxlen - nspaces;
1253 mstring_split (&s, &t, maxlen, &indent);
1255 fprintf (stream, "%s\n", s);
1259 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1262 for (i = 0; i < size_toInt (nspaces); i++)
1267 spaces[nspaces] = '\0';
1273 mstring_split (&st, &t, nextlen, &indent);
1274 fprintf (stream, "%s%s\n", spaces, st);
1283 nextlen = maxlen - nspaces;
1285 DPRINTF (("Here 2: [%s]", s));
1286 mstring_split (&s, &t, maxlen, &indent);
1287 DPRINTF (("Here 3: [%s] [%s]", s, t));
1289 fprintf (stream, "%s\n", s);
1293 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1296 for (i = 0; i < nspaces; i++)
1301 spaces[nspaces] = '\0';
1306 DPRINTF (("Loop: [%s]", t));
1307 mstring_split (&st, &t, nextlen, &indent);
1308 DPRINTF (("Split: [%s] [%s]", st, t));
1309 fprintf (stream, "%s%s\n", spaces, st);
1310 DPRINTF (("Next..."));
1323 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1326 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1327 fileloc_unparse (g_currentloc), s));
1328 showSourceLoc (srcFile, srcLine);
1336 lclfatalbug (char *msg)
1339 printError (g_errorstream,
1340 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1348 checkParseError (void)
1350 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1352 llfatalerror (message ("%q: Cannot recover from parse error.",
1353 fileloc_unparse (g_currentloc)));
1357 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1360 static int numbugs = 0;
1361 static bool inbug = FALSE;
1365 cstring temps = fileloc_unparseRaw (file, line);
1367 fprintf (g_errorstream,
1368 "%s: Recursive bug detected: %s\n",
1369 cstring_toCharsSafe (temps),
1370 cstring_toCharsSafe (s));
1371 cstring_free (temps);
1380 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1382 llfatalerror (message ("%q: Cannot recover from parse error.",
1383 fileloc_unparse (g_currentloc)));
1386 (void) fflush (g_warningstream);
1388 printError (g_errorstream,
1389 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1390 fileloc_unparse (g_currentloc),
1391 fileloc_unparseRaw (file, line),
1394 /* printCodePoint (); no longer useful */
1399 ** This is confusing, and hardly ever useful.
1403 perror ("Possible system error diagnostic: ");
1414 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1417 (message ("%q: Cannot recover from last bug. "
1418 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1419 fileloc_unparse (g_currentloc)));
1422 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1423 fileloc_free (lastbug);
1424 lastbug = fileloc_copy (g_currentloc);
1431 lclbug (/*@only@*/ cstring s)
1434 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1437 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1443 xllfatalerror (char *srcFile, int srcLine, cstring s)
1446 printError (g_errorstream, s);
1447 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1448 showSourceLoc (srcFile, srcLine);
1453 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1456 (void) fflush (g_warningstream);
1457 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1458 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1459 showSourceLoc (srcFile, srcLine);
1460 (void) fflush (g_warningstream);
1468 return (lclerrors > 0);
1472 lclHadNewError (void)
1474 static int lastcall = 0;
1476 if (lclerrors > lastcall)
1478 lastcall = lclerrors;
1488 lclNumberErrors (void)
1494 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1498 if (ltoken_getCode (t) != NOTTOKEN)
1500 cstring loc = ltoken_unparseLoc (t);
1501 lastfileloclen = cstring_length (loc);
1503 printError (g_warningstream, message ("%q: %q", loc, msg));
1504 showSourceLoc (srcFile, srcLine);
1508 printError (g_warningstream, msg);
1509 showSourceLoc (srcFile, srcLine);
1514 lclplainerror (/*@only@*/ cstring msg)
1517 printError (g_warningstream, msg);
1521 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1523 if (ltoken_getCode (t) != NOTTOKEN)
1525 cstring loc = ltoken_unparseLoc (t);
1526 lastfileloclen = cstring_length (loc);
1527 printError (g_errorstream, message ("%q: %q", loc, msg));
1531 printError (g_errorstream, msg);
1534 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1539 lclplainfatalerror (/*@only@*/ cstring msg)
1541 (void) fflush (g_warningstream);
1542 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1547 lclRedeclarationError (ltoken id)
1549 cstring s = ltoken_getRawString (id);
1552 if (usymtab_existsEither (s))
1554 uentry le = usymtab_lookupEither (s);
1556 lclerror (id, message ("Respecification of %s", s));
1557 llgenindentmsg (message ("Previous specification of %q",
1558 uentry_getName (le)),
1559 uentry_whereSpecified (le));
1563 lclerror (id, message ("Identifier redeclared: %s", s));
1568 void genppllerror (flagcode code, /*@only@*/ cstring s)
1570 if (context_inSuppressZone (g_currentloc))
1576 if (context_getFlag (code))
1578 if (!context_isInCommandLine ())
1580 displayScanClose ();
1585 if (code != FLG_PREPROC)
1587 llsuppresshint ('-', code);
1590 if (!context_isInCommandLine ())
1592 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1602 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1603 /*@only@*/ cstring hint)
1605 if (context_inSuppressZone (g_currentloc))
1608 cstring_free (hint);
1612 if (context_getFlag (code))
1615 context_clearPreprocessing ();
1618 context_setPreprocessing ();
1624 cstring_free (hint);
1629 void ppllerror (/*@only@*/ cstring s)
1631 genppllerror (FLG_PREPROC, s);
1634 void pplldiagmsg (cstring s)
1636 if (!context_isInCommandLine ())
1638 displayScanClose ();
1640 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1648 void loadllmsg (cstring s)
1650 displayScanClose ();
1652 displayScanOpen (cstring_makeLiteral ("< ."));
1655 static void llreportparseerror (/*@only@*/ cstring s)
1657 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1663 llerror (FLG_SYNTAX, s);
1665 fileloc_free (lastparseerror);
1666 lastparseerror = fileloc_copy (g_currentloc);
1670 bool xcppoptgenerror (char *srcFile, int srcLine,
1672 /*@only@*/ cstring s,
1676 fileloc loc = cppReader_getLoc (pfile);
1678 if (context_flagOn (o, loc))
1680 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1682 cppReader_printContainingFiles (pfile);
1696 bool xlloptgenerror (char *srcFile, int srcLine,
1697 flagcode o, /*@only@*/ cstring s, fileloc loc)
1699 DPRINTF (("xllopt: %s", s));
1701 if (llrealerror (srcFile, srcLine, s, loc))
1703 DPRINTF (("Here we are!"));
1704 llsuppresshint ('-', o);
1706 flagcode_recordError (o);
1711 DPRINTF (("Suppressed!"));
1712 flagcode_recordSuppressed (o);
1717 bool xoptgenerror2 (char *srcFile, int srcLine,
1718 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1720 if (context_suppressFlagMsg (f1, loc))
1722 flagcode_recordSuppressed (f1);
1727 if (context_suppressFlagMsg (f2, loc))
1729 flagcode_recordSuppressed (f2);
1734 if (llrealerror (srcFile, srcLine, s, loc))
1736 llsuppresshint2 ('-', f1, f2);
1737 flagcode_recordError (f2);
1743 flagcode_recordSuppressed (f2);
1751 bool xoptgenerror2n (char *srcFile, int srcLine,
1752 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1755 if (context_suppressFlagMsg (f1, loc))
1757 flagcode_recordSuppressed (f1);
1762 if (context_suppressNotFlagMsg (f2, loc))
1764 flagcode_recordSuppressed (f2);
1769 if (llrealerror (srcFile, srcLine, s, loc))
1771 llsuppresshint ('+', f2);
1772 flagcode_recordError (f2);
1777 flagcode_recordSuppressed (f2);
1783 bool xllnoptgenerror (char *srcFile, int srcLine,
1784 flagcode o, /*@only@*/ cstring s, fileloc loc)
1786 if (llrealerror (srcFile, srcLine, s, loc))
1788 llsuppresshint ('+', o);
1789 flagcode_recordError (o);
1794 flagcode_recordSuppressed (o);
1798 void xllparseerror (char *srcFile, int srcLine, cstring s)
1800 if (context_getFlag (FLG_TRYTORECOVER))
1804 if (parseerrorcount > GIVEUPPARSE)
1806 if (cstring_isDefined (s))
1808 xllfatalerror (srcFile, srcLine,
1809 message ("%q: Parse Error: %q. "
1810 "Too many errors, giving up.",
1811 fileloc_unparse (g_currentloc), s));
1815 xllfatalerror (srcFile, srcLine,
1816 message ("%q: Parse Error. Too many errors, giving up.",
1817 fileloc_unparse (g_currentloc)));
1822 if (cstring_isDefined (s))
1824 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1826 showSourceLoc (srcFile, srcLine);
1830 llreportparseerror (message ("Parse Error. Attempting to continue."));
1831 showSourceLoc (srcFile, srcLine);
1839 if (cstring_isDefined (s))
1841 msg = message ("Parse Error: %q.", s);
1845 msg = message ("Parse Error.");
1850 message ("%q: %s (For help on parse errors, "
1851 "see splint -help parseerrors.)",
1852 fileloc_unparse (g_currentloc), msg));
1856 bool xfsgenerror (char *srcFile, int srcLine,
1857 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1859 if (flagSpec_isOn (fs, fl))
1861 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1863 llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1864 flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1869 flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1875 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1881 bool doCheck (bool x, cstring pred, cstring file, int line)
1884 llbug (message ("%q: Check Failed: %s",
1885 fileloc_unparseRaw (file, line),
1892 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1897 #ifndef HAVE_STRERROR
1900 result = strerror (errnum);
1903 /* VAXCRTL's strerror() takes an optional second argument, which only
1904 matters when the first argument is EVMSERR. However, it's simplest
1905 just to pass it unconditionally. `vaxc$errno' is declared in
1906 <errno.h>, and maintained by the library in parallel with `errno'.
1907 We assume that caller's `errnum' either matches the last setting of
1908 `errno' by the library or else does not have the value `EVMSERR'. */
1910 result = strerror (errnum, vaxc$errno);
1915 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1918 return cstring_fromChars (result);
1921 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1926 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1927 fileloc_unparse (g_currentloc),
1928 fileloc_unparseRaw (file, line),
1940 (void) fflush (g_warningstream);
1941 (void) fflush (g_messagestream);
1944 static bool s_scanOpen = FALSE;
1946 void displayScan (cstring msg)
1948 llassert (!s_scanOpen);
1950 if (context_getFlag (FLG_SHOWSCAN))
1952 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
1953 (void) fflush (g_messagestream);
1959 void displayScanOpen (cstring msg)
1961 llassert (!s_scanOpen);
1964 if (context_getFlag (FLG_SHOWSCAN))
1966 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
1967 (void) fflush (g_messagestream);
1973 void displayScanContinue (/*@temp@*/ cstring msg)
1975 if (context_getFlag (FLG_SHOWSCAN))
1979 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
1980 (void) fflush (g_messagestream);
1985 ** Don't call bug recursively
1988 fprintf (stderr, "*** Bug: scan continue scan not open\n");
1993 void displayScanClose (void)
1997 if (context_getFlag (FLG_SHOWSCAN))
1999 fprintf (g_messagestream, " >\n");
2000 (void) fflush (g_messagestream);
2006 ** Don't call bug recursively
2009 fprintf (stderr, "*** Bug: scan close scan not open\n");