2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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@*/ ;
45 static bool s_scanOpen = FALSE;
46 static int s_lclerrors = 0;
47 static size_t s_lastfileloclen = 10;
48 static /*@only@*/ cstring s_lastmsg = cstring_undefined;
49 static int s_mcount = 0;
50 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
51 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
52 static /*@only@*/ fileloc lastbug = fileloc_undefined;
53 static bool llgenerrorreal (flagcode p_code,
54 char *p_srcFile, int p_srcLine,
55 /*@only@*/ cstring p_s,
56 /*@temp@*/ cstring p_addtext,
57 fileloc p_fl, bool p_iserror, bool p_indent)
58 /*@modifies g_warningstream@*/ ;
59 static bool llgenerroraux (flagcode p_code, char *p_srcFile, int p_srcLine,
60 /*@only@*/ cstring p_s,
61 /*@temp@*/ cstring p_addtext,
62 fileloc p_fl, bool p_iserror, bool p_indent)
63 /*@modifies g_warningstream@*/ ;
65 static void generateCSV (flagcode p_code, cstring p_s, cstring p_addtext, fileloc p_fl)
66 /*@modifies g_csvstream@*/ ;
68 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
69 /*@globals s_lastfileloclen @*/
70 /*@modifies *p_stream@*/ ;
71 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
72 /*@modifies *p_stream@*/ ;
74 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
76 static void showSourceLoc (char *srcFile, int srcLine)
77 /*@modifies g_warningstream@*/
79 if (context_getFlag (FLG_SHOWSOURCELOC)) {
80 llgenhint (message ("%s:%d: Source code error generation point.",
81 cstring_fromChars (srcFile), srcLine));
86 static /*@null@*/ char *
87 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
96 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
99 /* don't exit (EXIT_FAILURE); */
102 static bool s_needsPrepare = TRUE;
104 void prepareMessage ()
106 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
109 if ((context_isPreprocessing () || context_loadingLibrary ())
111 && context_getFlag (FLG_SHOWSCAN))
115 s_needsPrepare = FALSE;
121 void closeMessage (void)
123 if (context_isPreprocessing ()
124 && context_getFlag (FLG_SHOWSCAN))
127 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
128 llassertprotect (!s_needsPrepare);
129 s_needsPrepare = TRUE;
138 llmsg (/*@only@*/ cstring s)
140 context_setNeednl ();
142 printMessage (g_messagestream, s);
147 lldiagmsg (/*@only@*/ cstring s)
149 static bool inmsg = FALSE;
153 fprintf (g_errorstream,
154 "Recursive message call detected: %s\n",
155 cstring_toCharsSafe (s));
161 context_setNeednl ();
163 printMessage (g_messagestream, s);
170 llmsgplain (/*@only@*/ cstring s)
172 context_setNeednl ();
174 printMessage (g_messagestream, s);
178 void llerror_flagWarning (cstring s)
180 if (context_getFlag (FLG_WARNFLAGS))
182 llgenmsg (s, g_currentloc);
191 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
193 int indent = context_getIndentSpaces () - 1;
195 if (indent < 0) indent = 0;
197 context_setNeednl ();
198 printIndentMessage (g_warningstream, s, indent);
204 if (context_getFlag (FLG_HINTS) &&
205 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
216 llshowhint (flagcode f)
218 if (context_getFlag (FLG_HINTS))
220 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
222 cstring desc = flagcodeHint (f);
224 if (cstring_isDefined (desc))
226 llgenhint (cstring_copy (desc));
233 llsuppresshint2 (char c, flagcode f1, flagcode f2)
236 if (context_getFlag (FLG_HINTS))
238 if ((flagcode_numReported (f1) == 0
239 || flagcode_numReported (f2) == 0)
240 || context_getFlag (FLG_FORCEHINTS))
242 cstring desc = flagcodeHint (f1);
243 context_setNeednl ();
244 s_lastfileloclen = 8;
246 if (cstring_isUndefined (desc))
248 desc = flagcodeHint (f2);
251 if (flagcode_isNamePrefixFlag (f1))
256 if (flagcode_isNamePrefixFlag (f2))
263 if (cstring_isDefined (desc))
265 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
267 flagcode_unparse (f1)));
271 llgenhint (message ("(Use %h%s to inhibit warning)",
272 c, flagcode_unparse (f1)));
277 if (cstring_isDefined (desc))
279 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
281 flagcode_unparse (f1),
283 flagcode_unparse (f2)));
287 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
288 flagcode_unparse (f1),
289 c, flagcode_unparse (f2)));
297 llsuppresshint (char c, flagcode f)
299 if (context_getFlag (FLG_HINTS))
301 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
303 cstring desc = flagcodeHint (f);
304 context_setNeednl ();
305 s_lastfileloclen = 8;
307 if (flagcode_isNamePrefixFlag (f))
312 if (cstring_isDefined (desc))
314 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
315 flagcode_unparse (f)));
319 llgenhint (message ("(Use %h%s to inhibit warning)", c,
320 flagcode_unparse (f)));
327 llnosuppresshint (flagcode f)
329 if (context_getFlag (FLG_FORCEHINTS))
331 cstring desc = flagcodeHint (f);
332 context_setNeednl ();
333 s_lastfileloclen = 8;
335 if (cstring_isDefined (desc))
337 printError (g_warningstream, message (" %s", desc));
342 /*@constant int MAXSEARCH; @*/
343 # define MAXSEARCH 20
345 /*@constant int MINLINE; @*/
348 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
353 ** Divides a string into lines of up to maxline characters.
355 ** Initial string: *sp
357 ** Output split: *sp / *tp
362 mstring_split (/*@returned@*/ char **sp,
363 /*@out@*/ nd_charp *tp,
364 int maxline, /*@in@*/ int *indentchars)
373 DPRINTF (("Split: %s / %d", *sp, maxline));
375 if (maxline < MINLINELEN)
377 maxline = MINLINELEN;
380 if (*indentchars > 0)
382 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
389 ** if there is a newline in first maxline characters, split there
390 ** if line len is <= maxline, return no split
391 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
392 ** split there unless the ' ' is followed by a '}', then
394 ** of the ';' is inside quotation marks
395 ** if there is a space or tab in last maxsearch characters, split there
396 ** else, split at maxline
398 ** special code: slash [1-9] after a newline means indent the rest <n> chars
402 nl = strchr (s, '\n');
404 if ((nl != NULL) && ((nl - s) < maxline))
411 llassertprotect (*tp == NULL || (*tp > osp));
415 if (*t >= '\1' && *t <= '\7')
417 *indentchars += (int) (*t - '\1') + 1;
424 else if (size_toInt (strlen (s)) < maxline)
426 llassertprotect (*tp == NULL);
433 char *lcolon, *lsemi, *lcomma;
442 lcolon = strrchr (s, ':');
443 lsemi = strrchr (s, ';');
444 lcomma = strrchr (s, ',');
448 splitat = maxcp (lcolon, lsemi);
450 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
451 && *(splitat) != '\0'
452 && *(splitat + 1) == ' '
453 && (*(splitat + 2) != '}'
454 && *(splitat + 2) != ','
455 && (*(splitat + 2) != '\0')))
457 *(splitat + 1) = '\0';
460 llassertprotect (*tp == NULL || (*tp > osp));
464 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
468 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
469 && *(splitat) != '\0'
470 && *(splitat + 1) == ' '
471 && (*(splitat + 2) != '}'
472 && (*(splitat + 2) != '\0')))
474 *(splitat + 1) = '\0';
477 llassertprotect (*tp == NULL || (*tp > osp));
483 ** Search for any breaking point (at least 4 letters past s)
486 while (*t != ' ' && *t != '\t' && i < MAXSEARCH && t > (s + 4))
492 if (*t != ' ' && *t != '\t')
494 llassertprotect (maxline > 0);
495 t = mstring_copy (s + maxline);
496 *(s + maxline) = '\0';
501 llassertprotect (*tp == NULL || (*tp > osp));
505 mstring_markFree (t);
507 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
516 if (*t == '\0') return;
519 ** returns unqualified as only
524 llassert (*sp != *tp);
533 void limitmessage (/*@only@*/ cstring s, fileloc loc)
535 if (s_mcount > context_getLimit () + 1)
541 cstring flstring = fileloc_unparse (loc);
543 s_lastfileloclen = cstring_length (flstring);
544 cstring_free (saveOneMessage);
545 saveOneMessage = message ("%q: %q", flstring, s);
549 static int parseerrorcount = 0;
551 void cleanupMessages ()
555 if (context_unlimitedMessages ())
561 int unprinted = s_mcount - context_getLimit ();
565 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
568 printError (g_warningstream, saveOneMessage);
570 saveOneMessage = cstring_undefined;
574 if (cstring_isDefined (saveOneMessage))
576 /* cstring_free (saveOneMessage); */
577 saveOneMessage = cstring_undefined;
580 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
581 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
582 s_mcount - context_getLimit ());
591 llgenmsg (/*@only@*/ cstring s, fileloc fl)
593 cstring flstring = fileloc_unparse (fl);
594 s_lastfileloclen = cstring_length (flstring);
597 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
602 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
604 cstring flstring = fileloc_unparse (fl);
605 int indentspaces = context_getLocIndentSpaces ();
608 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s),
615 llgenindentmsgnoloc (/*@only@*/ cstring s)
618 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
623 llgentypeerroraux (char *srcFile, int srcLine,
624 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
625 /*@only@*/ cstring s, fileloc fl)
627 cstring hint = cstring_undefined;
628 flagcode code = ocode;
629 flagcode hcode = INVALID_FLAG;
633 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
634 flagcode_unparse (ocode),
635 exprNode_unparse (e1), exprNode_unparse (e2),
636 ctype_unparse (t1), ctype_unparse (t2)));
638 DPRINTF (("Bool: %s / %s",
639 bool_unparse (ctype_isBool (t1)),
640 bool_unparse (ctype_isBool (t2))));
643 ** Set the flag using the underlying types that didn't match.
646 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
647 ut1 = ctype_baseArrayPtr (ut1);
648 ut2 = ctype_baseArrayPtr (ut2);
651 if (ctype_isRealNumAbstract (ut1) && exprNode_isNumLiteral (e2))
653 hcode = FLG_NUMABSTRACTLIT;
655 else if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
656 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
658 hcode = FLG_FLOATDOUBLE;
660 else if ((exprNode_isCharLiteral (e1) && ctype_isInt (ut2))
661 || (exprNode_isCharLiteral (e2) && ctype_isInt (ut1)))
663 hcode = FLG_CHARINTLITERAL;
665 else if ((exprNode_isNumLiteral (e1) && ctype_isReal (ut2))
666 || (exprNode_isNumLiteral (e2) && ctype_isReal (ut1)))
668 hcode = FLG_NUMLITERAL;
670 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
671 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
672 /* evs 2000-07-24: was ctype_isDirectBool */
676 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
677 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
681 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
682 || (ctype_isChar (ut1) && ctype_isChar (ut2))
683 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
685 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
687 if (ctype_isArbitraryIntegral (ctype_realType (ut1))
688 && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
690 hcode = FLG_MATCHANYINTEGRAL;
692 else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
693 && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
695 hcode = FLG_MATCHANYINTEGRAL;
698 /*drl 4-270-2003 even if ignoresigns is set there may be another
699 problem that is causing splint to complain about a type error.
700 Don't tell the user that they can add +ignoresigns if it's
703 DPRINTF(("TEST INGORESIGNS"));
704 if (context_getFlag(FLG_IGNORESIGNS) )
706 DPRINTF(("INGORESIGNS SET"));
707 hcode = FLG_IGNOREQUALS;
712 DPRINTF(("INGORESIGNS NOT SET"));
713 hcode = FLG_IGNORESIGNS;
719 hcode = FLG_IGNOREQUALS;
722 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
724 DPRINTF (("HERE: %s", ctype_unparse (ctype_realType (ut2))));
726 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
728 hcode = FLG_MATCHANYINTEGRAL;
730 else if (ctype_equal (ut2, ctype_ulint))
732 hcode = FLG_LONGUNSIGNEDINTEGRAL;
734 else if (ctype_equal (ut2, ctype_lint))
736 hcode = FLG_LONGINTEGRAL;
738 else if (ctype_isInt (ut2))
740 hcode = FLG_MATCHANYINTEGRAL;
747 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
749 ctype tr = ctype_realType (ut1);
751 if (ctype_isArbitraryIntegral (tr))
753 hcode = FLG_MATCHANYINTEGRAL;
755 else if (ctype_match (ut1, ctype_ulint))
757 if (ctype_isUnsignedIntegral (tr))
759 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
761 else if (ctype_isSignedIntegral (tr))
767 hcode = FLG_LONGUNSIGNEDINTEGRAL;
770 else if (ctype_match (ut1, ctype_lint))
772 if (ctype_isSignedIntegral (tr))
774 hcode = FLG_LONGSIGNEDINTEGRAL;
776 else if (ctype_isSignedIntegral (tr))
782 hcode = FLG_LONGINTEGRAL;
785 else if (ctype_isInt (ut1))
787 hcode = FLG_MATCHANYINTEGRAL;
799 if (hcode == INVALID_FLAG)
801 DPRINTF (("[%s] %s - %s / %s",
803 bool_unparse (ctype_isEnum (ut1)),
804 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
805 bool_unparse (ctype_isInt (ut2))));
807 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
809 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
810 ctype ct = uentry_getType (ue1);
812 if (ctype_match (ct, ut2))
815 hint = message ("Underlying types match, but %s is an "
816 "abstract type that is not accessible here.",
820 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
822 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
823 ctype ct = uentry_getType (ue);
825 if (ctype_match (ct, ut1))
827 if (ctype_isNumAbstract (ut2))
829 if (exprNode_isNumLiteral (e1))
831 code = FLG_NUMABSTRACTLIT;
832 hint = message ("Underlying types match, but %s is a "
833 "numabstract type that is not accessible here. "
834 "(Use +numabstractlit to allow numeric literals "
835 "to be used as numabstract type values.)",
840 code = FLG_NUMABSTRACT;
841 hint = message ("Underlying types match, but %s is a "
842 "numabstract type that is not accessible here.",
849 hint = message ("Underlying types match, but %s is an "
850 "abstract type that is not accessible here.",
857 ; /* Not an abstract mismatch. */
861 if (hcode == INVALID_FLAG)
863 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
864 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
868 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
869 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
873 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
874 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
876 hcode = FLG_CHARUNSIGNEDCHAR;
878 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
880 hcode = FLG_RELAXTYPES;
881 DPRINTF (("Setting relax types!"));
885 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
886 ctype_unparse (ut2)));
891 if (cstring_isDefined (hint))
893 if (!context_suppressFlagMsg (ocode, fl))
895 return xllgenhinterror (srcFile, srcLine, code, s, hint, fl);
906 if (hcode != INVALID_FLAG && hcode != ocode)
911 if (llgenerroraux (ocode, srcFile, srcLine, s,
912 flagcodeHint (code), fl, TRUE, FALSE))
916 if (context_flagOn (code, fl))
918 /* The flag is alreay set, something buggy in the flag code */
919 llcontbug (message ("No hint available, flag %s is already set.",
920 flagcode_unparse (code)));
929 llsuppresshint ('-', code);
932 flagcode_recordError (code);
941 xllgentypeerror (char *srcFile, int srcLine,
942 ctype t1, exprNode e1, ctype t2, exprNode e2,
943 /*@only@*/ cstring s, fileloc fl)
945 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
949 xllgenformattypeerror (char *srcFile, int srcLine,
950 ctype t1, exprNode e1, ctype t2, exprNode e2,
951 /*@only@*/ cstring s, fileloc fl)
953 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
956 && ctype_isNumAbstract (t2))
958 if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT, fl))
960 return llgentypeerroraux (srcFile, srcLine, FLG_NUMABSTRACTPRINT, t1, e1, t2, e2, s, fl);
969 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
980 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
982 if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
984 llnosuppresshint (o);
985 flagcode_recordError (o);
991 flagcode_recordSuppressed (o);
997 xllgenhinterror (char *srcFile, int srcLine,
998 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
1001 if (!context_suppressFlagMsg (o, fl))
1003 if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
1005 flagcode_recordError (o);
1007 if (context_getFlag (FLG_HINTS))
1013 cstring_free (hint);
1020 cstring_free (hint);
1024 cstring_free (hint);
1028 flagcode_recordSuppressed (o);
1033 llrealerror (flagcode code, char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
1035 return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
1039 llgenerroraux (flagcode code,
1040 char *srcFile, int srcLine,
1041 /*@only@*/ cstring s,
1043 fileloc fl, bool iserror, bool indent)
1045 if (context_inSuppressZone (fl))
1051 if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1059 xllforceerror (char *srcFile, int srcLine,
1060 flagcode code, /*@only@*/ cstring s, fileloc fl)
1062 flagcode_recordError (code);
1064 if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1072 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1075 if (g_csvstream != NULL) {
1076 /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1077 fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1078 context_numErrors (),
1079 (int) code, /* flag code */
1080 cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1081 flagcode_priority (code), /* priority */
1082 cstring_toCharsSafe (fileloc_outputFilename (fl)),
1083 fileloc_lineno (fl),
1084 fileloc_column (fl),
1085 cstring_toCharsSafe (s));
1087 if (cstring_isDefined (addtext)) {
1088 fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1090 fprintf (g_csvstream, "\n");
1096 llgenerrorreal (flagcode code, char *srcFile, int srcLine,
1097 /*@only@*/ cstring s,
1099 fileloc fl, bool iserror, bool indent)
1103 /* duplicate message (rescanning a header file */
1105 if (!messageLog_add (context_messageLog (), fl, s))
1107 DPRINTF (("Duplicate message suppressed! %s / %s",
1108 fileloc_unparse (fl), s));
1114 ** If herald has not been displayed, display it before the first message.
1119 if (iserror) context_hasError ();
1121 if (context_unlimitedMessages ())
1128 ** suppress excessive messages:
1133 char *sc = cstring_toCharsSafe (s);
1134 char *tmpmsg = strchr (sc, ':');
1142 char *savechar = tmpmsg;
1148 if (cstring_equal (s_lastmsg, cstring_fromChars (tmpmsg)))
1151 if (s_mcount == (context_getLimit () + 1))
1153 limitmessage (s, fl);
1157 if (s_mcount > (context_getLimit ()))
1167 cstring_free (s_lastmsg);
1168 s_lastmsg = cstring_fromCharsNew (tmpmsg);
1172 DPRINTF (("Here..."));
1174 if (context_hasAliasAnnote ())
1176 char *sc = cstring_toCharsSafe (s);
1177 char *fcolon = strchr (sc, ':');
1178 cstring a = context_getAliasAnnote ();
1183 s = message ("%q (%q)", s, a);
1190 afterColon = cstring_fromCharsNew (fcolon + 1);
1192 s = message ("%q (%q):%q", s, a, afterColon);
1196 if (context_hasMessageAnnote ())
1198 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1203 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1204 s = message ("%q (%q)", s, context_getMessageAnnote ());
1205 /*@=dependenttrans@*/
1212 afterColon = cstring_fromCharsNew (fcolon + 1);
1214 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1215 s = message ("%q (%q):%q", s,
1216 context_getMessageAnnote (), afterColon);
1217 /*@=dependenttrans@*/
1221 context_setNeednl ();
1224 if (context_showFunction ())
1226 cstring fname = fileloc_unparseFilename (g_currentloc);
1228 if (context_inIterDef ())
1230 fprintf (g_warningstream, "%s: (in iter %s)\n",
1231 cstring_toCharsSafe (fname),
1232 cstring_toCharsSafe (context_inFunctionName ()));
1234 else if (context_inIterEnd ())
1236 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1237 cstring_toCharsSafe (fname),
1238 cstring_toCharsSafe (context_inFunctionName ()));
1240 else if (context_inMacro ())
1242 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1243 cstring_toCharsSafe (context_inFunctionName ()));
1247 fprintf (g_warningstream, "%s: (in function %s)\n",
1248 cstring_toCharsSafe (fname),
1249 cstring_toCharsSafe (context_inFunctionName ()));
1252 cstring_free (fname);
1253 context_setShownFunction ();
1256 flstring = fileloc_unparse (fl);
1257 s_lastfileloclen = cstring_length (flstring);
1259 generateCSV (code, s, addtext, fl);
1263 printError (g_warningstream, message (" %q: %q", flstring, s));
1267 printError (g_warningstream, message ("%q: %q", flstring, s));
1270 showSourceLoc (srcFile, srcLine);
1278 ** message contains no '\n'
1279 ** message fits in one line: print it
1280 ** message fits in two lines with 3-space indent after fileloc: print it
1281 ** split line with 5-space indent from left margin: print it
1286 void printMessage (FILE *stream, /*@only@*/ cstring s)
1288 printIndentMessage (stream, s, 0);
1292 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1294 static bool inbody = FALSE;
1295 int maxlen = context_getLineLen ();
1296 char *s = cstring_toCharsSafe (sc);
1299 llassertprotect (!inbody);
1307 llassertprotect (st != olds);
1309 mstring_split (&st, &t, maxlen, &indent);
1310 fprintf (stream, "%s\n", st);
1311 llassertprotect (t != s);
1313 } while (s != NULL) ;
1320 void printError (FILE *stream, /*@only@*/ cstring sc)
1322 int maxlen = context_getLineLen ();
1323 size_t nspaces = s_lastfileloclen + 5;
1324 int nextlen = maxlen - size_toInt (nspaces);
1325 size_t len = cstring_length (sc);
1327 char *s = cstring_toCharsSafe (sc);
1331 DPRINTF (("Print error: [%s]", sc));
1333 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1335 mstring_split (&s, &t, maxlen, &indent);
1337 fprintf (stream, "%s\n", s);
1341 len = mstring_length (t);
1343 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1344 && size_toInt (len) > (nextlen - 1))
1346 fprintf (stream, " %s\n", t);
1350 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1353 for (i = 0; i < size_toInt (nspaces); i++)
1358 spaces[nspaces] = '\0';
1363 mstring_split (&st, &t, nextlen, &indent);
1364 fprintf (stream, "%s%s\n", spaces, st);
1373 DPRINTF (("Here 1: [%s]", sc));
1375 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1377 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1379 if (nspaces < 1) nspaces = 1;
1381 nextlen = size_toInt (maxlen - nspaces);
1383 mstring_split (&s, &t, maxlen, &indent);
1385 fprintf (stream, "%s\n", s);
1389 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1392 for (i = 0; i < size_toInt (nspaces); i++)
1397 spaces[nspaces] = '\0';
1403 mstring_split (&st, &t, nextlen, &indent);
1404 fprintf (stream, "%s%s\n", spaces, st);
1413 nextlen = size_toInt (maxlen - nspaces);
1415 DPRINTF (("Here 2: [%s]", s));
1416 mstring_split (&s, &t, maxlen, &indent);
1417 DPRINTF (("Here 3: [%s] [%s]", s, t));
1419 fprintf (stream, "%s\n", s);
1423 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1426 for (i = 0; i < nspaces; i++)
1431 spaces[nspaces] = '\0';
1436 DPRINTF (("Loop: [%s]", t));
1437 mstring_split (&st, &t, nextlen, &indent);
1438 DPRINTF (("Split: [%s] [%s]", st, t));
1439 fprintf (stream, "%s%s\n", spaces, st);
1440 DPRINTF (("Next..."));
1453 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1456 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1457 fileloc_unparse (g_currentloc), s));
1458 showSourceLoc (srcFile, srcLine);
1465 lclfatalbug (char *msg)
1468 printError (g_errorstream,
1469 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1476 checkParseError (void)
1478 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1480 llfatalerror (message ("%q: Cannot recover from parse error.",
1481 fileloc_unparse (g_currentloc)));
1485 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1488 static int numbugs = 0;
1489 static bool inbug = FALSE;
1491 context_recordBug ();
1495 cstring temps = fileloc_unparseRaw (file, line);
1497 fprintf (g_errorstream,
1498 "%s: Recursive bug detected: %s\n",
1499 cstring_toCharsSafe (temps),
1500 cstring_toCharsSafe (s));
1501 cstring_free (temps);
1510 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1512 llfatalerror (message ("%q: Cannot recover from parse error.",
1513 fileloc_unparse (g_currentloc)));
1516 (void) fflush (g_warningstream);
1518 printError (g_errorstream,
1519 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1520 fileloc_unparse (g_currentloc),
1521 fileloc_unparseRaw (file, line),
1524 /* printCodePoint (); no longer useful */
1529 ** This is confusing, and hardly ever useful.
1533 perror ("Possible system error diagnostic: ");
1544 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1547 (message ("%q: Cannot recover from last bug. "
1548 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1549 fileloc_unparse (g_currentloc)));
1552 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1553 fileloc_free (lastbug);
1554 lastbug = fileloc_copy (g_currentloc);
1560 lclbug (/*@only@*/ cstring s)
1563 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1566 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1571 xllfatalerror (char *srcFile, int srcLine, cstring s)
1574 printError (g_errorstream, s);
1575 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1576 showSourceLoc (srcFile, srcLine);
1581 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1584 (void) fflush (g_warningstream);
1585 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1586 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1587 showSourceLoc (srcFile, srcLine);
1588 (void) fflush (g_warningstream);
1595 return (s_lclerrors > 0);
1599 lclHadNewError (void)
1601 static int lastcall = 0;
1603 if (s_lclerrors > lastcall)
1605 lastcall = s_lclerrors;
1615 lclNumberErrors (void)
1617 return (s_lclerrors);
1621 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1625 if (ltoken_getCode (t) != NOTTOKEN)
1627 cstring loc = ltoken_unparseLoc (t);
1628 s_lastfileloclen = cstring_length (loc);
1630 printError (g_warningstream, message ("%q: %q", loc, msg));
1631 showSourceLoc (srcFile, srcLine);
1635 printError (g_warningstream, msg);
1636 showSourceLoc (srcFile, srcLine);
1641 lclplainerror (/*@only@*/ cstring msg)
1644 printError (g_warningstream, msg);
1648 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1650 if (ltoken_getCode (t) != NOTTOKEN)
1652 cstring loc = ltoken_unparseLoc (t);
1653 s_lastfileloclen = cstring_length (loc);
1654 printError (g_errorstream, message ("%q: %q", loc, msg));
1658 printError (g_errorstream, msg);
1661 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1666 lclplainfatalerror (/*@only@*/ cstring msg)
1668 (void) fflush (g_warningstream);
1669 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1674 lclRedeclarationError (ltoken id)
1676 cstring s = ltoken_getRawString (id);
1679 if (usymtab_existsEither (s))
1681 uentry le = usymtab_lookupEither (s);
1683 lclerror (id, message ("Respecification of %s", s));
1684 llgenindentmsg (message ("Previous specification of %q",
1685 uentry_getName (le)),
1686 uentry_whereSpecified (le));
1690 lclerror (id, message ("Identifier redeclared: %s", s));
1694 void genppllerror (flagcode code, /*@only@*/ cstring s)
1696 if (context_inSuppressZone (g_currentloc))
1702 if (context_getFlag (code))
1706 displayScanClose ();
1711 if (code != FLG_PREPROC)
1713 llsuppresshint ('-', code);
1716 if (!context_isInCommandLine ())
1718 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1728 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1729 /*@only@*/ cstring hint)
1731 if (context_inSuppressZone (g_currentloc))
1734 cstring_free (hint);
1738 if (context_getFlag (code))
1740 generateCSV (code, s, hint, g_currentloc);
1742 context_clearPreprocessing ();
1745 context_setPreprocessing ();
1751 cstring_free (hint);
1756 void ppllerror (/*@only@*/ cstring s)
1758 genppllerror (FLG_PREPROC, s);
1761 void pplldiagmsg (cstring s)
1763 if (!context_isInCommandLine ())
1767 displayScanClose ();
1771 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1779 void loadllmsg (cstring s)
1781 displayScanClose ();
1783 displayScanOpen (cstring_makeLiteral ("< ."));
1786 static void llreportparseerror (/*@only@*/ cstring s)
1788 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1794 llerror (FLG_SYNTAX, s);
1796 fileloc_free (lastparseerror);
1797 lastparseerror = fileloc_copy (g_currentloc);
1801 bool xcppoptgenerror (char *srcFile, int srcLine,
1803 /*@only@*/ cstring s,
1807 fileloc loc = cppReader_getLoc (pfile);
1809 if (context_flagOn (o, loc))
1811 if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1813 cppReader_printContainingFiles (pfile);
1827 bool xlloptgenerror (char *srcFile, int srcLine,
1828 flagcode o, /*@only@*/ cstring s, fileloc loc)
1830 DPRINTF (("xllopt: %s", s));
1832 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1834 DPRINTF (("Here we are!"));
1835 llsuppresshint ('-', o);
1837 flagcode_recordError (o);
1842 DPRINTF (("Suppressed!"));
1843 flagcode_recordSuppressed (o);
1848 bool xoptgenerror2 (char *srcFile, int srcLine,
1849 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1851 if (context_suppressFlagMsg (f1, loc))
1853 flagcode_recordSuppressed (f1);
1858 if (context_suppressFlagMsg (f2, loc))
1860 flagcode_recordSuppressed (f2);
1865 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1867 llsuppresshint2 ('-', f1, f2);
1868 flagcode_recordError (f2);
1874 flagcode_recordSuppressed (f2);
1882 bool xoptgenerror2n (char *srcFile, int srcLine,
1883 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1886 if (context_suppressFlagMsg (f1, loc))
1888 flagcode_recordSuppressed (f1);
1893 if (context_suppressNotFlagMsg (f2, loc))
1895 flagcode_recordSuppressed (f2);
1900 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1902 llsuppresshint ('+', f2);
1903 flagcode_recordError (f2);
1908 flagcode_recordSuppressed (f2);
1914 bool xllnoptgenerror (char *srcFile, int srcLine,
1915 flagcode o, /*@only@*/ cstring s, fileloc loc)
1917 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1919 llsuppresshint ('+', o);
1920 flagcode_recordError (o);
1925 flagcode_recordSuppressed (o);
1929 void xllparseerror (char *srcFile, int srcLine, cstring s)
1931 if (context_getFlag (FLG_TRYTORECOVER))
1935 if (parseerrorcount > GIVEUPPARSE)
1937 if (cstring_isDefined (s))
1939 xllfatalerror (srcFile, srcLine,
1940 message ("%q: Parse Error: %q. "
1941 "Too many errors, giving up.",
1942 fileloc_unparse (g_currentloc), s));
1946 xllfatalerror (srcFile, srcLine,
1947 message ("%q: Parse Error. Too many errors, giving up.",
1948 fileloc_unparse (g_currentloc)));
1953 if (cstring_isDefined (s))
1955 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1957 showSourceLoc (srcFile, srcLine);
1961 llreportparseerror (message ("Parse Error. Attempting to continue."));
1962 showSourceLoc (srcFile, srcLine);
1970 if (cstring_isDefined (s))
1972 msg = message ("Parse Error: %q.", s);
1976 msg = message ("Parse Error.");
1981 message ("%q: %s (For help on parse errors, "
1982 "see splint -help parseerrors.)",
1983 fileloc_unparse (g_currentloc), msg));
1987 bool xfsgenerror (char *srcFile, int srcLine,
1988 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1990 if (flagSpec_isOn (fs, fl))
1992 flagcode firston = flagSpec_getFirstOn (fs, fl);
1994 if (llgenerroraux (firston, srcFile, srcLine, s,
1995 flagcodeHint (firston),
1998 llsuppresshint ('-', firston);
1999 flagcode_recordError (firston);
2004 flagcode_recordSuppressed (firston);
2010 flagcode_recordSuppressed (flagSpec_getDominant (fs));
2016 bool doCheck (bool x, cstring pred, cstring file, int line)
2019 llbug (message ("%q: Check Failed: %s",
2020 fileloc_unparseRaw (file, line),
2027 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
2032 #ifndef HAVE_STRERROR
2035 result = strerror (errnum);
2038 /* VAXCRTL's strerror() takes an optional second argument, which only
2039 matters when the first argument is EVMSERR. However, it's simplest
2040 just to pass it unconditionally. `vaxc$errno' is declared in
2041 <errno.h>, and maintained by the library in parallel with `errno'.
2042 We assume that caller's `errnum' either matches the last setting of
2043 `errno' by the library or else does not have the value `EVMSERR'. */
2045 result = strerror (errnum, vaxc$errno);
2050 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2053 return cstring_fromChars (result);
2056 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2061 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2062 fileloc_unparse (g_currentloc),
2063 fileloc_unparseRaw (file, line),
2075 (void) fflush (g_warningstream);
2076 (void) fflush (g_messagestream);
2079 void displayScan (cstring msg)
2083 displayScanClose ();
2086 llassert (!s_scanOpen);
2088 if (context_getFlag (FLG_SHOWSCAN))
2091 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2092 (void) fflush (g_messagestream);
2098 void displayScanOpen (cstring msg)
2102 displayScanClose ();
2105 llassert (!s_scanOpen);
2108 if (context_getFlag (FLG_SHOWSCAN))
2110 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2111 (void) fflush (g_messagestream);
2117 void displayScanContinue (/*@temp@*/ cstring msg)
2119 if (context_getFlag (FLG_SHOWSCAN))
2123 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2124 (void) fflush (g_messagestream);
2129 ** Don't call bug recursively
2132 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2137 void displayScanClose (void)
2141 if (context_getFlag (FLG_SHOWSCAN))
2143 fprintf (g_messagestream, " >\n");
2144 (void) fflush (g_messagestream);
2150 ** Don't call bug recursively
2153 fprintf (stderr, "*** Bug: scan close scan not open\n");