2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
27 ** error reporting procedures
30 # include "lclintMacros.nf"
35 # include "cpperror.h"
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 int 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 ())));
102 if ((context_isPreprocessing () || context_loadingLibrary ())
104 && context_getDebug (FLG_SHOWSCAN))
107 fprintf (stderr, " >\n");
108 s_needsPrepare = FALSE;
114 void closeMessage (void)
116 if (context_isPreprocessing ()
117 && context_getDebug (FLG_SHOWSCAN))
120 fprintf (stderr, "< more preprocessing .");
122 llassertprotect (!s_needsPrepare);
123 s_needsPrepare = TRUE;
132 llmsg (/*@only@*/ cstring s)
134 context_setNeednl ();
136 printMessage (g_msgstream, s);
141 lldiagmsg (/*@only@*/ cstring s)
143 context_setNeednl ();
145 printMessage (stderr, s);
150 llmsgplain (/*@only@*/ cstring s)
152 context_setNeednl ();
154 printMessage (g_msgstream, s);
158 void llerror_flagWarning (cstring s)
160 if (context_getFlag (FLG_WARNFLAGS))
164 if (fileloc_isBuiltin (g_currentloc))
166 llmsg (message ("Warning: %q", s));
170 llgenmsg (message ("Warning: %q", s), g_currentloc);
180 llgenhint (/*@only@*/ cstring s) /*@modifies g_msgstream@*/
182 int indent = context_getIndentSpaces () - 1;
184 if (indent < 0) indent = 0;
186 context_setNeednl ();
187 printIndentMessage (g_msgstream, s, indent);
193 if (context_getFlag (FLG_HINTS) &&
194 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
205 llshowhint (flagcode f)
207 if (context_getFlag (FLG_HINTS))
209 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
211 cstring desc = flagcodeHint (f);
213 if (cstring_isDefined (desc))
215 llgenhint (cstring_copy (desc));
222 llsuppresshint2 (char c, flagcode f1, flagcode f2)
225 if (context_getFlag (FLG_HINTS))
227 if ((flagcode_numReported (f1) == 0
228 || flagcode_numReported (f2) == 0)
229 || context_getFlag (FLG_FORCEHINTS))
231 cstring desc = flagcodeHint (f1);
232 context_setNeednl ();
235 if (cstring_isUndefined (desc))
237 desc = flagcodeHint (f2);
240 if (flagcode_isNamePrefixFlag (f1))
245 if (flagcode_isNamePrefixFlag (f2))
252 if (cstring_isDefined (desc))
254 llgenhint (message ("%s (Setting %h%s will suppress message)", desc,
256 flagcode_unparse (f1)));
260 llgenhint (message ("(Setting %h%s will suppress message)",
261 c, flagcode_unparse (f1)));
266 if (cstring_isDefined (desc))
268 llgenhint (message ("%s (Setting either %h%s or %h%s will suppress message)", desc,
270 flagcode_unparse (f1),
272 flagcode_unparse (f2)));
276 llgenhint (message ("(Setting either %h%s or %h%s will suppress message)", c,
277 flagcode_unparse (f1),
278 c, flagcode_unparse (f2)));
286 llsuppresshint (char c, flagcode f)
288 if (context_getFlag (FLG_HINTS))
290 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
292 cstring desc = flagcodeHint (f);
293 context_setNeednl ();
296 if (flagcode_isNamePrefixFlag (f))
301 if (cstring_isDefined (desc))
303 llgenhint (message ("%s (%h%s will suppress message)", desc, c,
304 flagcode_unparse (f)));
308 llgenhint (message ("(%h%s will suppress message)", c,
309 flagcode_unparse (f)));
316 llnosuppresshint (flagcode f)
318 if (context_getFlag (FLG_FORCEHINTS))
320 cstring desc = flagcodeHint (f);
321 context_setNeednl ();
324 if (cstring_isDefined (desc))
326 printError (g_msgstream, message (" %s", desc));
331 /*@constant int MAXSEARCH; @*/
332 # define MAXSEARCH 20
334 /*@constant int MINLINE; @*/
337 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
340 mstring_split (/*@returned@*/ char **sp,
341 /*@out@*/ nd_charp *tp,
342 int maxline, /*@in@*/ int *indentchars)
351 DPRINTF (("Split: %s / %d", *sp, maxline));
353 if (maxline < MINLINELEN)
355 maxline = MINLINELEN;
358 if (*indentchars > 0)
360 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
364 nl = strchr (s, '\n');
369 ** if there is a newline in first maxline characters, split there
370 ** if line len is <= maxline, return no split
371 ** if there is a ':' or ';' followed by ' ' in first maxline characters,
372 ** split there unless the ' ' is followed by a '}', then
374 ** of the ';' is inside quotation marks
375 ** if there is a space or tab in last maxsearch characters, split there
376 ** else, split at maxline
378 ** special code: slash [1-9] after a newline means indent the rest <n> chars
382 if ((nl != NULL) && ((nl - s) < maxline))
389 llassertprotect (*tp == NULL || (*tp > osp));
393 if (*t >= '\1' && *t <= '\7')
395 *indentchars += (int) (*t - '\1') + 1;
402 else if (size_toInt (strlen (s)) < maxline)
404 llassertprotect (*tp == NULL || (*tp > osp));
411 char *lcolon, *lsemi, *splitat;
419 lcolon = strrchr (s, ':');
420 lsemi = strrchr (s, ';');
423 splitat = maxcp (lcolon, lsemi);
425 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
426 && *(splitat) != '\0'
427 && *(splitat + 1) == ' '
428 && (*(splitat + 2) != '}' && (*(splitat + 2) != '\0')))
430 *(splitat + 1) = '\0';
433 llassertprotect (*tp == NULL || (*tp > osp));
437 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
443 if (*t != ' ' && *t != '\t')
445 llassertprotect (maxline > 0);
446 t = mstring_copy (s + maxline);
447 *(s + maxline) = '\0';
452 llassertprotect (*tp == NULL || (*tp > osp));
456 mstring_markFree (t);
458 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
467 if (*t == '\0') return;
470 ** returns unqualified as only
476 /* Hack to prevent error case for wierd strings. */
482 llassertprotect (*tp == NULL || (*tp > osp));
493 void limitmessage (/*@only@*/ cstring s, fileloc loc)
495 if (mcount > context_getLimit () + 1)
501 cstring flstring = fileloc_unparse (loc);
503 lastfileloclen = cstring_length (flstring);
504 cstring_free (saveOneMessage);
505 saveOneMessage = message ("%q: %q", flstring, s);
509 static int parseerrorcount = 0;
511 void cleanupMessages ()
515 if (context_unlimitedMessages ())
521 int unprinted = mcount - context_getLimit ();
525 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
528 printError (g_msgstream, saveOneMessage);
530 saveOneMessage = cstring_undefined;
534 if (cstring_isDefined (saveOneMessage))
536 /* cstring_free (saveOneMessage); */
537 saveOneMessage = cstring_undefined;
540 fprintf (g_msgstream, "%s: (%d more similar errors unprinted)\n",
541 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
542 mcount - context_getLimit ());
551 llgenmsg (/*@only@*/ cstring s, fileloc fl)
553 cstring flstring = fileloc_unparse (fl);
554 lastfileloclen = cstring_length (flstring);
557 (void) printError (g_msgstream, message ("%q: %q", flstring, s));
562 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
564 cstring flstring = fileloc_unparse (fl);
567 (void) printIndentMessage (g_msgstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
572 llgenindentmsgnoloc (/*@only@*/ cstring s)
575 (void) printIndentMessage (g_msgstream, s, context_getIndentSpaces ());
580 llgentypeerroraux (char *srcFile, int srcLine,
581 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
582 /*@only@*/ cstring s, fileloc fl)
584 cstring hint = cstring_undefined;
585 flagcode code = ocode;
586 flagcode hcode = INVALID_FLAG;
590 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
591 flagcode_unparse (ocode),
592 exprNode_unparse (e1), exprNode_unparse (e2),
593 ctype_unparse (t1), ctype_unparse (t2)));
595 DPRINTF (("Bool: %s / %s",
596 bool_unparse (ctype_isBool (t1)),
597 bool_unparse (ctype_isBool (t2))));
600 ** Set the flag using the underlying types that didn't match.
603 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
604 ut1 = ctype_baseArrayPtr (ut1);
605 ut2 = ctype_baseArrayPtr (ut2);
608 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
609 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
611 hcode = FLG_FLOATDOUBLE;
613 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
614 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
616 hcode = FLG_CHARINTLITERAL;
618 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
619 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
621 hcode = FLG_NUMLITERAL;
623 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
624 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
625 /* evs 2000-07-24: was ctype_isDirectBool */
629 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
630 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
634 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
635 || (ctype_isChar (ut1) && ctype_isChar (ut2))
636 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
638 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
640 hcode = FLG_IGNORESIGNS;
644 hcode = FLG_IGNOREQUALS;
647 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
649 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
651 hcode = FLG_MATCHANYINTEGRAL;
653 else if (ctype_match (ut2, ctype_ulint))
655 hcode = FLG_LONGUNSIGNEDINTEGRAL;
657 else if (ctype_match (ut2, ctype_lint))
659 hcode = FLG_LONGINTEGRAL;
661 else if (ctype_isInt (ut2))
663 hcode = FLG_MATCHANYINTEGRAL;
670 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
672 ctype tr = ctype_realType (ut1);
674 if (ctype_isArbitraryIntegral (tr))
676 hcode = FLG_MATCHANYINTEGRAL;
678 else if (ctype_match (ut1, ctype_ulint))
680 if (ctype_isUnsignedIntegral (tr))
682 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
684 else if (ctype_isSignedIntegral (tr))
690 hcode = FLG_LONGUNSIGNEDINTEGRAL;
693 else if (ctype_match (ut1, ctype_lint))
695 if (ctype_isSignedIntegral (tr))
697 hcode = FLG_LONGSIGNEDINTEGRAL;
699 else if (ctype_isSignedIntegral (tr))
705 hcode = FLG_LONGINTEGRAL;
708 else if (ctype_isInt (ut1))
710 hcode = FLG_MATCHANYINTEGRAL;
722 if (hcode == INVALID_FLAG)
724 DPRINTF (("[%s] %s - %s / %s",
726 bool_unparse (ctype_isEnum (ut1)),
727 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
728 bool_unparse (ctype_isInt (ut2))));
730 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
732 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
733 ctype ct = uentry_getType (ue1);
735 if (ctype_match (ct, ut2))
738 hint = message ("Underlying types match, but %s is an "
739 "abstract type that is not accessible here.",
743 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
745 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
746 ctype ct = uentry_getType (ue);
748 if (ctype_match (ct, ut1))
751 hint = message ("Underlying types match, but %s is an "
752 "abstract type that is not accessible here.",
758 ; /* Not an abstract mismatch. */
762 if (hcode == INVALID_FLAG)
764 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
765 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
769 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
770 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
774 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
775 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
777 hcode = FLG_CHARUNSIGNEDCHAR;
779 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
781 hcode = FLG_RELAXTYPES;
782 DPRINTF (("Setting relax types!"));
786 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
787 ctype_unparse (ut2)));
792 if (cstring_isDefined (hint))
794 if (!context_suppressFlagMsg (ocode, fl))
796 return llgenhinterror (code, s, hint, fl);
807 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
809 if (hcode != INVALID_FLAG && hcode != ocode)
817 llsuppresshint ('-', code);
820 flagcode_recordError (code);
829 xllgentypeerror (char *srcFile, int srcLine,
830 ctype t1, exprNode e1, ctype t2, exprNode e2,
831 /*@only@*/ cstring s, fileloc fl)
833 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
837 xllgenformattypeerror (char *srcFile, int srcLine,
838 ctype t1, exprNode e1, ctype t2, exprNode e2,
839 /*@only@*/ cstring s, fileloc fl)
841 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
843 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
853 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
855 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
857 llnosuppresshint (o);
858 flagcode_recordError (o);
864 flagcode_recordSuppressed (o);
870 xllgenhinterror (char *srcFile, int srcLine,
871 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
874 if (!context_suppressFlagMsg (o, fl))
876 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
878 flagcode_recordError (o);
880 if (context_getFlag (FLG_HINTS))
901 flagcode_recordSuppressed (o);
906 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
908 return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
912 llgenerroraux (char *srcFile, int srcLine,
913 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
915 if (context_inSuppressZone (fl))
921 if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
929 xllforceerror (char *srcFile, int srcLine,
930 flagcode code, /*@only@*/ cstring s, fileloc fl)
932 flagcode_recordError (code);
934 if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
943 llgenerrorreal (char *srcFile, int srcLine,
944 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
948 /* duplicate message (rescanning a header file */
950 if (!messageLog_add (context_messageLog (), fl, s))
952 DPRINTF (("Duplicate message suppressed! %s / %s",
953 fileloc_unparse (fl), s));
959 ** If herald has not been displayed, display it before the first message.
964 if (iserror) context_hasError ();
966 if (context_unlimitedMessages ())
973 ** suppress excessive messages:
978 char *sc = cstring_toCharsSafe (s);
979 char *tmpmsg = strchr (sc, ':');
987 char *savechar = tmpmsg;
993 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
996 if (mcount == (context_getLimit () + 1))
998 limitmessage (s, fl);
1002 if (mcount > (context_getLimit ()))
1012 cstring_free (lastmsg);
1013 lastmsg = cstring_fromCharsNew (tmpmsg);
1017 DPRINTF (("Here..."));
1019 if (context_hasAliasAnnote ())
1021 char *sc = cstring_toCharsSafe (s);
1022 char *fcolon = strchr (sc, ':');
1023 cstring a = context_getAliasAnnote ();
1028 s = message ("%q (%q)", s, a);
1035 afterColon = cstring_fromCharsNew (fcolon + 1);
1037 s = message ("%q (%q):%q", s, a, afterColon);
1041 if (context_hasMessageAnnote ())
1043 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1048 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1049 s = message ("%q (%q)", s, context_getMessageAnnote ());
1050 /*@=dependenttrans@*/
1057 afterColon = cstring_fromCharsNew (fcolon + 1);
1059 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1060 s = message ("%q (%q):%q", s,
1061 context_getMessageAnnote (), afterColon);
1062 /*@=dependenttrans@*/
1066 context_setNeednl ();
1069 if (context_showFunction ())
1071 cstring fname = fileloc_unparseFilename (g_currentloc);
1073 if (context_inIterDef ())
1075 fprintf (g_msgstream, "%s: (in iter %s)\n",
1076 cstring_toCharsSafe (fname),
1077 cstring_toCharsSafe (context_inFunctionName ()));
1079 else if (context_inIterEnd ())
1081 fprintf (g_msgstream, "%s: (in iter finalizer %s)\n",
1082 cstring_toCharsSafe (fname),
1083 cstring_toCharsSafe (context_inFunctionName ()));
1085 else if (context_inMacro ())
1087 fprintf (g_msgstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1088 cstring_toCharsSafe (context_inFunctionName ()));
1092 fprintf (g_msgstream, "%s: (in function %s)\n",
1093 cstring_toCharsSafe (fname),
1094 cstring_toCharsSafe (context_inFunctionName ()));
1097 cstring_free (fname);
1098 context_setShownFunction ();
1101 flstring = fileloc_unparse (fl);
1102 lastfileloclen = cstring_length (flstring);
1106 printError (g_msgstream, message (" %q: %q", flstring, s));
1110 printError (g_msgstream, message ("%q: %q", flstring, s));
1113 showSourceLoc (srcFile, srcLine);
1120 ** message contains no '\n'
1121 ** message fits in one line: print it
1122 ** message fits in two lines with 3-space indent after fileloc: print it
1123 ** split line with 5-space indent from left margin: print it
1128 void printMessage (FILE *stream, /*@only@*/ cstring s)
1130 printIndentMessage (stream, s, 0);
1134 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1136 static bool inbody = FALSE;
1137 int maxlen = context_getLineLen ();
1138 char *s = cstring_toCharsSafe (sc);
1141 llassertprotect (!inbody);
1149 llassertprotect (st != olds);
1151 mstring_split (&st, &t, maxlen, &indent);
1152 fprintf (stream, "%s\n", st);
1153 llassertprotect (t != s);
1155 } while (s != NULL) ;
1162 void printError (FILE *stream, /*@only@*/ cstring sc)
1164 int maxlen = context_getLineLen ();
1165 int nspaces = lastfileloclen + 5;
1166 int nextlen = maxlen - nspaces;
1167 int len = cstring_length (sc);
1169 char *s = cstring_toCharsSafe (sc);
1173 DPRINTF (("Print error: [%s]", sc));
1175 if (len < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1177 mstring_split (&s, &t, maxlen, &indent);
1179 fprintf (stream, "%s\n", s);
1183 len = mstring_length (t);
1185 if (len < (maxlen - 3) && (strchr (t, '\n') == NULL)
1186 && len > (nextlen - 1))
1188 fprintf (stream, " %s\n", t);
1192 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1195 for (i = 0; i < nspaces; i++)
1200 spaces[nspaces] = '\0';
1205 mstring_split (&st, &t, nextlen, &indent);
1206 fprintf (stream, "%s%s\n", spaces, st);
1215 DPRINTF (("Here 1: [%s]", sc));
1217 if (len < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1219 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1221 if (nspaces < 1) nspaces = 1;
1223 nextlen = maxlen - nspaces;
1225 mstring_split (&s, &t, maxlen, &indent);
1227 fprintf (stream, "%s\n", s);
1231 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1234 for (i = 0; i < nspaces; i++)
1239 spaces[nspaces] = '\0';
1245 mstring_split (&st, &t, nextlen, &indent);
1246 fprintf (stream, "%s%s\n", spaces, st);
1255 nextlen = maxlen - nspaces;
1257 DPRINTF (("Here 2: [%s]", s));
1258 mstring_split (&s, &t, maxlen, &indent);
1259 DPRINTF (("Here 3: [%s] [%s]", s, t));
1261 fprintf (stream, "%s\n", s);
1265 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1268 for (i = 0; i < nspaces; i++)
1273 spaces[nspaces] = '\0';
1278 DPRINTF (("Loop: [%s]", t));
1279 mstring_split (&st, &t, nextlen, &indent);
1280 DPRINTF (("Split: [%s] [%s]", st, t));
1281 fprintf (stream, "%s%s\n", spaces, st);
1282 DPRINTF (("Next..."));
1295 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1298 printError (stderr, message ("%q: *** Fatal bug: %q",
1299 fileloc_unparse (g_currentloc), s));
1300 showSourceLoc (srcFile, srcLine);
1308 lclfatalbug (char *msg)
1312 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1320 checkParseError (void)
1322 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1324 llfatalerror (message ("%q: Cannot recover from parse error.",
1325 fileloc_unparse (g_currentloc)));
1329 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1332 static int numbugs = 0;
1333 static bool inbug = FALSE;
1337 cstring temps = fileloc_unparseRaw (file, line);
1339 fprintf (stderr, "%s: Recursive bug detected: %s\n",
1340 cstring_toCharsSafe (temps),
1341 cstring_toCharsSafe (s));
1342 cstring_free (temps);
1353 if (fileloc_isRealLib (g_currentloc))
1355 DPRINTF (("Here we are!"));
1356 llfatalerror (message ("%q: Library file appears to be corrupted. Error: %q: %s",
1357 fileloc_unparse (g_currentloc),
1358 fileloc_unparseRaw (file, line),
1363 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1365 llfatalerror (message ("%q: Cannot recover from parse error.",
1366 fileloc_unparse (g_currentloc)));
1369 (void) fflush (g_msgstream);
1370 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1371 fileloc_unparse (g_currentloc),
1372 fileloc_unparseRaw (file, line),
1376 (void) fflush (stderr);
1379 perror ("Possible system error diagnostic: ");
1381 (void) fflush (stderr);
1387 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1389 llfatalerror (message ("%q: Cannot recover from last bug. (If you really want Splint to try to continue, use -bugslimit <n>.)",
1390 fileloc_unparse (g_currentloc)));
1393 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
1394 fileloc_free (lastbug);
1395 lastbug = fileloc_copy (g_currentloc);
1398 (void) fflush (stderr);
1404 lclbug (/*@only@*/ cstring s)
1407 printError (stderr, message ("*** Internal Bug: %q", s));
1410 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
1416 llfatalerror (cstring s)
1419 printError (stderr, s);
1420 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1425 llfatalerrorLoc (/*@only@*/ cstring s)
1428 (void) fflush (g_msgstream);
1429 printError (stderr, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1430 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1431 (void) fflush (g_msgstream);
1439 return (lclerrors > 0);
1443 lclHadNewError (void)
1445 static int lastcall = 0;
1447 if (lclerrors > lastcall)
1449 lastcall = lclerrors;
1459 lclNumberErrors (void)
1465 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1469 if (ltoken_getCode (t) != NOTTOKEN)
1471 cstring loc = ltoken_unparseLoc (t);
1473 lastfileloclen = cstring_length (loc);
1475 printError (g_msgstream, message ("%q: %q", loc, msg));
1476 showSourceLoc (srcFile, srcLine);
1480 printError (g_msgstream, msg);
1481 showSourceLoc (srcFile, srcLine);
1486 lclplainerror (/*@only@*/ cstring msg)
1490 printError (g_msgstream, msg);
1494 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1497 (void) fflush (g_msgstream);
1498 printError (stderr, cstring_makeLiteral ("*** Cannot continue"));
1503 lclplainfatalerror (/*@only@*/ cstring msg)
1505 (void) fflush (g_msgstream);
1506 printError (stderr, message ("*** Cannot continue: %q", msg));
1511 lclRedeclarationError (ltoken id)
1513 cstring s = ltoken_getRawString (id);
1516 if (usymtab_existsEither (s))
1518 uentry le = usymtab_lookupEither (s);
1520 lclerror (id, message ("Respecification of %s", s));
1521 llgenindentmsg (message ("Previous specification of %q",
1522 uentry_getName (le)),
1523 uentry_whereSpecified (le));
1527 lclerror (id, message ("Identifier redeclared: %s", s));
1532 void genppllerror (flagcode code, /*@only@*/ cstring s)
1534 if (context_inSuppressZone (g_currentloc))
1540 if (context_getFlag (code))
1542 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
1544 fprintf (g_msgstream, " >\n");
1549 if (code != FLG_PREPROC)
1551 llsuppresshint ('-', code);
1554 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
1556 fprintf (stderr, "< more preprocessing .");
1566 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1567 /*@only@*/ cstring hint)
1569 if (context_inSuppressZone (g_currentloc))
1572 cstring_free (hint);
1576 if (context_getFlag (code))
1579 context_clearPreprocessing ();
1582 context_setPreprocessing ();
1588 cstring_free (hint);
1593 void ppllerror (/*@only@*/ cstring s)
1595 genppllerror (FLG_PREPROC, s);
1598 void pplldiagmsg (cstring s)
1600 if (context_getDebug (FLG_SHOWSCAN) && !context_isInCommandLine ())
1602 fprintf (stderr, " >\n");
1604 fprintf (stderr, "< more preprocessing .");
1612 void loadllmsg (cstring s)
1614 if (context_getDebug (FLG_SHOWSCAN))
1616 fprintf (stderr, " >\n");
1618 fprintf (stderr, "< .");
1626 static void llreportparseerror (/*@only@*/ cstring s)
1628 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1634 llerror (FLG_SYNTAX, s);
1636 fileloc_free (lastparseerror);
1637 lastparseerror = fileloc_copy (g_currentloc);
1641 bool xcppoptgenerror (char *srcFile, int srcLine,
1643 /*@only@*/ cstring s,
1647 fileloc loc = cppReader_getLoc (pfile);
1649 if (context_flagOn (o, loc))
1651 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1653 cppReader_printContainingFiles (pfile);
1667 bool xlloptgenerror (char *srcFile, int srcLine,
1668 flagcode o, /*@only@*/ cstring s, fileloc loc)
1670 DPRINTF (("xllopt: %s", s));
1672 if (llrealerror (srcFile, srcLine, s, loc))
1674 DPRINTF (("Here we are!"));
1675 llsuppresshint ('-', o);
1677 flagcode_recordError (o);
1682 DPRINTF (("Suppressed!"));
1683 flagcode_recordSuppressed (o);
1688 bool xoptgenerror2 (char *srcFile, int srcLine,
1689 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1691 if (context_suppressFlagMsg (f1, loc))
1693 flagcode_recordSuppressed (f1);
1698 if (context_suppressFlagMsg (f2, loc))
1700 flagcode_recordSuppressed (f2);
1705 if (llrealerror (srcFile, srcLine, s, loc))
1707 llsuppresshint2 ('-', f1, f2);
1708 flagcode_recordError (f2);
1714 flagcode_recordSuppressed (f2);
1722 bool xoptgenerror2n (char *srcFile, int srcLine,
1723 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1726 if (context_suppressFlagMsg (f1, loc))
1728 flagcode_recordSuppressed (f1);
1733 if (context_suppressNotFlagMsg (f2, loc))
1735 flagcode_recordSuppressed (f2);
1740 if (llrealerror (srcFile, srcLine, s, loc))
1742 llsuppresshint ('+', f2);
1743 flagcode_recordError (f2);
1748 flagcode_recordSuppressed (f2);
1754 bool xllnoptgenerror (char *srcFile, int srcLine,
1755 flagcode o, /*@only@*/ cstring s, fileloc loc)
1757 if (llrealerror (srcFile, srcLine, s, loc))
1759 llsuppresshint ('+', o);
1760 flagcode_recordError (o);
1765 flagcode_recordSuppressed (o);
1769 void llparseerror (cstring s)
1771 if (context_getFlag (FLG_TRYTORECOVER))
1775 if (parseerrorcount > GIVEUPPARSE)
1777 if (cstring_isDefined (s))
1779 llfatalerror (message ("%q: Parse Error: %q. "
1780 "Too many errors, giving up.",
1781 fileloc_unparse (g_currentloc), s));
1785 llfatalerror (message ("%q: Parse Error. Too many errors, giving up.",
1786 fileloc_unparse (g_currentloc)));
1791 if (cstring_isDefined (s))
1793 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1798 llreportparseerror (message ("Parse Error. Attempting to continue."));
1806 if (cstring_isDefined (s))
1808 msg = message ("Parse Error: %q.", s);
1812 msg = message ("Parse Error.");
1816 (message ("%q: %s (For help on parse errors, "
1817 "see lclint -help parseerrors.)",
1818 fileloc_unparse (g_currentloc), msg));
1822 bool xfsgenerror (char *srcFile, int srcLine,
1823 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1825 if (flagSpec_isOn (fs, fl))
1827 if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1829 llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1830 flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1835 flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1841 flagcode_recordSuppressed (flagSpec_getDominant (fs));
1847 bool doCheck (bool x, cstring pred, cstring file, int line)
1850 llbug (message ("%q: Check Failed: %s",
1851 fileloc_unparseRaw (file, line),
1858 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1863 #ifndef HAVE_STRERROR
1866 result = strerror (errnum);
1869 /* VAXCRTL's strerror() takes an optional second argument, which only
1870 matters when the first argument is EVMSERR. However, it's simplest
1871 just to pass it unconditionally. `vaxc$errno' is declared in
1872 <errno.h>, and maintained by the library in parallel with `errno'.
1873 We assume that caller's `errnum' either matches the last setting of
1874 `errno' by the library or else does not have the value `EVMSERR'. */
1876 result = strerror (errnum, vaxc$errno);
1881 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1884 return cstring_fromChars (result);
1887 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1892 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1893 fileloc_unparse (g_currentloc),
1894 fileloc_unparseRaw (file, line),
1906 (void) fflush (g_msgstream);
1907 (void) fflush (stderr);