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_msgstream@*/ ;
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_msgstream@*/ ;
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_msgstream@*/ ;
70 static void showSourceLoc (char *srcFile, int srcLine)
71 /*@modifies g_msgstream@*/
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 (stderr, " *** Please report bug to %s ***\n",
93 /* don't exit (EXIT_FAILURE); */
96 static bool s_needsPrepare = TRUE;
98 void prepareMessage (void)
100 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
103 if ((context_isPreprocessing () || context_loadingLibrary ())
105 && context_getDebug (FLG_SHOWSCAN))
108 fprintf (stderr, " >\n");
109 s_needsPrepare = FALSE;
115 void closeMessage (void)
117 if (context_isPreprocessing ()
118 && context_getDebug (FLG_SHOWSCAN))
121 fprintf (stderr, "< more preprocessing .");
123 llassertprotect (!s_needsPrepare);
124 s_needsPrepare = TRUE;
133 llmsg (/*@only@*/ cstring s)
135 context_setNeednl ();
137 printMessage (g_msgstream, s);
142 lldiagmsg (/*@only@*/ cstring s)
144 static bool inmsg = FALSE;
148 fprintf (stderr, "Recursive message call detected: %s\n", cstring_toCharsSafe (s));
154 context_setNeednl ();
156 printMessage (stderr, s);
163 llmsgplain (/*@only@*/ cstring s)
165 context_setNeednl ();
167 printMessage (g_msgstream, s);
171 void llerror_flagWarning (cstring s)
173 if (context_getFlag (FLG_WARNFLAGS))
177 if (fileloc_isBuiltin (g_currentloc))
179 llmsg (message ("Warning: %q", s));
183 llgenmsg (message ("Warning: %q", s), g_currentloc);
193 llgenhint (/*@only@*/ cstring s) /*@modifies g_msgstream@*/
195 int indent = context_getIndentSpaces () - 1;
197 if (indent < 0) indent = 0;
199 context_setNeednl ();
200 printIndentMessage (g_msgstream, s, indent);
206 if (context_getFlag (FLG_HINTS) &&
207 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
218 llshowhint (flagcode f)
220 if (context_getFlag (FLG_HINTS))
222 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
224 cstring desc = flagcodeHint (f);
226 if (cstring_isDefined (desc))
228 llgenhint (cstring_copy (desc));
235 llsuppresshint2 (char c, flagcode f1, flagcode f2)
238 if (context_getFlag (FLG_HINTS))
240 if ((flagcode_numReported (f1) == 0
241 || flagcode_numReported (f2) == 0)
242 || context_getFlag (FLG_FORCEHINTS))
244 cstring desc = flagcodeHint (f1);
245 context_setNeednl ();
248 if (cstring_isUndefined (desc))
250 desc = flagcodeHint (f2);
253 if (flagcode_isNamePrefixFlag (f1))
258 if (flagcode_isNamePrefixFlag (f2))
265 if (cstring_isDefined (desc))
267 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
269 flagcode_unparse (f1)));
273 llgenhint (message ("(Use %h%s to inhibit warning)",
274 c, flagcode_unparse (f1)));
279 if (cstring_isDefined (desc))
281 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
283 flagcode_unparse (f1),
285 flagcode_unparse (f2)));
289 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
290 flagcode_unparse (f1),
291 c, flagcode_unparse (f2)));
299 llsuppresshint (char c, flagcode f)
301 if (context_getFlag (FLG_HINTS))
303 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
305 cstring desc = flagcodeHint (f);
306 context_setNeednl ();
309 if (flagcode_isNamePrefixFlag (f))
314 if (cstring_isDefined (desc))
316 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
317 flagcode_unparse (f)));
321 llgenhint (message ("(Use %h%s to inhibit warning)", c,
322 flagcode_unparse (f)));
329 llnosuppresshint (flagcode f)
331 if (context_getFlag (FLG_FORCEHINTS))
333 cstring desc = flagcodeHint (f);
334 context_setNeednl ();
337 if (cstring_isDefined (desc))
339 printError (g_msgstream, message (" %s", desc));
344 /*@constant int MAXSEARCH; @*/
345 # define MAXSEARCH 20
347 /*@constant int MINLINE; @*/
350 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
353 mstring_split (/*@returned@*/ char **sp,
354 /*@out@*/ nd_charp *tp,
355 int maxline, /*@in@*/ int *indentchars)
364 DPRINTF (("Split: %s / %d", *sp, maxline));
366 if (maxline < MINLINELEN)
368 maxline = MINLINELEN;
371 if (*indentchars > 0)
373 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
377 nl = strchr (s, '\n');
382 ** if there is a newline in first maxline characters, split there
383 ** if line len is <= maxline, return no split
384 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
385 ** split there unless the ' ' is followed by a '}', then
387 ** of the ';' is inside quotation marks
388 ** if there is a space or tab in last maxsearch characters, split there
389 ** else, split at maxline
391 ** special code: slash [1-9] after a newline means indent the rest <n> chars
395 if ((nl != NULL) && ((nl - s) < maxline))
402 llassertprotect (*tp == NULL || (*tp > osp));
406 if (*t >= '\1' && *t <= '\7')
408 *indentchars += (int) (*t - '\1') + 1;
415 else if (size_toInt (strlen (s)) < maxline)
417 llassertprotect (*tp == NULL || (*tp > osp));
424 char *lcolon, *lsemi, *lcomma;
433 lcolon = strrchr (s, ':');
434 lsemi = strrchr (s, ';');
435 lcomma = strrchr (s, ',');
439 splitat = maxcp (lcolon, lsemi);
441 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
442 && *(splitat) != '\0'
443 && *(splitat + 1) == ' '
444 && (*(splitat + 2) != '}'
445 && *(splitat + 2) != ','
446 && (*(splitat + 2) != '\0')))
448 *(splitat + 1) = '\0';
451 llassertprotect (*tp == NULL || (*tp > osp));
455 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
459 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
460 && *(splitat) != '\0'
461 && *(splitat + 1) == ' '
462 && (*(splitat + 2) != '}'
463 && (*(splitat + 2) != '\0')))
465 *(splitat + 1) = '\0';
468 llassertprotect (*tp == NULL || (*tp > osp));
473 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
479 if (*t != ' ' && *t != '\t')
481 llassertprotect (maxline > 0);
482 t = mstring_copy (s + maxline);
483 *(s + maxline) = '\0';
488 llassertprotect (*tp == NULL || (*tp > osp));
492 mstring_markFree (t);
494 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
503 if (*t == '\0') return;
506 ** returns unqualified as only
512 /* Hack to prevent error case for wierd strings. */
518 llassertprotect (*tp == NULL || (*tp > osp));
529 void limitmessage (/*@only@*/ cstring s, fileloc loc)
531 if (mcount > context_getLimit () + 1)
537 cstring flstring = fileloc_unparse (loc);
539 lastfileloclen = cstring_length (flstring);
540 cstring_free (saveOneMessage);
541 saveOneMessage = message ("%q: %q", flstring, s);
545 static int parseerrorcount = 0;
547 void cleanupMessages ()
551 if (context_unlimitedMessages ())
557 int unprinted = mcount - context_getLimit ();
561 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
564 printError (g_msgstream, saveOneMessage);
566 saveOneMessage = cstring_undefined;
570 if (cstring_isDefined (saveOneMessage))
572 /* cstring_free (saveOneMessage); */
573 saveOneMessage = cstring_undefined;
576 fprintf (g_msgstream, "%s: (%d more similar errors unprinted)\n",
577 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
578 mcount - context_getLimit ());
587 llgenmsg (/*@only@*/ cstring s, fileloc fl)
589 cstring flstring = fileloc_unparse (fl);
590 lastfileloclen = cstring_length (flstring);
593 (void) printError (g_msgstream, message ("%q: %q", flstring, s));
598 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
600 cstring flstring = fileloc_unparse (fl);
603 (void) printIndentMessage (g_msgstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
608 llgenindentmsgnoloc (/*@only@*/ cstring s)
611 (void) printIndentMessage (g_msgstream, s, context_getIndentSpaces ());
616 llgentypeerroraux (char *srcFile, int srcLine,
617 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
618 /*@only@*/ cstring s, fileloc fl)
620 cstring hint = cstring_undefined;
621 flagcode code = ocode;
622 flagcode hcode = INVALID_FLAG;
626 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
627 flagcode_unparse (ocode),
628 exprNode_unparse (e1), exprNode_unparse (e2),
629 ctype_unparse (t1), ctype_unparse (t2)));
631 DPRINTF (("Bool: %s / %s",
632 bool_unparse (ctype_isBool (t1)),
633 bool_unparse (ctype_isBool (t2))));
636 ** Set the flag using the underlying types that didn't match.
639 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
640 ut1 = ctype_baseArrayPtr (ut1);
641 ut2 = ctype_baseArrayPtr (ut2);
644 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
645 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
647 hcode = FLG_FLOATDOUBLE;
649 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
650 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
652 hcode = FLG_CHARINTLITERAL;
654 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
655 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
657 hcode = FLG_NUMLITERAL;
659 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
660 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
661 /* evs 2000-07-24: was ctype_isDirectBool */
665 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
666 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
670 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
671 || (ctype_isChar (ut1) && ctype_isChar (ut2))
672 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
674 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
676 hcode = FLG_IGNORESIGNS;
680 hcode = FLG_IGNOREQUALS;
683 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
685 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
687 hcode = FLG_MATCHANYINTEGRAL;
689 else if (ctype_match (ut2, ctype_ulint))
691 hcode = FLG_LONGUNSIGNEDINTEGRAL;
693 else if (ctype_match (ut2, ctype_lint))
695 hcode = FLG_LONGINTEGRAL;
697 else if (ctype_isInt (ut2))
699 hcode = FLG_MATCHANYINTEGRAL;
706 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
708 ctype tr = ctype_realType (ut1);
710 if (ctype_isArbitraryIntegral (tr))
712 hcode = FLG_MATCHANYINTEGRAL;
714 else if (ctype_match (ut1, ctype_ulint))
716 if (ctype_isUnsignedIntegral (tr))
718 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
720 else if (ctype_isSignedIntegral (tr))
726 hcode = FLG_LONGUNSIGNEDINTEGRAL;
729 else if (ctype_match (ut1, ctype_lint))
731 if (ctype_isSignedIntegral (tr))
733 hcode = FLG_LONGSIGNEDINTEGRAL;
735 else if (ctype_isSignedIntegral (tr))
741 hcode = FLG_LONGINTEGRAL;
744 else if (ctype_isInt (ut1))
746 hcode = FLG_MATCHANYINTEGRAL;
758 if (hcode == INVALID_FLAG)
760 DPRINTF (("[%s] %s - %s / %s",
762 bool_unparse (ctype_isEnum (ut1)),
763 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
764 bool_unparse (ctype_isInt (ut2))));
766 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
768 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
769 ctype ct = uentry_getType (ue1);
771 if (ctype_match (ct, ut2))
774 hint = message ("Underlying types match, but %s is an "
775 "abstract type that is not accessible here.",
779 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
781 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
782 ctype ct = uentry_getType (ue);
784 if (ctype_match (ct, ut1))
787 hint = message ("Underlying types match, but %s is an "
788 "abstract type that is not accessible here.",
794 ; /* Not an abstract mismatch. */
798 if (hcode == INVALID_FLAG)
800 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
801 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
805 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
806 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
810 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
811 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
813 hcode = FLG_CHARUNSIGNEDCHAR;
815 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
817 hcode = FLG_RELAXTYPES;
818 DPRINTF (("Setting relax types!"));
822 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
823 ctype_unparse (ut2)));
828 if (cstring_isDefined (hint))
830 if (!context_suppressFlagMsg (ocode, fl))
832 return llgenhinterror (code, s, hint, fl);
843 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
845 if (hcode != INVALID_FLAG && hcode != ocode)
853 llsuppresshint ('-', code);
856 flagcode_recordError (code);
865 xllgentypeerror (char *srcFile, int srcLine,
866 ctype t1, exprNode e1, ctype t2, exprNode e2,
867 /*@only@*/ cstring s, fileloc fl)
869 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
873 xllgenformattypeerror (char *srcFile, int srcLine,
874 ctype t1, exprNode e1, ctype t2, exprNode e2,
875 /*@only@*/ cstring s, fileloc fl)
877 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
879 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
889 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
891 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
893 llnosuppresshint (o);
894 flagcode_recordError (o);
900 flagcode_recordSuppressed (o);
906 xllgenhinterror (char *srcFile, int srcLine,
907 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
910 if (!context_suppressFlagMsg (o, fl))
912 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
914 flagcode_recordError (o);
916 if (context_getFlag (FLG_HINTS))
937 flagcode_recordSuppressed (o);
942 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
944 return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
948 llgenerroraux (char *srcFile, int srcLine,
949 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
951 if (context_inSuppressZone (fl))
957 if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
965 xllforceerror (char *srcFile, int srcLine,
966 flagcode code, /*@only@*/ cstring s, fileloc fl)
968 flagcode_recordError (code);
970 if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
979 llgenerrorreal (char *srcFile, int srcLine,
980 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
984 /* duplicate message (rescanning a header file */
986 if (!messageLog_add (context_messageLog (), fl, s))
988 DPRINTF (("Duplicate message suppressed! %s / %s",
989 fileloc_unparse (fl), s));
995 ** If herald has not been displayed, display it before the first message.
1000 if (iserror) context_hasError ();
1002 if (context_unlimitedMessages ())
1009 ** suppress excessive messages:
1014 char *sc = cstring_toCharsSafe (s);
1015 char *tmpmsg = strchr (sc, ':');
1023 char *savechar = tmpmsg;
1029 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1032 if (mcount == (context_getLimit () + 1))
1034 limitmessage (s, fl);
1038 if (mcount > (context_getLimit ()))
1048 cstring_free (lastmsg);
1049 lastmsg = cstring_fromCharsNew (tmpmsg);
1053 DPRINTF (("Here..."));
1055 if (context_hasAliasAnnote ())
1057 char *sc = cstring_toCharsSafe (s);
1058 char *fcolon = strchr (sc, ':');
1059 cstring a = context_getAliasAnnote ();
1064 s = message ("%q (%q)", s, a);
1071 afterColon = cstring_fromCharsNew (fcolon + 1);
1073 s = message ("%q (%q):%q", s, a, afterColon);
1077 if (context_hasMessageAnnote ())
1079 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1084 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1085 s = message ("%q (%q)", s, context_getMessageAnnote ());
1086 /*@=dependenttrans@*/
1093 afterColon = cstring_fromCharsNew (fcolon + 1);
1095 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1096 s = message ("%q (%q):%q", s,
1097 context_getMessageAnnote (), afterColon);
1098 /*@=dependenttrans@*/
1102 context_setNeednl ();
1105 if (context_showFunction ())
1107 cstring fname = fileloc_unparseFilename (g_currentloc);
1109 if (context_inIterDef ())
1111 fprintf (g_msgstream, "%s: (in iter %s)\n",
1112 cstring_toCharsSafe (fname),
1113 cstring_toCharsSafe (context_inFunctionName ()));
1115 else if (context_inIterEnd ())
1117 fprintf (g_msgstream, "%s: (in iter finalizer %s)\n",
1118 cstring_toCharsSafe (fname),
1119 cstring_toCharsSafe (context_inFunctionName ()));
1121 else if (context_inMacro ())
1123 fprintf (g_msgstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1124 cstring_toCharsSafe (context_inFunctionName ()));
1128 fprintf (g_msgstream, "%s: (in function %s)\n",
1129 cstring_toCharsSafe (fname),
1130 cstring_toCharsSafe (context_inFunctionName ()));
1133 cstring_free (fname);
1134 context_setShownFunction ();
1137 flstring = fileloc_unparse (fl);
1138 lastfileloclen = cstring_length (flstring);
1142 printError (g_msgstream, message (" %q: %q", flstring, s));
1146 printError (g_msgstream, message ("%q: %q", flstring, s));
1149 showSourceLoc (srcFile, srcLine);
1156 ** message contains no '\n'
1157 ** message fits in one line: print it
1158 ** message fits in two lines with 3-space indent after fileloc: print it
1159 ** split line with 5-space indent from left margin: print it
1164 void printMessage (FILE *stream, /*@only@*/ cstring s)
1166 printIndentMessage (stream, s, 0);
1170 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1172 static bool inbody = FALSE;
1173 int maxlen = context_getLineLen ();
1174 char *s = cstring_toCharsSafe (sc);
1177 llassertprotect (!inbody);
1185 llassertprotect (st != olds);
1187 mstring_split (&st, &t, maxlen, &indent);
1188 fprintf (stream, "%s\n", st);
1189 llassertprotect (t != s);
1191 } while (s != NULL) ;
1198 void printError (FILE *stream, /*@only@*/ cstring sc)
1200 int maxlen = context_getLineLen ();
1201 size_t nspaces = lastfileloclen + 5;
1202 int nextlen = maxlen - nspaces;
1203 size_t len = cstring_length (sc);
1205 char *s = cstring_toCharsSafe (sc);
1209 DPRINTF (("Print error: [%s]", sc));
1211 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1213 mstring_split (&s, &t, maxlen, &indent);
1215 fprintf (stream, "%s\n", s);
1219 len = mstring_length (t);
1221 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1222 && size_toInt (len) > (nextlen - 1))
1224 fprintf (stream, " %s\n", t);
1228 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1231 for (i = 0; i < size_toInt (nspaces); i++)
1236 spaces[nspaces] = '\0';
1241 mstring_split (&st, &t, nextlen, &indent);
1242 fprintf (stream, "%s%s\n", spaces, st);
1251 DPRINTF (("Here 1: [%s]", sc));
1253 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1255 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1257 if (nspaces < 1) nspaces = 1;
1259 nextlen = maxlen - nspaces;
1261 mstring_split (&s, &t, maxlen, &indent);
1263 fprintf (stream, "%s\n", s);
1267 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1270 for (i = 0; i < size_toInt (nspaces); i++)
1275 spaces[nspaces] = '\0';
1281 mstring_split (&st, &t, nextlen, &indent);
1282 fprintf (stream, "%s%s\n", spaces, st);
1291 nextlen = maxlen - nspaces;
1293 DPRINTF (("Here 2: [%s]", s));
1294 mstring_split (&s, &t, maxlen, &indent);
1295 DPRINTF (("Here 3: [%s] [%s]", s, t));
1297 fprintf (stream, "%s\n", s);
1301 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1304 for (i = 0; i < nspaces; i++)
1309 spaces[nspaces] = '\0';
1314 DPRINTF (("Loop: [%s]", t));
1315 mstring_split (&st, &t, nextlen, &indent);
1316 DPRINTF (("Split: [%s] [%s]", st, t));
1317 fprintf (stream, "%s%s\n", spaces, st);
1318 DPRINTF (("Next..."));
1331 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1334 printError (stderr, message ("%q: *** Fatal bug: %q",
1335 fileloc_unparse (g_currentloc), s));
1336 showSourceLoc (srcFile, srcLine);
1344 lclfatalbug (char *msg)
1348 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1356 checkParseError (void)
1358 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1360 llfatalerror (message ("%q: Cannot recover from parse error.",
1361 fileloc_unparse (g_currentloc)));
1365 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1368 static int numbugs = 0;
1369 static bool inbug = FALSE;
1373 cstring temps = fileloc_unparseRaw (file, line);
1375 fprintf (stderr, "%s: Recursive bug detected: %s\n",
1376 cstring_toCharsSafe (temps),
1377 cstring_toCharsSafe (s));
1378 cstring_free (temps);
1389 if (fileloc_isRealLib (g_currentloc))
1391 DPRINTF (("Here we are!"));
1392 llfatalerror (message ("%q: Library file appears to be corrupted. Error: %q: %s",
1393 fileloc_unparse (g_currentloc),
1394 fileloc_unparseRaw (file, line),
1399 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1401 llfatalerror (message ("%q: Cannot recover from parse error.",
1402 fileloc_unparse (g_currentloc)));
1405 (void) fflush (g_msgstream);
1407 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1408 fileloc_unparse (g_currentloc),
1409 fileloc_unparseRaw (file, line),
1412 /* printCodePoint (); no longer useful */
1414 (void) fflush (stderr);
1418 perror ("Possible system error diagnostic: ");
1421 (void) fflush (stderr);
1427 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1429 llfatalerror (message ("%q: Cannot recover from last bug. (If you really want Splint to try to continue, use -bugslimit <n>.)",
1430 fileloc_unparse (g_currentloc)));
1433 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
1434 fileloc_free (lastbug);
1435 lastbug = fileloc_copy (g_currentloc);
1438 (void) fflush (stderr);
1444 lclbug (/*@only@*/ cstring s)
1447 printError (stderr, message ("*** Internal Bug: %q", s));
1450 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
1456 llfatalerror (cstring s)
1459 printError (stderr, s);
1460 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1465 llfatalerrorLoc (/*@only@*/ cstring s)
1468 (void) fflush (g_msgstream);
1469 printError (stderr, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1470 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1471 (void) fflush (g_msgstream);
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);
1513 lastfileloclen = cstring_length (loc);
1515 printError (g_msgstream, message ("%q: %q", loc, msg));
1516 showSourceLoc (srcFile, srcLine);
1520 printError (g_msgstream, msg);
1521 showSourceLoc (srcFile, srcLine);
1526 lclplainerror (/*@only@*/ cstring msg)
1530 printError (g_msgstream, msg);
1534 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1537 (void) fflush (g_msgstream);
1538 printError (stderr, cstring_makeLiteral ("*** Cannot continue"));
1543 lclplainfatalerror (/*@only@*/ cstring msg)
1545 (void) fflush (g_msgstream);
1546 printError (stderr, message ("*** Cannot continue: %q", msg));
1551 lclRedeclarationError (ltoken id)
1553 cstring s = ltoken_getRawString (id);
1556 if (usymtab_existsEither (s))
1558 uentry le = usymtab_lookupEither (s);
1560 lclerror (id, message ("Respecification of %s", s));
1561 llgenindentmsg (message ("Previous specification of %q",
1562 uentry_getName (le)),
1563 uentry_whereSpecified (le));
1567 lclerror (id, message ("Identifier redeclared: %s", s));
1572 void genppllerror (flagcode code, /*@only@*/ cstring s)
1574 if (context_inSuppressZone (g_currentloc))
1580 if (context_getFlag (code))
1582 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
1584 fprintf (g_msgstream, " >\n");
1589 if (code != FLG_PREPROC)
1591 llsuppresshint ('-', code);
1594 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
1596 fprintf (stderr, "< more preprocessing .");
1606 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1607 /*@only@*/ cstring hint)
1609 if (context_inSuppressZone (g_currentloc))
1612 cstring_free (hint);
1616 if (context_getFlag (code))
1619 context_clearPreprocessing ();
1622 context_setPreprocessing ();
1628 cstring_free (hint);
1633 void ppllerror (/*@only@*/ cstring s)
1635 genppllerror (FLG_PREPROC, s);
1638 void pplldiagmsg (cstring s)
1640 if (context_getDebug (FLG_SHOWSCAN) && !context_isInCommandLine ())
1642 fprintf (stderr, " >\n");
1644 fprintf (stderr, "< more preprocessing .");
1652 void loadllmsg (cstring s)
1654 if (context_getDebug (FLG_SHOWSCAN))
1656 fprintf (stderr, " >\n");
1658 fprintf (stderr, "< .");
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 llparseerror (cstring s)
1811 if (context_getFlag (FLG_TRYTORECOVER))
1815 if (parseerrorcount > GIVEUPPARSE)
1817 if (cstring_isDefined (s))
1819 llfatalerror (message ("%q: Parse Error: %q. "
1820 "Too many errors, giving up.",
1821 fileloc_unparse (g_currentloc), s));
1825 llfatalerror (message ("%q: Parse Error. Too many errors, giving up.",
1826 fileloc_unparse (g_currentloc)));
1831 if (cstring_isDefined (s))
1833 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1838 llreportparseerror (message ("Parse Error. Attempting to continue."));
1846 if (cstring_isDefined (s))
1848 msg = message ("Parse Error: %q.", s);
1852 msg = message ("Parse Error.");
1856 (message ("%q: %s (For help on parse errors, "
1857 "see splint -help parseerrors.)",
1858 fileloc_unparse (g_currentloc), msg));
1862 bool xfsgenerror (char *srcFile, int srcLine,
1863 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1865 if (flagSpec_isOn (fs, fl))
1867 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1869 llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1870 flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1875 flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1881 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1887 bool doCheck (bool x, cstring pred, cstring file, int line)
1890 llbug (message ("%q: Check Failed: %s",
1891 fileloc_unparseRaw (file, line),
1898 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1903 #ifndef HAVE_STRERROR
1906 result = strerror (errnum);
1909 /* VAXCRTL's strerror() takes an optional second argument, which only
1910 matters when the first argument is EVMSERR. However, it's simplest
1911 just to pass it unconditionally. `vaxc$errno' is declared in
1912 <errno.h>, and maintained by the library in parallel with `errno'.
1913 We assume that caller's `errnum' either matches the last setting of
1914 `errno' by the library or else does not have the value `EVMSERR'. */
1916 result = strerror (errnum, vaxc$errno);
1921 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1924 return cstring_fromChars (result);
1927 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1932 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1933 fileloc_unparse (g_currentloc),
1934 fileloc_unparseRaw (file, line),
1946 (void) fflush (g_msgstream);
1947 (void) fflush (stderr);