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! */
39 /* Don't allow possibly-recursive assertion failures. */
41 # define llassert llassertprotect
43 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
44 /*@modifies *p_stream@*/ ;
47 static int lclerrors = 0;
50 static size_t lastfileloclen = 10;
51 static /*@only@*/ cstring lastmsg = cstring_undefined;
52 static int mcount = 0;
53 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
54 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
55 static /*@only@*/ fileloc lastbug = fileloc_undefined;
56 static bool llgenerrorreal (char *p_srcFile, int p_srcLine,
57 /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
58 /*@modifies g_warningstream@*/ ;
59 static bool llgenerroraux (char *p_srcFile, int p_srcLine,
60 /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
61 /*@modifies g_warningstream@*/ ;
63 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
64 /*@globals lastfileloclen @*/
65 /*@modifies *p_stream@*/ ;
66 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
67 /*@modifies *p_stream@*/ ;
69 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
71 static void showSourceLoc (char *srcFile, int srcLine)
72 /*@modifies g_warningstream@*/
74 if (context_getFlag (FLG_SHOWSOURCELOC)) {
75 llgenhint (message ("%s:%d: Source code error generation point.",
76 cstring_fromChars (srcFile), srcLine));
81 static /*@null@*/ char *
82 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
91 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
94 /* don't exit (EXIT_FAILURE); */
97 static bool s_needsPrepare = TRUE;
99 void prepareMessage ()
101 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
104 if ((context_isPreprocessing () || context_loadingLibrary ())
106 && context_getFlag (FLG_SHOWSCAN))
110 s_needsPrepare = FALSE;
116 void closeMessage (void)
118 if (context_isPreprocessing ()
119 && context_getFlag (FLG_SHOWSCAN))
122 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
123 llassertprotect (!s_needsPrepare);
124 s_needsPrepare = TRUE;
133 llmsg (/*@only@*/ cstring s)
135 context_setNeednl ();
137 printMessage (g_messagestream, s);
142 lldiagmsg (/*@only@*/ cstring s)
144 static bool inmsg = FALSE;
148 fprintf (g_errorstream,
149 "Recursive message call detected: %s\n",
150 cstring_toCharsSafe (s));
156 context_setNeednl ();
158 printMessage (g_messagestream, s);
165 llmsgplain (/*@only@*/ cstring s)
167 context_setNeednl ();
169 printMessage (g_messagestream, s);
173 void llerror_flagWarning (cstring s)
175 if (context_getFlag (FLG_WARNFLAGS))
179 if (fileloc_isBuiltin (g_currentloc))
181 llmsg (message ("Warning: %q", s));
185 llgenmsg (message ("Warning: %q", s), g_currentloc);
195 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
197 int indent = context_getIndentSpaces () - 1;
199 if (indent < 0) indent = 0;
201 context_setNeednl ();
202 printIndentMessage (g_warningstream, s, indent);
208 if (context_getFlag (FLG_HINTS) &&
209 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
220 llshowhint (flagcode f)
222 if (context_getFlag (FLG_HINTS))
224 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
226 cstring desc = flagcodeHint (f);
228 if (cstring_isDefined (desc))
230 llgenhint (cstring_copy (desc));
237 llsuppresshint2 (char c, flagcode f1, flagcode f2)
240 if (context_getFlag (FLG_HINTS))
242 if ((flagcode_numReported (f1) == 0
243 || flagcode_numReported (f2) == 0)
244 || context_getFlag (FLG_FORCEHINTS))
246 cstring desc = flagcodeHint (f1);
247 context_setNeednl ();
250 if (cstring_isUndefined (desc))
252 desc = flagcodeHint (f2);
255 if (flagcode_isNamePrefixFlag (f1))
260 if (flagcode_isNamePrefixFlag (f2))
267 if (cstring_isDefined (desc))
269 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
271 flagcode_unparse (f1)));
275 llgenhint (message ("(Use %h%s to inhibit warning)",
276 c, flagcode_unparse (f1)));
281 if (cstring_isDefined (desc))
283 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
285 flagcode_unparse (f1),
287 flagcode_unparse (f2)));
291 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
292 flagcode_unparse (f1),
293 c, flagcode_unparse (f2)));
301 llsuppresshint (char c, flagcode f)
303 if (context_getFlag (FLG_HINTS))
305 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
307 cstring desc = flagcodeHint (f);
308 context_setNeednl ();
311 if (flagcode_isNamePrefixFlag (f))
316 if (cstring_isDefined (desc))
318 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
319 flagcode_unparse (f)));
323 llgenhint (message ("(Use %h%s to inhibit warning)", c,
324 flagcode_unparse (f)));
331 llnosuppresshint (flagcode f)
333 if (context_getFlag (FLG_FORCEHINTS))
335 cstring desc = flagcodeHint (f);
336 context_setNeednl ();
339 if (cstring_isDefined (desc))
341 printError (g_warningstream, message (" %s", desc));
346 /*@constant int MAXSEARCH; @*/
347 # define MAXSEARCH 20
349 /*@constant int MINLINE; @*/
352 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
355 mstring_split (/*@returned@*/ char **sp,
356 /*@out@*/ nd_charp *tp,
357 int maxline, /*@in@*/ int *indentchars)
366 DPRINTF (("Split: %s / %d", *sp, maxline));
368 if (maxline < MINLINELEN)
370 maxline = MINLINELEN;
373 if (*indentchars > 0)
375 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
379 nl = strchr (s, '\n');
384 ** if there is a newline in first maxline characters, split there
385 ** if line len is <= maxline, return no split
386 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
387 ** split there unless the ' ' is followed by a '}', then
389 ** of the ';' is inside quotation marks
390 ** if there is a space or tab in last maxsearch characters, split there
391 ** else, split at maxline
393 ** special code: slash [1-9] after a newline means indent the rest <n> chars
397 if ((nl != NULL) && ((nl - s) < maxline))
404 llassertprotect (*tp == NULL || (*tp > osp));
408 if (*t >= '\1' && *t <= '\7')
410 *indentchars += (int) (*t - '\1') + 1;
417 else if (size_toInt (strlen (s)) < maxline)
419 llassertprotect (*tp == NULL || (*tp > osp));
426 char *lcolon, *lsemi, *lcomma;
435 lcolon = strrchr (s, ':');
436 lsemi = strrchr (s, ';');
437 lcomma = strrchr (s, ',');
441 splitat = maxcp (lcolon, lsemi);
443 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
444 && *(splitat) != '\0'
445 && *(splitat + 1) == ' '
446 && (*(splitat + 2) != '}'
447 && *(splitat + 2) != ','
448 && (*(splitat + 2) != '\0')))
450 *(splitat + 1) = '\0';
453 llassertprotect (*tp == NULL || (*tp > osp));
457 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
461 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
462 && *(splitat) != '\0'
463 && *(splitat + 1) == ' '
464 && (*(splitat + 2) != '}'
465 && (*(splitat + 2) != '\0')))
467 *(splitat + 1) = '\0';
470 llassertprotect (*tp == NULL || (*tp > osp));
475 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
481 if (*t != ' ' && *t != '\t')
483 llassertprotect (maxline > 0);
484 t = mstring_copy (s + maxline);
485 *(s + maxline) = '\0';
490 llassertprotect (*tp == NULL || (*tp > osp));
494 mstring_markFree (t);
496 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
505 if (*t == '\0') return;
508 ** returns unqualified as only
514 /* Hack to prevent error case for wierd strings. */
520 llassertprotect (*tp == NULL || (*tp > osp));
531 void limitmessage (/*@only@*/ cstring s, fileloc loc)
533 if (mcount > context_getLimit () + 1)
539 cstring flstring = fileloc_unparse (loc);
541 lastfileloclen = cstring_length (flstring);
542 cstring_free (saveOneMessage);
543 saveOneMessage = message ("%q: %q", flstring, s);
547 static int parseerrorcount = 0;
549 void cleanupMessages ()
553 if (context_unlimitedMessages ())
559 int unprinted = mcount - context_getLimit ();
563 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
566 printError (g_warningstream, saveOneMessage);
568 saveOneMessage = cstring_undefined;
572 if (cstring_isDefined (saveOneMessage))
574 /* cstring_free (saveOneMessage); */
575 saveOneMessage = cstring_undefined;
578 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
579 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
580 mcount - context_getLimit ());
589 llgenmsg (/*@only@*/ cstring s, fileloc fl)
591 cstring flstring = fileloc_unparse (fl);
592 lastfileloclen = cstring_length (flstring);
595 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
600 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
602 cstring flstring = fileloc_unparse (fl);
605 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
610 llgenindentmsgnoloc (/*@only@*/ cstring s)
613 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
618 llgentypeerroraux (char *srcFile, int srcLine,
619 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
620 /*@only@*/ cstring s, fileloc fl)
622 cstring hint = cstring_undefined;
623 flagcode code = ocode;
624 flagcode hcode = INVALID_FLAG;
628 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
629 flagcode_unparse (ocode),
630 exprNode_unparse (e1), exprNode_unparse (e2),
631 ctype_unparse (t1), ctype_unparse (t2)));
633 DPRINTF (("Bool: %s / %s",
634 bool_unparse (ctype_isBool (t1)),
635 bool_unparse (ctype_isBool (t2))));
638 ** Set the flag using the underlying types that didn't match.
641 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
642 ut1 = ctype_baseArrayPtr (ut1);
643 ut2 = ctype_baseArrayPtr (ut2);
646 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
647 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
649 hcode = FLG_FLOATDOUBLE;
651 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
652 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
654 hcode = FLG_CHARINTLITERAL;
656 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
657 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
659 hcode = FLG_NUMLITERAL;
661 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
662 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
663 /* evs 2000-07-24: was ctype_isDirectBool */
667 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
668 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
672 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
673 || (ctype_isChar (ut1) && ctype_isChar (ut2))
674 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
676 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
678 hcode = FLG_IGNORESIGNS;
682 hcode = FLG_IGNOREQUALS;
685 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
687 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
689 hcode = FLG_MATCHANYINTEGRAL;
691 else if (ctype_match (ut2, ctype_ulint))
693 hcode = FLG_LONGUNSIGNEDINTEGRAL;
695 else if (ctype_match (ut2, ctype_lint))
697 hcode = FLG_LONGINTEGRAL;
699 else if (ctype_isInt (ut2))
701 hcode = FLG_MATCHANYINTEGRAL;
708 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
710 ctype tr = ctype_realType (ut1);
712 if (ctype_isArbitraryIntegral (tr))
714 hcode = FLG_MATCHANYINTEGRAL;
716 else if (ctype_match (ut1, ctype_ulint))
718 if (ctype_isUnsignedIntegral (tr))
720 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
722 else if (ctype_isSignedIntegral (tr))
728 hcode = FLG_LONGUNSIGNEDINTEGRAL;
731 else if (ctype_match (ut1, ctype_lint))
733 if (ctype_isSignedIntegral (tr))
735 hcode = FLG_LONGSIGNEDINTEGRAL;
737 else if (ctype_isSignedIntegral (tr))
743 hcode = FLG_LONGINTEGRAL;
746 else if (ctype_isInt (ut1))
748 hcode = FLG_MATCHANYINTEGRAL;
760 if (hcode == INVALID_FLAG)
762 DPRINTF (("[%s] %s - %s / %s",
764 bool_unparse (ctype_isEnum (ut1)),
765 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
766 bool_unparse (ctype_isInt (ut2))));
768 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
770 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
771 ctype ct = uentry_getType (ue1);
773 if (ctype_match (ct, ut2))
776 hint = message ("Underlying types match, but %s is an "
777 "abstract type that is not accessible here.",
781 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
783 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
784 ctype ct = uentry_getType (ue);
786 if (ctype_match (ct, ut1))
789 hint = message ("Underlying types match, but %s is an "
790 "abstract type that is not accessible here.",
796 ; /* Not an abstract mismatch. */
800 if (hcode == INVALID_FLAG)
802 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
803 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
807 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
808 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
812 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
813 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
815 hcode = FLG_CHARUNSIGNEDCHAR;
817 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
819 hcode = FLG_RELAXTYPES;
820 DPRINTF (("Setting relax types!"));
824 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
825 ctype_unparse (ut2)));
830 if (cstring_isDefined (hint))
832 if (!context_suppressFlagMsg (ocode, fl))
834 return llgenhinterror (code, s, hint, fl);
845 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
847 if (hcode != INVALID_FLAG && hcode != ocode)
855 llsuppresshint ('-', code);
858 flagcode_recordError (code);
867 xllgentypeerror (char *srcFile, int srcLine,
868 ctype t1, exprNode e1, ctype t2, exprNode e2,
869 /*@only@*/ cstring s, fileloc fl)
871 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
875 xllgenformattypeerror (char *srcFile, int srcLine,
876 ctype t1, exprNode e1, ctype t2, exprNode e2,
877 /*@only@*/ cstring s, fileloc fl)
879 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
881 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
891 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
893 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
895 llnosuppresshint (o);
896 flagcode_recordError (o);
902 flagcode_recordSuppressed (o);
908 xllgenhinterror (char *srcFile, int srcLine,
909 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
912 if (!context_suppressFlagMsg (o, fl))
914 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
916 flagcode_recordError (o);
918 if (context_getFlag (FLG_HINTS))
939 flagcode_recordSuppressed (o);
944 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
946 return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
950 llgenerroraux (char *srcFile, int srcLine,
951 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
953 if (context_inSuppressZone (fl))
959 if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
967 xllforceerror (char *srcFile, int srcLine,
968 flagcode code, /*@only@*/ cstring s, fileloc fl)
970 flagcode_recordError (code);
972 if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
981 llgenerrorreal (char *srcFile, int srcLine,
982 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
986 /* duplicate message (rescanning a header file */
988 if (!messageLog_add (context_messageLog (), fl, s))
990 DPRINTF (("Duplicate message suppressed! %s / %s",
991 fileloc_unparse (fl), s));
997 ** If herald has not been displayed, display it before the first message.
1002 if (iserror) context_hasError ();
1004 if (context_unlimitedMessages ())
1011 ** suppress excessive messages:
1016 char *sc = cstring_toCharsSafe (s);
1017 char *tmpmsg = strchr (sc, ':');
1025 char *savechar = tmpmsg;
1031 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1034 if (mcount == (context_getLimit () + 1))
1036 limitmessage (s, fl);
1040 if (mcount > (context_getLimit ()))
1050 cstring_free (lastmsg);
1051 lastmsg = cstring_fromCharsNew (tmpmsg);
1055 DPRINTF (("Here..."));
1057 if (context_hasAliasAnnote ())
1059 char *sc = cstring_toCharsSafe (s);
1060 char *fcolon = strchr (sc, ':');
1061 cstring a = context_getAliasAnnote ();
1066 s = message ("%q (%q)", s, a);
1073 afterColon = cstring_fromCharsNew (fcolon + 1);
1075 s = message ("%q (%q):%q", s, a, afterColon);
1079 if (context_hasMessageAnnote ())
1081 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1086 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1087 s = message ("%q (%q)", s, context_getMessageAnnote ());
1088 /*@=dependenttrans@*/
1095 afterColon = cstring_fromCharsNew (fcolon + 1);
1097 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1098 s = message ("%q (%q):%q", s,
1099 context_getMessageAnnote (), afterColon);
1100 /*@=dependenttrans@*/
1104 context_setNeednl ();
1107 if (context_showFunction ())
1109 cstring fname = fileloc_unparseFilename (g_currentloc);
1111 if (context_inIterDef ())
1113 fprintf (g_warningstream, "%s: (in iter %s)\n",
1114 cstring_toCharsSafe (fname),
1115 cstring_toCharsSafe (context_inFunctionName ()));
1117 else if (context_inIterEnd ())
1119 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1120 cstring_toCharsSafe (fname),
1121 cstring_toCharsSafe (context_inFunctionName ()));
1123 else if (context_inMacro ())
1125 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1126 cstring_toCharsSafe (context_inFunctionName ()));
1130 fprintf (g_warningstream, "%s: (in function %s)\n",
1131 cstring_toCharsSafe (fname),
1132 cstring_toCharsSafe (context_inFunctionName ()));
1135 cstring_free (fname);
1136 context_setShownFunction ();
1139 flstring = fileloc_unparse (fl);
1140 lastfileloclen = cstring_length (flstring);
1144 printError (g_warningstream, message (" %q: %q", flstring, s));
1148 printError (g_warningstream, message ("%q: %q", flstring, s));
1151 showSourceLoc (srcFile, srcLine);
1158 ** message contains no '\n'
1159 ** message fits in one line: print it
1160 ** message fits in two lines with 3-space indent after fileloc: print it
1161 ** split line with 5-space indent from left margin: print it
1166 void printMessage (FILE *stream, /*@only@*/ cstring s)
1168 printIndentMessage (stream, s, 0);
1172 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1174 static bool inbody = FALSE;
1175 int maxlen = context_getLineLen ();
1176 char *s = cstring_toCharsSafe (sc);
1179 llassertprotect (!inbody);
1187 llassertprotect (st != olds);
1189 mstring_split (&st, &t, maxlen, &indent);
1190 fprintf (stream, "%s\n", st);
1191 llassertprotect (t != s);
1193 } while (s != NULL) ;
1200 void printError (FILE *stream, /*@only@*/ cstring sc)
1202 int maxlen = context_getLineLen ();
1203 size_t nspaces = lastfileloclen + 5;
1204 int nextlen = maxlen - nspaces;
1205 size_t len = cstring_length (sc);
1207 char *s = cstring_toCharsSafe (sc);
1211 DPRINTF (("Print error: [%s]", sc));
1213 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1215 mstring_split (&s, &t, maxlen, &indent);
1217 fprintf (stream, "%s\n", s);
1221 len = mstring_length (t);
1223 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1224 && size_toInt (len) > (nextlen - 1))
1226 fprintf (stream, " %s\n", t);
1230 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1233 for (i = 0; i < size_toInt (nspaces); i++)
1238 spaces[nspaces] = '\0';
1243 mstring_split (&st, &t, nextlen, &indent);
1244 fprintf (stream, "%s%s\n", spaces, st);
1253 DPRINTF (("Here 1: [%s]", sc));
1255 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1257 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1259 if (nspaces < 1) nspaces = 1;
1261 nextlen = maxlen - nspaces;
1263 mstring_split (&s, &t, maxlen, &indent);
1265 fprintf (stream, "%s\n", s);
1269 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1272 for (i = 0; i < size_toInt (nspaces); i++)
1277 spaces[nspaces] = '\0';
1283 mstring_split (&st, &t, nextlen, &indent);
1284 fprintf (stream, "%s%s\n", spaces, st);
1293 nextlen = maxlen - nspaces;
1295 DPRINTF (("Here 2: [%s]", s));
1296 mstring_split (&s, &t, maxlen, &indent);
1297 DPRINTF (("Here 3: [%s] [%s]", s, t));
1299 fprintf (stream, "%s\n", s);
1303 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1306 for (i = 0; i < nspaces; i++)
1311 spaces[nspaces] = '\0';
1316 DPRINTF (("Loop: [%s]", t));
1317 mstring_split (&st, &t, nextlen, &indent);
1318 DPRINTF (("Split: [%s] [%s]", st, t));
1319 fprintf (stream, "%s%s\n", spaces, st);
1320 DPRINTF (("Next..."));
1333 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1336 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1337 fileloc_unparse (g_currentloc), s));
1338 showSourceLoc (srcFile, srcLine);
1347 lclfatalbug (char *msg)
1350 printError (g_errorstream,
1351 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1359 checkParseError (void)
1361 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1363 llfatalerror (message ("%q: Cannot recover from parse error.",
1364 fileloc_unparse (g_currentloc)));
1368 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1371 static int numbugs = 0;
1372 static bool inbug = FALSE;
1376 cstring temps = fileloc_unparseRaw (file, line);
1378 fprintf (g_errorstream,
1379 "%s: Recursive bug detected: %s\n",
1380 cstring_toCharsSafe (temps),
1381 cstring_toCharsSafe (s));
1382 cstring_free (temps);
1391 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1393 llfatalerror (message ("%q: Cannot recover from parse error.",
1394 fileloc_unparse (g_currentloc)));
1397 (void) fflush (g_warningstream);
1399 printError (g_errorstream,
1400 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1401 fileloc_unparse (g_currentloc),
1402 fileloc_unparseRaw (file, line),
1405 /* printCodePoint (); no longer useful */
1410 ** This is confusing, and hardly ever useful.
1414 perror ("Possible system error diagnostic: ");
1425 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1428 (message ("%q: Cannot recover from last bug. "
1429 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1430 fileloc_unparse (g_currentloc)));
1433 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1434 fileloc_free (lastbug);
1435 lastbug = fileloc_copy (g_currentloc);
1442 lclbug (/*@only@*/ cstring s)
1445 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1448 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1454 xllfatalerror (char *srcFile, int srcLine, cstring s)
1457 printError (g_errorstream, s);
1458 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1459 showSourceLoc (srcFile, srcLine);
1464 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1467 (void) fflush (g_warningstream);
1468 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1469 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1470 showSourceLoc (srcFile, srcLine);
1471 (void) fflush (g_warningstream);
1479 return (lclerrors > 0);
1483 lclHadNewError (void)
1485 static int lastcall = 0;
1487 if (lclerrors > lastcall)
1489 lastcall = lclerrors;
1499 lclNumberErrors (void)
1505 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1509 if (ltoken_getCode (t) != NOTTOKEN)
1511 cstring loc = ltoken_unparseLoc (t);
1512 lastfileloclen = cstring_length (loc);
1514 printError (g_warningstream, message ("%q: %q", loc, msg));
1515 showSourceLoc (srcFile, srcLine);
1519 printError (g_warningstream, msg);
1520 showSourceLoc (srcFile, srcLine);
1525 lclplainerror (/*@only@*/ cstring msg)
1528 printError (g_warningstream, msg);
1532 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1534 if (ltoken_getCode (t) != NOTTOKEN)
1536 cstring loc = ltoken_unparseLoc (t);
1537 lastfileloclen = cstring_length (loc);
1538 printError (g_errorstream, message ("%q: %q", loc, msg));
1542 printError (g_errorstream, msg);
1545 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1550 lclplainfatalerror (/*@only@*/ cstring msg)
1552 (void) fflush (g_warningstream);
1553 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1558 lclRedeclarationError (ltoken id)
1560 cstring s = ltoken_getRawString (id);
1563 if (usymtab_existsEither (s))
1565 uentry le = usymtab_lookupEither (s);
1567 lclerror (id, message ("Respecification of %s", s));
1568 llgenindentmsg (message ("Previous specification of %q",
1569 uentry_getName (le)),
1570 uentry_whereSpecified (le));
1574 lclerror (id, message ("Identifier redeclared: %s", s));
1579 void genppllerror (flagcode code, /*@only@*/ cstring s)
1581 if (context_inSuppressZone (g_currentloc))
1587 if (context_getFlag (code))
1589 if (!context_isInCommandLine ())
1591 displayScanClose ();
1596 if (code != FLG_PREPROC)
1598 llsuppresshint ('-', code);
1601 if (!context_isInCommandLine ())
1603 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1613 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1614 /*@only@*/ cstring hint)
1616 if (context_inSuppressZone (g_currentloc))
1619 cstring_free (hint);
1623 if (context_getFlag (code))
1626 context_clearPreprocessing ();
1629 context_setPreprocessing ();
1635 cstring_free (hint);
1640 void ppllerror (/*@only@*/ cstring s)
1642 genppllerror (FLG_PREPROC, s);
1645 void pplldiagmsg (cstring s)
1647 if (!context_isInCommandLine ())
1649 displayScanClose ();
1651 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1659 void loadllmsg (cstring s)
1661 displayScanClose ();
1663 displayScanOpen (cstring_makeLiteral ("< ."));
1666 static void llreportparseerror (/*@only@*/ cstring s)
1668 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1674 llerror (FLG_SYNTAX, s);
1676 fileloc_free (lastparseerror);
1677 lastparseerror = fileloc_copy (g_currentloc);
1681 bool xcppoptgenerror (char *srcFile, int srcLine,
1683 /*@only@*/ cstring s,
1687 fileloc loc = cppReader_getLoc (pfile);
1689 if (context_flagOn (o, loc))
1691 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1693 cppReader_printContainingFiles (pfile);
1707 bool xlloptgenerror (char *srcFile, int srcLine,
1708 flagcode o, /*@only@*/ cstring s, fileloc loc)
1710 DPRINTF (("xllopt: %s", s));
1712 if (llrealerror (srcFile, srcLine, s, loc))
1714 DPRINTF (("Here we are!"));
1715 llsuppresshint ('-', o);
1717 flagcode_recordError (o);
1722 DPRINTF (("Suppressed!"));
1723 flagcode_recordSuppressed (o);
1728 bool xoptgenerror2 (char *srcFile, int srcLine,
1729 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1731 if (context_suppressFlagMsg (f1, loc))
1733 flagcode_recordSuppressed (f1);
1738 if (context_suppressFlagMsg (f2, loc))
1740 flagcode_recordSuppressed (f2);
1745 if (llrealerror (srcFile, srcLine, s, loc))
1747 llsuppresshint2 ('-', f1, f2);
1748 flagcode_recordError (f2);
1754 flagcode_recordSuppressed (f2);
1762 bool xoptgenerror2n (char *srcFile, int srcLine,
1763 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1766 if (context_suppressFlagMsg (f1, loc))
1768 flagcode_recordSuppressed (f1);
1773 if (context_suppressNotFlagMsg (f2, loc))
1775 flagcode_recordSuppressed (f2);
1780 if (llrealerror (srcFile, srcLine, s, loc))
1782 llsuppresshint ('+', f2);
1783 flagcode_recordError (f2);
1788 flagcode_recordSuppressed (f2);
1794 bool xllnoptgenerror (char *srcFile, int srcLine,
1795 flagcode o, /*@only@*/ cstring s, fileloc loc)
1797 if (llrealerror (srcFile, srcLine, s, loc))
1799 llsuppresshint ('+', o);
1800 flagcode_recordError (o);
1805 flagcode_recordSuppressed (o);
1809 void xllparseerror (char *srcFile, int srcLine, cstring s)
1811 if (context_getFlag (FLG_TRYTORECOVER))
1815 if (parseerrorcount > GIVEUPPARSE)
1817 if (cstring_isDefined (s))
1819 xllfatalerror (srcFile, srcLine,
1820 message ("%q: Parse Error: %q. "
1821 "Too many errors, giving up.",
1822 fileloc_unparse (g_currentloc), s));
1826 xllfatalerror (srcFile, srcLine,
1827 message ("%q: Parse Error. Too many errors, giving up.",
1828 fileloc_unparse (g_currentloc)));
1833 if (cstring_isDefined (s))
1835 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1837 showSourceLoc (srcFile, srcLine);
1841 llreportparseerror (message ("Parse Error. Attempting to continue."));
1842 showSourceLoc (srcFile, srcLine);
1850 if (cstring_isDefined (s))
1852 msg = message ("Parse Error: %q.", s);
1856 msg = message ("Parse Error.");
1861 message ("%q: %s (For help on parse errors, "
1862 "see splint -help parseerrors.)",
1863 fileloc_unparse (g_currentloc), msg));
1867 bool xfsgenerror (char *srcFile, int srcLine,
1868 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1870 if (flagSpec_isOn (fs, fl))
1872 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1874 llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1875 flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1880 flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1886 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1892 bool doCheck (bool x, cstring pred, cstring file, int line)
1895 llbug (message ("%q: Check Failed: %s",
1896 fileloc_unparseRaw (file, line),
1903 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1908 #ifndef HAVE_STRERROR
1911 result = strerror (errnum);
1914 /* VAXCRTL's strerror() takes an optional second argument, which only
1915 matters when the first argument is EVMSERR. However, it's simplest
1916 just to pass it unconditionally. `vaxc$errno' is declared in
1917 <errno.h>, and maintained by the library in parallel with `errno'.
1918 We assume that caller's `errnum' either matches the last setting of
1919 `errno' by the library or else does not have the value `EVMSERR'. */
1921 result = strerror (errnum, vaxc$errno);
1926 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1929 return cstring_fromChars (result);
1932 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1937 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1938 fileloc_unparse (g_currentloc),
1939 fileloc_unparseRaw (file, line),
1951 (void) fflush (g_warningstream);
1952 (void) fflush (g_messagestream);
1955 static bool s_scanOpen = FALSE;
1957 void displayScan (cstring msg)
1959 llassert (!s_scanOpen);
1961 if (context_getFlag (FLG_SHOWSCAN))
1963 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
1964 (void) fflush (g_messagestream);
1970 void displayScanOpen (cstring msg)
1972 llassert (!s_scanOpen);
1975 if (context_getFlag (FLG_SHOWSCAN))
1977 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
1978 (void) fflush (g_messagestream);
1984 void displayScanContinue (/*@temp@*/ cstring msg)
1986 if (context_getFlag (FLG_SHOWSCAN))
1990 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
1991 (void) fflush (g_messagestream);
1996 ** Don't call bug recursively
1999 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2004 void displayScanClose (void)
2008 if (context_getFlag (FLG_SHOWSCAN))
2010 fprintf (g_messagestream, " >\n");
2011 (void) fflush (g_messagestream);
2017 ** Don't call bug recursively
2020 fprintf (stderr, "*** Bug: scan close scan not open\n");