Handle possible null character inside string literal
[splint-patched.git] / src / llerror.c
blob388e141afd21d5aa7dc496d6ba9064ae03c9258b
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
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
25 ** llerror.c
27 ** error reporting procedures
30 # include <errno.h>
32 # include "splintMacros.nf"
33 # include "basic.h"
36 ** Use this for assertions in error-generation code (that
37 ** might lead to infinite loops of failed assertions if
38 ** the normal error generation routines are used).
41 /*@function static noreturnwhenfalse void llassertprotect (sef bool p_test); @*/
42 # define llassertprotect(tst) \
43 do { if (!(tst)) { \
44 fprintf (stderr, "%s:%d: at source point: ", __FILE__, __LINE__); \
45 fprintf (stderr, "protected fatal llassert failed: " #tst "\n"); \
46 failexit (); \
47 }} while (FALSE)
49 /* Don't allow possibly-recursive assertion failures. */
50 # undef llassert
51 # define llassert llassertprotect
53 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
54 /*@modifies *p_stream@*/ ;
56 static bool s_scanOpen = FALSE;
57 static int s_lclerrors = 0;
58 static size_t s_lastfileloclen = 10;
59 static /*@only@*/ cstring s_lastmsg = cstring_undefined;
60 static int s_mcount = 0;
61 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
62 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
63 static /*@only@*/ fileloc lastbug = fileloc_undefined;
64 static bool llgenerrorreal (flagcode p_code,
65 const char *p_srcFile, int p_srcLine,
66 /*@only@*/ cstring p_s,
67 /*@temp@*/ cstring p_addtext,
68 fileloc p_fl, bool p_iserror, bool p_indent)
69 /*@modifies g_warningstream@*/ ;
70 static bool llgenerroraux (flagcode p_code, const char *p_srcFile, int p_srcLine,
71 /*@only@*/ cstring p_s,
72 /*@temp@*/ cstring p_addtext,
73 fileloc p_fl, bool p_iserror, bool p_indent)
74 /*@modifies g_warningstream@*/ ;
76 static void generateCSV (flagcode p_code, cstring p_s, cstring p_addtext, fileloc p_fl)
77 /*@modifies g_csvstream@*/ ;
79 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
80 /*@globals s_lastfileloclen @*/
81 /*@modifies *p_stream@*/ ;
82 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
83 /*@modifies *p_stream@*/ ;
85 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
87 static void showSourceLoc (const char *srcFile, int srcLine)
88 /*@modifies g_warningstream@*/
90 if (context_getFlag (FLG_SHOWSOURCELOC)) {
91 llgenhint (message ("%s:%d: Source code error generation point.",
92 cstring_fromChars (srcFile), srcLine));
97 static /*@null@*/ char *
98 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
100 if (a > b) return a;
101 else return b;
104 static void
105 printBugReport (void)
107 fprintf (g_errorstream, " *** Please report bug to %s ***\n",
108 PACKAGE_BUGREPORT);
109 llflush ();
110 /* don't exit (EXIT_FAILURE); */
113 static bool s_needsPrepare = TRUE;
115 static void prepareMessage (void)
116 /*@modifies internalState, g_messagestream@*/
118 DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
119 showHerald ();
121 if ((context_isPreprocessing () || context_loadingLibrary ())
122 && s_needsPrepare
123 && context_getFlag (FLG_SHOWSCAN))
125 llflush ();
126 displayScanClose ();
127 s_needsPrepare = FALSE;
130 llflush ();
133 static void closeMessage (void)
134 /*@modifies internalState, g_messagestream@*/
136 if (context_isPreprocessing ()
137 && context_getFlag (FLG_SHOWSCAN))
139 llflush ();
140 displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
141 llassertprotect (!s_needsPrepare);
142 s_needsPrepare = TRUE;
144 else
146 llflush ();
150 void
151 llmsg (/*@only@*/ cstring s)
153 context_setNeednl ();
154 prepareMessage ();
155 printMessage (g_messagestream, s);
156 closeMessage ();
159 void
160 lldiagmsg (/*@only@*/ cstring s)
162 static bool inmsg = FALSE;
164 if (inmsg)
166 fprintf (g_errorstream,
167 "Recursive message call detected: %s\n",
168 cstring_toCharsSafe (s));
169 failexit ();
172 inmsg = TRUE;
174 context_setNeednl ();
175 prepareMessage ();
176 printMessage (g_messagestream, s);
177 closeMessage ();
179 inmsg = FALSE;
182 void
183 llmsgplain (/*@only@*/ cstring s)
185 context_setNeednl ();
186 prepareMessage ();
187 printMessage (g_messagestream, s);
188 closeMessage ();
191 void llerror_flagWarning (cstring s)
193 if (context_getFlag (FLG_WARNFLAGS))
195 llgenmsg (s, g_currentloc);
197 else
199 cstring_free (s);
203 static void
204 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
206 int indent = context_getIndentSpaces () - 1;
208 if (indent < 0) indent = 0;
210 context_setNeednl ();
211 printIndentMessage (g_warningstream, s, indent);
214 void
215 llhint (cstring s)
217 if (context_getFlag (FLG_HINTS) &&
218 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
220 llgenhint (s);
222 else
224 cstring_free (s);
228 static void
229 llshowhint (flagcode f)
231 if (context_getFlag (FLG_HINTS))
233 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
235 cstring desc = flagcodeHint (f);
237 if (cstring_isDefined (desc))
239 llgenhint (cstring_copy (desc));
245 static void
246 llsuppresshint2 (char c, flagcode f1, flagcode f2)
249 if (context_getFlag (FLG_HINTS))
251 if ((flagcode_numReported (f1) == 0
252 || flagcode_numReported (f2) == 0)
253 || context_getFlag (FLG_FORCEHINTS))
255 cstring desc = flagcodeHint (f1);
256 context_setNeednl ();
257 s_lastfileloclen = 8;
259 if (cstring_isUndefined (desc))
261 desc = flagcodeHint (f2);
264 if (flagcode_isNamePrefixFlag (f1))
266 f1 = FLG_NAMECHECKS;
269 if (flagcode_isNamePrefixFlag (f2))
271 f2 = FLG_NAMECHECKS;
274 if (f1 == f2)
276 if (cstring_isDefined (desc))
278 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
280 flagcode_unparse (f1)));
282 else
284 llgenhint (message ("(Use %h%s to inhibit warning)",
285 c, flagcode_unparse (f1)));
288 else
290 if (cstring_isDefined (desc))
292 llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc,
294 flagcode_unparse (f1),
296 flagcode_unparse (f2)));
298 else
300 llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
301 flagcode_unparse (f1),
302 c, flagcode_unparse (f2)));
309 static void
310 llsuppresshint (char c, flagcode f)
312 if (context_getFlag (FLG_HINTS))
314 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
316 cstring desc = flagcodeHint (f);
317 context_setNeednl ();
318 s_lastfileloclen = 8;
320 if (flagcode_isNamePrefixFlag (f))
322 f = FLG_NAMECHECKS;
325 if (cstring_isDefined (desc))
327 llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
328 flagcode_unparse (f)));
330 else
332 llgenhint (message ("(Use %h%s to inhibit warning)", c,
333 flagcode_unparse (f)));
339 static void
340 llnosuppresshint (flagcode f)
342 if (context_getFlag (FLG_FORCEHINTS))
344 cstring desc = flagcodeHint (f);
345 context_setNeednl ();
346 s_lastfileloclen = 8;
348 if (cstring_isDefined (desc))
350 printError (g_warningstream, message (" %s", desc));
355 /*@constant int MAXSEARCH; @*/
356 # define MAXSEARCH 20
358 /*@constant int MINLINE; @*/
359 # define MINLINE 35
361 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
363 static char *
364 mstring_spaces (int n)
366 int i;
367 char *ret;
368 char *ptr;
370 llassert (n >= 0);
372 ret = (char *) dmalloc (size_fromInt (n + 1));
373 ptr = ret;
375 for (i = 0; i < n; i++)
377 *ptr++ = ' ';
380 *ptr = '\0';
382 return ret;
386 ** mstring_split
388 ** Divides a string into lines of up to maxline characters.
390 ** Initial string: *sp
392 ** Output split: *sp / *tp
393 ** possibly null
396 static void
397 mstring_split (/*@returned@*/ char **sp,
398 /*@out@*/ nd_charp *tp,
399 int maxline, /*@in@*/ int *indentchars)
401 char *nl;
402 char *t;
403 char *s = *sp;
404 char *osp = *sp;
406 *tp = NULL;
408 DPRINTF (("Split: %s / %d", *sp, maxline));
410 if (maxline < MINLINELEN)
412 maxline = MINLINELEN;
415 if (*indentchars > 0)
417 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
418 osp = s;
422 ** splitting:
424 ** if there is a newline in first maxline characters, split there
425 ** if line len is <= maxline, return no split
426 ** if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
427 ** split there unless the ' ' is followed by a '}', then
428 ** split after '}'
429 ** of the ';' is inside quotation marks
430 ** if there is a space or tab in last maxsearch characters, split there
431 ** else, split at maxline
433 ** special code: slash [1-9] after a newline means indent the rest <n> chars
437 nl = strchr (s, '\n');
439 if ((nl != NULL) && ((nl - s) < maxline))
441 *nl = '\0';
442 t = nl + 1;
444 if (*t == '\0')
446 llassertprotect (*tp == NULL || (*tp > osp));
447 return;
450 if (*t >= '\1' && *t <= '\7')
452 *indentchars += (int) (*t - '\1') + 1;
453 t++;
456 *tp = t;
457 return;
459 else if (size_toInt (strlen (s)) < maxline)
461 llassertprotect (*tp == NULL);
462 return;
464 else
466 int i = 0;
467 char savechar;
468 char *lcolon, *lsemi, *lcomma;
469 char *splitat;
471 t = s + maxline - 1;
472 savechar = *t;
474 *t = '\0';
475 lcolon = strrchr (s, ':');
476 lsemi = strrchr (s, ';');
477 lcomma = strrchr (s, ',');
479 *t = savechar;
481 splitat = maxcp (lcolon, lsemi);
483 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
484 && *(splitat) != '\0'
485 && *(splitat + 1) == ' '
486 && (*(splitat + 2) != '}'
487 && *(splitat + 2) != ','
488 && (*(splitat + 2) != '\0')))
490 *(splitat + 1) = '\0';
491 t = splitat + 2;
492 *tp = t;
493 llassertprotect (*tp == NULL || (*tp > osp));
494 return;
497 if (lcomma != NULL && ((lcomma - s) > maxline - 5))
499 splitat = lcomma;
501 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
502 && *(splitat) != '\0'
503 && *(splitat + 1) == ' '
504 && (*(splitat + 2) != '}'
505 && (*(splitat + 2) != '\0')))
507 *(splitat + 1) = '\0';
508 t = splitat + 2;
509 *tp = t;
510 llassertprotect (*tp == NULL || (*tp > osp));
511 return;
516 ** Search for any breaking point (at least 4 letters past s)
519 while (*t != ' ' && *t != '\t' && i < MAXSEARCH && t > (s + 4))
521 t--;
522 i++;
525 if (*t != ' ' && *t != '\t')
527 llassertprotect (maxline > 0);
528 t = mstring_copy (s + maxline);
529 *(s + maxline) = '\0';
531 if (*t == '\0')
533 sfree (t);
534 llassertprotect (*tp == NULL || (*tp > osp));
535 return;
538 sfreeEventually (t);
539 *tp = t;
540 /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
541 return;
543 else
546 *t = '\0';
547 t++;
549 if (*t == '\0') return;
552 ** returns unqualified as only
555 *tp = t;
557 llassert (*sp != *tp);
558 return;
562 BADBRANCH;
565 static
566 void limitmessage (/*@only@*/ cstring s, fileloc loc)
568 if (s_mcount > context_getLimit () + 1)
570 cstring_free (s);
572 else
574 cstring flstring = fileloc_unparse (loc);
576 s_lastfileloclen = cstring_length (flstring);
577 cstring_free (saveOneMessage);
578 saveOneMessage = message ("%q: %q", flstring, s);
582 static int parseerrorcount = 0;
584 void cleanupMessages (void)
586 parseerrorcount = 0;
588 if (context_unlimitedMessages ())
592 else
594 int unprinted = s_mcount - context_getLimit ();
596 if (unprinted > 0)
598 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
600 prepareMessage ();
601 printError (g_warningstream, saveOneMessage);
602 closeMessage ();
603 saveOneMessage = cstring_undefined;
605 else
607 if (cstring_isDefined (saveOneMessage))
609 /* cstring_free (saveOneMessage); */
610 saveOneMessage = cstring_undefined;
613 fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
614 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
615 s_mcount - context_getLimit ());
620 s_mcount = 0;
623 void
624 llgenmsg (/*@only@*/ cstring s, fileloc fl)
626 cstring flstring = fileloc_unparse (fl);
627 s_lastfileloclen = cstring_length (flstring);
629 prepareMessage ();
630 (void) printError (g_warningstream, message ("%q: %q", flstring, s));
631 closeMessage ();
634 void
635 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
637 cstring flstring = fileloc_unparse (fl);
638 int indentspaces = context_getLocIndentSpaces ();
639 prepareMessage ();
641 (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s),
642 indentspaces);
644 closeMessage ();
647 void
648 llgenindentmsgnoloc (/*@only@*/ cstring s)
650 prepareMessage ();
651 (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
652 closeMessage ();
655 static bool
656 llgentypeerroraux (const char *srcFile, int srcLine,
657 flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
658 /*@only@*/ cstring s, fileloc fl)
660 cstring hint = cstring_undefined;
661 flagcode code = ocode;
662 flagcode hcode = INVALID_FLAG;
663 ctype ut1 = t1;
664 ctype ut2 = t2;
666 DPRINTF (("Type error [%s]: %s / %s : %s / %s",
667 flagcode_unparse (ocode),
668 exprNode_unparse (e1), exprNode_unparse (e2),
669 ctype_unparse (t1), ctype_unparse (t2)));
671 DPRINTF (("Bool: %s / %s",
672 bool_unparse (ctype_isBool (t1)),
673 bool_unparse (ctype_isBool (t2))));
676 ** Set the flag using the underlying types that didn't match.
679 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
680 ut1 = ctype_baseArrayPtr (ut1);
681 ut2 = ctype_baseArrayPtr (ut2);
684 if (ctype_isRealNumAbstract (ut1) && exprNode_isNumLiteral (e2))
686 hcode = FLG_NUMABSTRACTLIT;
688 else if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
689 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
691 hcode = FLG_FLOATDOUBLE;
693 else if ((exprNode_isCharLiteral (e1) && ctype_isInt (ut2))
694 || (exprNode_isCharLiteral (e2) && ctype_isInt (ut1)))
696 hcode = FLG_CHARINTLITERAL;
698 else if ((exprNode_isNumLiteral (e1) && ctype_isReal (ut2))
699 || (exprNode_isNumLiteral (e2) && ctype_isReal (ut1)))
701 hcode = FLG_NUMLITERAL;
703 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
704 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
705 /* evs 2000-07-24: was ctype_isDirectBool */
707 hcode = FLG_BOOLINT;
709 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
710 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
712 hcode = FLG_CHARINT;
714 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
715 || (ctype_isChar (ut1) && ctype_isChar (ut2))
716 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
718 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
720 if (ctype_isArbitraryIntegral (ctype_realType (ut1))
721 && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
723 hcode = FLG_MATCHANYINTEGRAL;
725 else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
726 && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
728 hcode = FLG_MATCHANYINTEGRAL;
730 else
731 /*drl 4-270-2003 even if ignoresigns is set there may be another
732 problem that is causing splint to complain about a type error.
733 Don't tell the user that they can add +ignoresigns if it's
734 already on*/
736 DPRINTF(("TEST INGORESIGNS"));
737 if (context_getFlag(FLG_IGNORESIGNS) )
739 DPRINTF(("INGORESIGNS SET"));
740 hcode = FLG_IGNOREQUALS;
743 else
745 DPRINTF(("INGORESIGNS NOT SET"));
746 hcode = FLG_IGNORESIGNS;
750 else
752 hcode = FLG_IGNOREQUALS;
755 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
757 DPRINTF (("HERE: %s", ctype_unparse (ctype_realType (ut2))));
759 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
761 hcode = FLG_MATCHANYINTEGRAL;
763 else if (ctype_equal (ut2, ctype_ulint))
765 hcode = FLG_LONGUNSIGNEDINTEGRAL;
767 else if (ctype_equal (ut2, ctype_lint))
769 hcode = FLG_LONGINTEGRAL;
771 else if (ctype_isInt (ut2))
773 hcode = FLG_MATCHANYINTEGRAL;
775 else
777 hcode = FLG_TYPE;
780 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
782 ctype tr = ctype_realType (ut1);
784 if (ctype_isArbitraryIntegral (tr))
786 hcode = FLG_MATCHANYINTEGRAL;
788 else if (ctype_match (ut1, ctype_ulint))
790 if (ctype_isUnsignedIntegral (tr))
792 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
794 else if (ctype_isSignedIntegral (tr))
798 else
800 hcode = FLG_LONGUNSIGNEDINTEGRAL;
803 else if (ctype_match (ut1, ctype_lint))
805 if (ctype_isSignedIntegral (tr))
807 hcode = FLG_LONGSIGNEDINTEGRAL;
809 else if (ctype_isSignedIntegral (tr))
813 else
815 hcode = FLG_LONGINTEGRAL;
818 else if (ctype_isInt (ut1))
820 hcode = FLG_MATCHANYINTEGRAL;
822 else
827 else
832 if (hcode == INVALID_FLAG)
834 DPRINTF (("[%s] %s - %s / %s",
835 ctype_unparse (ut1),
836 bool_unparse (ctype_isEnum (ut1)),
837 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
838 bool_unparse (ctype_isInt (ut2))));
840 if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
842 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
843 ctype ct = uentry_getType (ue1);
845 if (ctype_match (ct, ut2))
847 code = FLG_ABSTRACT;
848 hint = message ("Underlying types match, but %s is an "
849 "abstract type that is not accessible here.",
850 ctype_unparse (t1));
853 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
855 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
856 ctype ct = uentry_getType (ue);
858 if (ctype_match (ct, ut1))
860 if (ctype_isNumAbstract (ut2))
862 if (exprNode_isNumLiteral (e1))
864 code = FLG_NUMABSTRACTLIT;
865 hint = message ("Underlying types match, but %s is a "
866 "numabstract type that is not accessible here. "
867 "(Use +numabstractlit to allow numeric literals "
868 "to be used as numabstract type values.)",
869 ctype_unparse (t2));
871 else
873 code = FLG_NUMABSTRACT;
874 hint = message ("Underlying types match, but %s is a "
875 "numabstract type that is not accessible here.",
876 ctype_unparse (t2));
879 else
881 code = FLG_ABSTRACT;
882 hint = message ("Underlying types match, but %s is an "
883 "abstract type that is not accessible here.",
884 ctype_unparse (t2));
888 else
890 ; /* Not an abstract mismatch. */
894 if (hcode == INVALID_FLAG)
896 if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
897 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
899 hcode = FLG_ENUMINT;
901 else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
902 || (ctype_isEnum (ut2) && ctype_isInt (ut1)))
904 hcode = FLG_ENUMINT;
906 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
907 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
909 hcode = FLG_CHARUNSIGNEDCHAR;
911 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
913 hcode = FLG_RELAXTYPES;
914 DPRINTF (("Setting relax types!"));
916 else
918 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
919 ctype_unparse (ut2)));
924 if (cstring_isDefined (hint))
926 if (!context_suppressFlagMsg (ocode, fl))
928 return xllgenhinterror (srcFile, srcLine, code, s, hint, fl);
930 else
932 cstring_free (s);
933 cstring_free (hint);
934 return FALSE;
937 else
939 if (hcode != INVALID_FLAG && hcode != ocode)
941 code = hcode;
944 if (llgenerroraux (ocode, srcFile, srcLine, s,
945 flagcodeHint (code), fl, TRUE, FALSE))
947 if (code != ocode)
949 if (context_flagOn (code, fl))
951 /* The flag is alreay set, something buggy in the flag code */
952 llcontbug (message ("No hint available, flag %s is already set.",
953 flagcode_unparse (code)));
955 else
957 llshowhint (code);
960 else
962 llsuppresshint ('-', code);
965 flagcode_recordError (code);
966 return TRUE;
969 return FALSE;
973 bool
974 xllgentypeerror (const char *srcFile, int srcLine,
975 ctype t1, exprNode e1, ctype t2, exprNode e2,
976 /*@only@*/ cstring s, fileloc fl)
978 return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
981 bool
982 xllgenformattypeerror (const char *srcFile, int srcLine,
983 ctype t1, exprNode e1, ctype t2, exprNode e2,
984 /*@only@*/ cstring s, fileloc fl)
986 if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
988 if (ctype_isInt (t1)
989 && ctype_isNumAbstract (t2))
991 if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT, fl))
993 return llgentypeerroraux (srcFile, srcLine, FLG_NUMABSTRACTPRINT, t1, e1, t2, e2, s, fl);
995 else
997 return FALSE;
1000 else
1002 return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
1005 else
1007 cstring_free (s);
1008 return FALSE;
1012 bool
1013 xllgenerror (const char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
1015 if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
1017 llnosuppresshint (o);
1018 flagcode_recordError (o);
1019 closeMessage ();
1020 return TRUE;
1022 else
1024 flagcode_recordSuppressed (o);
1025 return FALSE;
1029 bool
1030 xllgenhinterror (const char *srcFile, int srcLine,
1031 flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
1032 fileloc fl)
1034 if (!context_suppressFlagMsg (o, fl))
1036 if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
1038 flagcode_recordError (o);
1040 if (context_getFlag (FLG_HINTS))
1042 llgenhint (hint);
1044 else
1046 cstring_free (hint);
1049 closeMessage ();
1050 return TRUE;
1053 cstring_free (hint);
1055 else
1057 cstring_free (hint);
1058 cstring_free (s);
1061 flagcode_recordSuppressed (o);
1062 return FALSE;
1065 static bool
1066 llrealerror (flagcode code, const char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
1068 return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
1071 static bool
1072 llgenerroraux (flagcode code,
1073 const char *srcFile, int srcLine,
1074 /*@only@*/ cstring s,
1075 cstring addtext,
1076 fileloc fl, bool iserror, bool indent)
1078 if (context_inSuppressZone (fl))
1080 cstring_free (s);
1081 return FALSE;
1084 if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1085 return TRUE;
1086 } else {
1087 return FALSE;
1091 bool
1092 xllforceerror (const char *srcFile, int srcLine,
1093 flagcode code, /*@only@*/ cstring s, fileloc fl)
1095 flagcode_recordError (code);
1097 if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1098 closeMessage ();
1099 return TRUE;
1100 } else {
1101 return FALSE;
1105 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1108 if (g_csvstream != NULL) {
1109 /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1110 fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1111 context_numErrors (),
1112 (int) code, /* flag code */
1113 cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1114 flagcode_priority (code), /* priority */
1115 cstring_toCharsSafe (fileloc_outputFilename (fl)),
1116 fileloc_lineno (fl),
1117 fileloc_column (fl),
1118 cstring_toCharsSafe (s));
1120 if (cstring_isDefined (addtext)) {
1121 fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1122 } else {
1123 fprintf (g_csvstream, "\n");
1128 static bool
1129 llgenerrorreal (flagcode code, const char *srcFile, int srcLine,
1130 /*@only@*/ cstring s,
1131 cstring addtext,
1132 fileloc fl, bool iserror, bool indent)
1134 cstring flstring;
1136 /* duplicate message (rescanning a header file */
1138 if (!messageLog_add (context_messageLog (), fl, s))
1140 DPRINTF (("Duplicate message suppressed! %s / %s",
1141 fileloc_unparse (fl), s));
1142 cstring_free (s);
1143 return FALSE;
1147 ** If herald has not been displayed, display it before the first message.
1150 showHerald ();
1152 if (iserror) context_hasError ();
1154 if (context_unlimitedMessages ())
1158 else
1161 ** suppress excessive messages:
1162 ** check up to ':'
1166 char *sc = cstring_toCharsSafe (s);
1167 char *tmpmsg = strchr (sc, ':');
1169 if (tmpmsg == NULL)
1171 tmpmsg = sc;
1173 else
1175 char *savechar = tmpmsg;
1176 *tmpmsg = '\0';
1177 tmpmsg = sc;
1178 *savechar = ':';
1181 if (cstring_equal (s_lastmsg, cstring_fromChars (tmpmsg)))
1183 s_mcount++;
1184 if (s_mcount == (context_getLimit () + 1))
1186 limitmessage (s, fl);
1187 return FALSE;
1190 if (s_mcount > (context_getLimit ()))
1192 cstring_free (s);
1193 return FALSE;
1196 else
1198 cleanupMessages ();
1199 s_mcount = 0;
1200 cstring_free (s_lastmsg);
1201 s_lastmsg = cstring_fromCharsNew (tmpmsg);
1205 DPRINTF (("Here..."));
1207 if (context_hasAliasAnnote ())
1209 char *sc = cstring_toCharsSafe (s);
1210 char *fcolon = strchr (sc, ':');
1211 cstring a = context_getAliasAnnote ();
1214 if (fcolon == NULL)
1216 s = message ("%q (%q)", s, a);
1218 else
1220 cstring afterColon;
1222 *fcolon = '\0';
1223 afterColon = cstring_fromCharsNew (fcolon + 1);
1225 s = message ("%q (%q):%q", s, a, afterColon);
1229 if (context_hasMessageAnnote ())
1231 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1234 if (fcolon == NULL)
1236 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1237 s = message ("%q (%q)", s, context_getMessageAnnote ());
1238 /*@=dependenttrans@*/
1240 else
1242 cstring afterColon;
1244 *fcolon = '\0';
1245 afterColon = cstring_fromCharsNew (fcolon + 1);
1247 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1248 s = message ("%q (%q):%q", s,
1249 context_getMessageAnnote (), afterColon);
1250 /*@=dependenttrans@*/
1254 context_setNeednl ();
1255 prepareMessage ();
1257 if (context_showFunction ())
1259 cstring fname = fileloc_unparseFilename (g_currentloc);
1261 if (context_inIterDef ())
1263 fprintf (g_warningstream, "%s: (in iter %s)\n",
1264 cstring_toCharsSafe (fname),
1265 cstring_toCharsSafe (context_inFunctionName ()));
1267 else if (context_inIterEnd ())
1269 fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1270 cstring_toCharsSafe (fname),
1271 cstring_toCharsSafe (context_inFunctionName ()));
1273 else if (context_inMacro ())
1275 fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1276 cstring_toCharsSafe (context_inFunctionName ()));
1278 else
1280 fprintf (g_warningstream, "%s: (in function %s)\n",
1281 cstring_toCharsSafe (fname),
1282 cstring_toCharsSafe (context_inFunctionName ()));
1285 cstring_free (fname);
1286 context_setShownFunction ();
1289 flstring = fileloc_unparse (fl);
1290 s_lastfileloclen = cstring_length (flstring);
1292 generateCSV (code, s, addtext, fl);
1294 if (indent)
1296 printError (g_warningstream, message (" %q: %q", flstring, s));
1298 else
1300 printError (g_warningstream, message ("%q: %q", flstring, s));
1303 showSourceLoc (srcFile, srcLine);
1305 return TRUE;
1309 ** printMessage
1311 ** message contains no '\n'
1312 ** message fits in one line: print it
1313 ** message fits in two lines with 3-space indent after fileloc: print it
1314 ** split line with 5-space indent from left margin: print it
1318 static
1319 void printMessage (FILE *stream, /*@only@*/ cstring s)
1321 printIndentMessage (stream, s, 0);
1324 static
1325 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1327 static bool inbody = FALSE;
1328 int maxlen = context_getLineLen ();
1329 char *s = cstring_toCharsSafe (sc);
1330 char *olds = NULL;
1332 llassertprotect (!inbody);
1333 inbody = TRUE;
1337 char *t = NULL;
1338 char *st = s;
1340 llassertprotect (st != olds);
1341 olds = st;
1342 mstring_split (&st, &t, maxlen, &indent);
1343 fprintf (stream, "%s\n", st);
1344 llassertprotect (t != s);
1345 s = t;
1346 } while (s != NULL) ;
1348 cstring_free (sc);
1349 inbody = FALSE;
1352 static
1353 void printError (FILE *stream, /*@only@*/ cstring sc)
1355 int maxlen = context_getLineLen ();
1356 size_t nspaces = s_lastfileloclen + 5;
1357 int nextlen = maxlen - size_toInt (nspaces);
1358 size_t len = cstring_length (sc);
1359 int indent = 0;
1360 char *s = cstring_toCharsSafe (sc);
1361 char *os = s;
1362 char *t = NULL;
1364 DPRINTF (("Print error: [%s]", sc));
1366 if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1368 mstring_split (&s, &t, maxlen, &indent);
1370 fprintf (stream, "%s\n", s);
1372 if (t != NULL)
1374 len = mstring_length (t);
1376 if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1377 && size_toInt (len) > (nextlen - 1))
1379 fprintf (stream, " %s\n", t);
1381 else
1383 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1384 int i;
1386 for (i = 0; i < size_toInt (nspaces); i++)
1388 spaces[i] = ' ';
1391 spaces[nspaces] = '\0';
1393 while (t != NULL)
1395 char *st = t;
1396 mstring_split (&st, &t, nextlen, &indent);
1397 fprintf (stream, "%s%s\n", spaces, st);
1400 sfree (spaces);
1404 else
1406 DPRINTF (("Here 1: [%s]", sc));
1408 if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1410 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1412 if (nspaces < 1) nspaces = 1;
1414 nextlen = size_toInt (maxlen - nspaces);
1416 mstring_split (&s, &t, maxlen, &indent);
1418 fprintf (stream, "%s\n", s);
1420 if (t != NULL)
1422 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1423 int i;
1425 for (i = 0; i < size_toInt (nspaces); i++)
1427 spaces[i] = ' ';
1430 spaces[nspaces] = '\0';
1432 while (t != NULL)
1434 char *st = t;
1436 mstring_split (&st, &t, nextlen, &indent);
1437 fprintf (stream, "%s%s\n", spaces, st);
1440 sfree (spaces);
1443 else
1445 nspaces = 4;
1446 nextlen = size_toInt (maxlen - nspaces);
1448 DPRINTF (("Here 2: [%s]", s));
1449 mstring_split (&s, &t, maxlen, &indent);
1450 DPRINTF (("Here 3: [%s] [%s]", s, t));
1452 fprintf (stream, "%s\n", s);
1454 if (t != NULL)
1456 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1457 size_t i;
1459 for (i = 0; i < nspaces; i++)
1461 spaces[i] = ' ';
1464 spaces[nspaces] = '\0';
1466 while (t != NULL)
1468 char *st = t;
1469 DPRINTF (("Loop: [%s]", t));
1470 mstring_split (&st, &t, nextlen, &indent);
1471 DPRINTF (("Split: [%s] [%s]", st, t));
1472 fprintf (stream, "%s%s\n", spaces, st);
1473 DPRINTF (("Next..."));
1476 sfree (spaces);
1481 DPRINTF (("Done"));
1482 sfree (os);
1485 void
1486 xllfatalbug (const char *srcFile, int srcLine, /*@only@*/ cstring s)
1488 prepareMessage ();
1489 printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1490 fileloc_unparse (g_currentloc), s));
1491 showSourceLoc (srcFile, srcLine);
1492 printCodePoint ();
1493 printBugReport ();
1494 failexit ();
1497 void
1498 lclfatalbug (char *msg)
1500 prepareMessage ();
1501 printError (g_errorstream,
1502 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1503 printCodePoint ();
1504 printBugReport ();
1505 failexit ();
1508 void
1509 checkParseError (void)
1511 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1513 llfatalerror (message ("%q: Cannot recover from parse error.",
1514 fileloc_unparse (g_currentloc)));
1518 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1520 /*@unchecked@*/
1521 static int numbugs = 0;
1522 static bool inbug = FALSE;
1524 context_recordBug ();
1526 if (inbug)
1528 cstring temps = fileloc_unparseRaw (file, line);
1530 fprintf (g_errorstream,
1531 "%s: Recursive bug detected: %s\n",
1532 cstring_toCharsSafe (temps),
1533 cstring_toCharsSafe (s));
1534 cstring_free (temps);
1536 failexit ();
1539 inbug = TRUE;
1541 prepareMessage ();
1543 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1545 llfatalerror (message ("%q: Cannot recover from parse error.",
1546 fileloc_unparse (g_currentloc)));
1549 (void) fflush (g_warningstream);
1551 printError (g_errorstream,
1552 message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1553 fileloc_unparse (g_currentloc),
1554 fileloc_unparseRaw (file, line),
1555 s, errno));
1557 /* printCodePoint (); no longer useful */
1559 llflush ();
1562 ** This is confusing, and hardly ever useful.
1564 if (errno != 0)
1566 perror ("Possible system error diagnostic: ");
1572 printBugReport ();
1573 llflush ();
1575 numbugs++;
1577 if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1579 llfatalerror
1580 (message ("%q: Cannot recover from last bug. "
1581 "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1582 fileloc_unparse (g_currentloc)));
1585 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1586 fileloc_free (lastbug);
1587 lastbug = fileloc_copy (g_currentloc);
1588 closeMessage ();
1589 inbug = FALSE;
1592 void
1593 lclbug (/*@only@*/ cstring s)
1595 prepareMessage ();
1596 printError (g_errorstream, message ("*** Internal Bug: %q", s));
1597 printCodePoint ();
1598 printBugReport ();
1599 fprintf (g_errorstream, " (attempting to continue, results may be incorrect)\n");
1600 closeMessage ();
1603 void
1604 xllfatalerror (const char *srcFile, int srcLine, cstring s)
1606 prepareMessage ();
1607 printError (g_errorstream, s);
1608 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1609 showSourceLoc (srcFile, srcLine);
1610 failexit ();
1613 void
1614 xllfatalerrorLoc (const char *srcFile, int srcLine, /*@only@*/ cstring s)
1616 prepareMessage ();
1617 (void) fflush (g_warningstream);
1618 printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1619 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1620 showSourceLoc (srcFile, srcLine);
1621 (void) fflush (g_warningstream);
1622 failexit ();
1625 bool
1626 lclHadError (void)
1628 return (s_lclerrors > 0);
1631 bool
1632 lclHadNewError (void)
1634 static int lastcall = 0;
1636 if (s_lclerrors > lastcall)
1638 lastcall = s_lclerrors;
1639 return TRUE;
1641 else
1643 return FALSE;
1648 lclNumberErrors (void)
1650 return (s_lclerrors);
1653 void
1654 xlclerror (const char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1656 s_lclerrors++;
1658 if (ltoken_getCode (t) != NOTTOKEN)
1660 cstring loc = ltoken_unparseLoc (t);
1661 s_lastfileloclen = cstring_length (loc);
1663 printError (g_warningstream, message ("%q: %q", loc, msg));
1664 showSourceLoc (srcFile, srcLine);
1666 else
1668 printError (g_warningstream, msg);
1669 showSourceLoc (srcFile, srcLine);
1673 void
1674 lclplainerror (/*@only@*/ cstring msg)
1676 s_lclerrors++;
1677 printError (g_warningstream, msg);
1680 void
1681 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1683 if (ltoken_getCode (t) != NOTTOKEN)
1685 cstring loc = ltoken_unparseLoc (t);
1686 s_lastfileloclen = cstring_length (loc);
1687 printError (g_errorstream, message ("%q: %q", loc, msg));
1689 else
1691 printError (g_errorstream, msg);
1694 printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1695 failexit ();
1698 void
1699 lclplainfatalerror (/*@only@*/ cstring msg)
1701 (void) fflush (g_warningstream);
1702 printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1703 failexit ();
1706 void
1707 lclRedeclarationError (ltoken id)
1709 cstring s = ltoken_getRawString (id);
1712 if (usymtab_existsEither (s))
1714 uentry le = usymtab_lookupEither (s);
1716 lclerror (id, message ("Respecification of %s", s));
1717 llgenindentmsg (message ("Previous specification of %q",
1718 uentry_getName (le)),
1719 uentry_whereSpecified (le));
1721 else
1723 lclerror (id, message ("Identifier redeclared: %s", s));
1727 void genppllerror (flagcode code, /*@only@*/ cstring s)
1729 if (context_inSuppressZone (g_currentloc))
1731 cstring_free (s);
1733 else
1735 if (context_getFlag (code))
1737 if (s_scanOpen)
1739 displayScanClose ();
1742 llerror (code, s);
1744 if (code != FLG_PREPROC)
1746 llsuppresshint ('-', code);
1749 if (!context_isInCommandLine ())
1751 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1754 else
1756 cstring_free (s);
1761 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1762 /*@only@*/ cstring hint)
1764 if (context_inSuppressZone (g_currentloc))
1766 cstring_free (s);
1767 cstring_free (hint);
1769 else
1771 if (context_getFlag (code))
1773 generateCSV (code, s, hint, g_currentloc);
1774 prepareMessage ();
1775 context_clearPreprocessing ();
1776 llerror (code, s);
1777 llgenhint (hint);
1778 context_setPreprocessing ();
1779 closeMessage ();
1781 else
1783 cstring_free (s);
1784 cstring_free (hint);
1789 void ppllerror (/*@only@*/ cstring s)
1791 genppllerror (FLG_PREPROC, s);
1794 # ifdef DEADCODE
1795 void pplldiagmsg (cstring s)
1797 if (!context_isInCommandLine ())
1799 if (s_scanOpen)
1801 displayScanClose ();
1804 lldiagmsg (s);
1805 displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1807 else
1809 lldiagmsg (s);
1812 # endif /* DEADCODE */
1814 void loadllmsg (cstring s)
1816 displayScanClose ();
1817 lldiagmsg (s);
1818 displayScanOpen (cstring_makeLiteral ("< ."));
1821 static void llreportparseerror (/*@only@*/ cstring s)
1823 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1825 cstring_free (s);
1827 else
1829 llerror (FLG_SYNTAX, s);
1831 fileloc_free (lastparseerror);
1832 lastparseerror = fileloc_copy (g_currentloc);
1836 bool xlloptgenerror (const char *srcFile, int srcLine,
1837 flagcode o, /*@only@*/ cstring s, fileloc loc)
1839 DPRINTF (("xllopt: %s", s));
1841 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1843 DPRINTF (("Here we are!"));
1844 llsuppresshint ('-', o);
1845 closeMessage ();
1846 flagcode_recordError (o);
1847 return TRUE;
1849 else
1851 DPRINTF (("Suppressed!"));
1852 flagcode_recordSuppressed (o);
1853 return FALSE;
1857 bool xoptgenerror2 (const char *srcFile, int srcLine,
1858 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1860 if (context_suppressFlagMsg (f1, loc))
1862 flagcode_recordSuppressed (f1);
1863 cstring_free (s);
1865 else
1867 if (context_suppressFlagMsg (f2, loc))
1869 flagcode_recordSuppressed (f2);
1870 cstring_free (s);
1872 else
1874 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1876 llsuppresshint2 ('-', f1, f2);
1877 flagcode_recordError (f2);
1878 closeMessage ();
1879 return TRUE;
1881 else
1883 flagcode_recordSuppressed (f2);
1888 return FALSE;
1891 bool xoptgenerror2n (const char *srcFile, int srcLine,
1892 flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1895 if (context_suppressFlagMsg (f1, loc))
1897 flagcode_recordSuppressed (f1);
1898 cstring_free (s);
1900 else
1902 if (context_suppressNotFlagMsg (f2, loc))
1904 flagcode_recordSuppressed (f2);
1905 cstring_free (s);
1907 else
1909 if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1911 llsuppresshint ('+', f2);
1912 flagcode_recordError (f2);
1913 closeMessage ();
1914 return TRUE;
1917 flagcode_recordSuppressed (f2);
1920 return FALSE;
1923 bool xllnoptgenerror (const char *srcFile, int srcLine,
1924 flagcode o, /*@only@*/ cstring s, fileloc loc)
1926 if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1928 llsuppresshint ('+', o);
1929 flagcode_recordError (o);
1930 closeMessage ();
1931 return TRUE;
1934 flagcode_recordSuppressed (o);
1935 return FALSE;
1938 void xllparseerror (const char *srcFile, int srcLine, cstring s)
1940 if (context_getFlag (FLG_TRYTORECOVER))
1942 parseerrorcount++;
1944 if (parseerrorcount > GIVEUPPARSE)
1946 if (cstring_isDefined (s))
1948 xllfatalerror (srcFile, srcLine,
1949 message ("%q: Parse Error: %q. "
1950 "Too many errors, giving up.",
1951 fileloc_unparse (g_currentloc), s));
1953 else
1955 xllfatalerror (srcFile, srcLine,
1956 message ("%q: Parse Error. Too many errors, giving up.",
1957 fileloc_unparse (g_currentloc)));
1960 else
1962 if (cstring_isDefined (s))
1964 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1965 s));
1966 showSourceLoc (srcFile, srcLine);
1968 else
1970 llreportparseerror (message ("Parse Error. Attempting to continue."));
1971 showSourceLoc (srcFile, srcLine);
1975 else
1977 cstring msg;
1979 if (cstring_isDefined (s))
1981 msg = message ("Parse Error: %q.", s);
1983 else
1985 msg = message ("Parse Error.");
1988 xllfatalerror
1989 (srcFile, srcLine,
1990 message ("%q: %s (For help on parse errors, "
1991 "see splint -help parseerrors.)",
1992 fileloc_unparse (g_currentloc), msg));
1996 bool xfsgenerror (const char *srcFile, int srcLine,
1997 flagSpec fs, /*@only@*/ cstring s, fileloc fl)
1999 if (flagSpec_isOn (fs, fl))
2001 flagcode firston = flagSpec_getFirstOn (fs, fl);
2003 if (llgenerroraux (firston, srcFile, srcLine, s,
2004 flagcodeHint (firston),
2005 fl, TRUE, FALSE))
2007 llsuppresshint ('-', firston);
2008 flagcode_recordError (firston);
2009 return TRUE;
2011 else
2013 flagcode_recordSuppressed (firston);
2014 return FALSE;
2017 else
2019 flagcode_recordSuppressed (flagSpec_getDominant (fs));
2020 cstring_free (s);
2021 return FALSE;
2025 bool doCheck (bool x, cstring pred, cstring file, int line)
2027 if (!x) {
2028 llbug (message ("%q: Check Failed: %s",
2029 fileloc_unparseRaw (file, line),
2030 pred));
2033 return x;
2036 /*@observer@*/ cstring lldecodeerror (int errnum)
2038 return cstring_fromChars (strerror (errnum));
2041 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2043 # if 0
2044 llflush ();
2045 printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2046 fileloc_unparse (g_currentloc),
2047 fileloc_unparseRaw (file, line),
2048 s, errno));
2049 printCodePoint ();
2050 llflush ();
2051 # else
2052 cstring_free (s);
2053 # endif
2056 void llflush (void)
2058 (void) fflush (g_warningstream);
2059 (void) fflush (g_messagestream);
2062 void displayScan (cstring msg)
2064 if (s_scanOpen)
2066 displayScanClose ();
2069 llassert (!s_scanOpen);
2071 if (context_getFlag (FLG_SHOWSCAN))
2073 showHerald ();
2074 fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2075 (void) fflush (g_messagestream);
2078 cstring_free (msg);
2081 void displayScanOpen (cstring msg)
2083 if (s_scanOpen)
2085 displayScanClose ();
2088 llassert (!s_scanOpen);
2089 s_scanOpen = TRUE;
2091 if (context_getFlag (FLG_SHOWSCAN))
2093 fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2094 (void) fflush (g_messagestream);
2097 cstring_free (msg);
2100 void displayScanContinue (/*@temp@*/ cstring msg)
2102 if (context_getFlag (FLG_SHOWSCAN))
2104 if (s_scanOpen)
2106 fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2107 (void) fflush (g_messagestream);
2109 else
2112 ** Don't call bug recursively
2115 fprintf (stderr, "*** Bug: scan continue scan not open\n");
2120 void displayScanClose (void)
2122 if (s_scanOpen)
2124 if (context_getFlag (FLG_SHOWSCAN))
2126 fprintf (g_messagestream, " >\n");
2127 (void) fflush (g_messagestream);
2130 else
2133 ** Don't call bug recursively
2136 fprintf (stderr, "*** Bug: scan close scan not open\n");
2139 s_scanOpen = FALSE;