]> andersk Git - splint.git/blame - src/llerror.c
Updating to use the LEnsures and LRequires instead of the ensures requires so
[splint.git] / src / llerror.c
CommitLineData
90bc41f7 1#include <assert.h> /*drl take this out*/
616915dd 2/*
3** LCLint - annotation-assisted static program checker
4** Copyright (C) 1994-2000 University of Virginia,
5** Massachusetts Institute of Technology
6**
7** This program is free software; you can redistribute it and/or modify it
8** under the terms of the GNU General Public License as published by the
9** Free Software Foundation; either version 2 of the License, or (at your
10** option) any later version.
11**
12** This program is distributed in the hope that it will be useful, but
13** WITHOUT ANY WARRANTY; without even the implied warranty of
14** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15** General Public License for more details.
16**
17** The GNU General Public License is available from http://www.gnu.org/ or
18** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19** MA 02111-1307, USA.
20**
21** For information on lclint: lclint-request@cs.virginia.edu
22** To report a bug: lclint-bug@cs.virginia.edu
23** For more information: http://lclint.cs.virginia.edu
24*/
25/*
26** llerror.c
27**
28** error reporting procedures
29*/
30
31# include "lclintMacros.nf"
32# include <string.h>
33# include <errno.h>
34# include "llbasic.h"
35# include "llmain.h"
36# include "version.h"
37
38static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
39 /*@modifies *p_stream@*/ ;
40
41# ifndef NOLCL
42static int lclerrors = 0;
43# endif
44
45static int lastfileloclen = 10;
46static /*@only@*/ cstring lastmsg = cstring_undefined;
47static int mcount = 0;
48static /*@only@*/ cstring saveOneMessage = cstring_undefined;
49static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
50static /*@only@*/ fileloc lastbug = fileloc_undefined;
51static bool llgenerrorreal (/*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
52 /*@modifies g_msgstream@*/ ;
53static bool llgenerroraux (/*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
54 /*@modifies g_msgstream@*/ ;
55static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
56 /*@globals lastfileloclen @*/
57 /*@modifies *p_stream@*/ ;
58static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
59 /*@modifies *p_stream@*/ ;
60
61static /*@null@*/ char *
62maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
63{
64 if (a > b) return a;
65 else return b;
66}
67
68static void
69printBugReport (void)
70{
71 fprintf (stderr, " *** Please report bug to %s ***\n",
72 LCLINT_MAINTAINER);
73 llflush ();
74 /* don't exit (EXIT_FAILURE); */
75}
76
77static bool s_needsPrepare = TRUE;
78
79void prepareMessage (void)
80{
81 if (context_isPreprocessing ()
82 && s_needsPrepare
83 && context_getDebug (FLG_SHOWSCAN))
84 {
85 llflush ();
86 fprintf (stderr, " >\n");
87 s_needsPrepare = FALSE;
88 }
89
90 llflush ();
91}
92
93void closeMessage (void)
94{
95 if (context_isPreprocessing ()
96 && context_getDebug (FLG_SHOWSCAN))
97 {
98 llflush ();
99 fprintf (stderr, "< more preprocessing .");
100
101 llassert (!s_needsPrepare);
102 s_needsPrepare = TRUE;
103 }
104 else
105 {
106 llflush ();
107 }
108}
109
110void
111llmsg (/*@only@*/ cstring s)
112{
113 context_setNeednl ();
114 prepareMessage ();
115 printMessage (g_msgstream, s);
116 closeMessage ();
117}
118
119void
120lldiagmsg (/*@only@*/ cstring s)
121{
122 context_setNeednl ();
123 prepareMessage ();
124 printMessage (stderr, s);
125 closeMessage ();
126}
127
128void
129llmsgplain (/*@only@*/ cstring s)
130{
131 context_setNeednl ();
132 prepareMessage ();
133 printMessage (g_msgstream, s);
134 closeMessage ();
135}
136
137void flagWarning (cstring s)
138{
139 if (context_getFlag (FLG_WARNFLAGS))
140 {
141 showHerald ();
142
143 if (fileloc_isBuiltin (g_currentloc))
144 {
145 llmsg (message ("Warning: %s", s));
146 }
147 else
148 {
149 llgenmsg (message ("Warning: %s", s), g_currentloc);
150 }
151 }
152}
153
154static void
155llgenhint (/*@only@*/ cstring s) /*@modifies g_msgstream@*/
156{
157 context_setNeednl ();
158 printIndentMessage (g_msgstream, s, 2);
159}
160
161void
162llhint (cstring s)
163{
164 if (context_getFlag (FLG_HINTS) &&
165 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
166 {
167 llgenhint (s);
168 }
169 else
170 {
171 cstring_free (s);
172 }
173}
174
175static void
176llshowhint (flagcode f)
177{
178 if (context_getFlag (FLG_HINTS))
179 {
180 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
181 {
182 cstring desc = flagcodeHint (f);
183
184 if (cstring_isDefined (desc))
185 {
186 llgenhint (cstring_copy (desc));
187 }
188 }
189 }
190}
191
192
193static void
194llsuppresshint (char c, flagcode f)
195{
196
197 if (context_getFlag (FLG_HINTS))
198 {
199 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
200 {
201 cstring desc = flagcodeHint (f);
202 context_setNeednl ();
203 lastfileloclen = 8;
204
205 if (flagcode_isNamePrefixFlag (f))
206 {
207 f = FLG_NAMECHECKS;
208 }
209
210 if (cstring_isDefined (desc))
211 {
212 llgenhint (message ("%s (%h%s will suppress message)", desc, c,
213 flagcode_name (f)));
214 }
215 else
216 {
217 llgenhint (message ("(%h%s will suppress message)", c,
218 flagcode_name (f)));
219 }
220 }
221 }
222}
223
224static void
225llnosuppresshint (flagcode f)
226{
227
228 if (context_getFlag (FLG_FORCEHINTS))
229 {
230 cstring desc = flagcodeHint (f);
231 context_setNeednl ();
232 lastfileloclen = 8;
233
234 if (cstring_isDefined (desc))
235 {
236 printError (g_msgstream, message (" %s", desc));
237 }
238 }
239}
240
241/*@constant int MAXSEARCH; @*/
242# define MAXSEARCH 20
243
244/*@constant int MINLINE; @*/
245# define MINLINE 35
246
247typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
248
249static void
250mstring_split (/*@returned@*/ char **sp,
251 /*@out@*/ nd_charp *tp,
252 int maxline, /*@in@*/ int *indentchars)
253{
254 char *nl;
255 char *t;
256 char *s = *sp;
257
258 *tp = NULL;
259
260 if (maxline < MINLINELEN)
261 {
262 maxline = MINLINELEN;
263 }
264
265 if (*indentchars > 0)
266 {
267 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
268 }
269
270 nl = strchr (s, '\n');
271
272 /*
273 ** splitting:
274 **
275 ** if there is a newline in first maxline characters, split there
276 ** if line len is <= maxline, return no split
277 ** if there is a ':' or ';' followed by ' ' in first maxline characters,
278 ** split there unless the ' ' is followed by a '}', then
279 ** split after '}'
280 ** of the ';' is inside quotation marks
281 ** if there is a space or tab in last maxsearch characters, split there
282 ** else, split at maxline
283 **
284 ** special code: slash [1-9] after a newline means indent the rest <n> chars
285 **
286 */
287
288 if ((nl != NULL) && ((nl - s) < maxline))
289 {
290 *nl = '\0';
291 t = nl + 1;
292
293 if (*t == '\0')
294 {
295 return;
296 }
297
298 if (*t >= '\1' && *t <= '\7')
299 {
300 *indentchars += (int) (*t - '\1') + 1;
301 t++;
302 }
303
304 *tp = t;
305 return;
306 }
307 else if (size_toInt (strlen (s)) < maxline)
308 {
309 return;
310 }
311 else
312 {
313 int i = 0;
314 char savechar;
315 char *lcolon, *lsemi, *splitat;
316
317 splitat = NULL;
318
319 t = s + maxline - 1;
320 savechar = *t;
321
322 *t = '\0';
323 lcolon = strrchr (s, ':');
324 lsemi = strrchr (s, ';');
325 *t = savechar;
326
327 splitat = maxcp (lcolon, lsemi);
328
329 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
330 && *(splitat + 1) == ' ' && *(splitat + 2) != '}')
331 {
332 *(splitat + 1) = '\0';
333 t = splitat + 2;
334 *tp = t;
335 return;
336 }
337
338 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
339 {
340 t--;
341 i++;
342 }
343
344 if (*t != ' ' && *t != '\t')
345 {
346 t = mstring_copy (s + maxline);
347 *(s + maxline) = '\0';
348
349 if (*t == '\0')
350 {
351 sfree (t);
352 return;
353 }
354
355 mstring_markFree (t);
356 *tp = t;
357 return;
358 }
359 else
360 {
361 *t = '\0';
362 t++;
363
364 if (*t == '\0') return;
365
366 /*
367 ** returns unqualified as only
368 */
369
370 *tp = t;
371 return;
372 }
373 }
374}
375
376static
377void limitmessage (/*@only@*/ cstring s, fileloc loc)
378{
379 if (mcount > context_getLimit () + 1)
380 {
381 cstring_free (s);
382 }
383 else
384 {
385 cstring flstring = fileloc_unparse (loc);
386
387 lastfileloclen = cstring_length (flstring);
388 cstring_free (saveOneMessage);
389 saveOneMessage = message ("%q: %q", flstring, s);
390 }
391}
392
393static int parseerrorcount = 0;
394
395void cleanupMessages ()
396{
397 parseerrorcount = 0;
398
399 if (context_unlimitedMessages ())
400 {
401 ;
402 }
403 else
404 {
405 int unprinted = mcount - context_getLimit ();
406
407 if (unprinted > 0)
408 {
409 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
410 {
411 prepareMessage ();
412 printError (g_msgstream, saveOneMessage);
413 closeMessage ();
414 saveOneMessage = cstring_undefined;
415 }
416 else
417 {
418 if (cstring_isDefined (saveOneMessage))
419 {
420 /* cstring_free (saveOneMessage); */
421 saveOneMessage = cstring_undefined;
422 }
423
424 fprintf (g_msgstream, "%s: (%d more similar errors unprinted)\n",
425 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
426 mcount - context_getLimit ());
427 }
428 }
429 }
430
431 mcount = 0;
432}
433
434void
435llgenmsg (/*@only@*/ cstring s, fileloc fl)
436{
437 cstring flstring = fileloc_unparse (fl);
438 lastfileloclen = cstring_length (flstring);
439
440 prepareMessage ();
441 (void) printError (g_msgstream, message ("%q: %q", flstring, s));
442 closeMessage ();
443}
444
445void
446llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
447{
448 cstring flstring = fileloc_unparse (fl);
449
450 prepareMessage ();
451 (void) printIndentMessage (g_msgstream, message ("%q: %q", flstring, s), 3);
452 closeMessage ();
453}
454
455void
456llgenindentmsgnoloc (/*@only@*/ cstring s)
457{
458 prepareMessage ();
459 (void) printIndentMessage (g_msgstream, s, 3);
460 closeMessage ();
461}
462
463static bool
464 llgentypeerroraux (flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
465 /*@only@*/ cstring s, fileloc fl)
466{
467 cstring hint = cstring_undefined;
468 flagcode code = ocode;
469 flagcode hcode = INVALID_FLAG;
470 ctype ut1 = t1;
471 ctype ut2 = t2;
472
473 DPRINTF (("Type error: %s / %s : %s / %s",
474 exprNode_unparse (e1), exprNode_unparse (e2),
475 ctype_unparse (t1), ctype_unparse (t2)));
476
477 DPRINTF (("Bool: %s / %s",
478 bool_unparse (ctype_isBool (t1)),
479 bool_unparse (ctype_isBool (t2))));
480
481 /*
482 ** Set the flag using the underlying types that didn't match.
483 */
484
485 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
486 ut1 = ctype_baseArrayPtr (ut1);
487 ut2 = ctype_baseArrayPtr (ut2);
488 }
489
490 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
491 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
492 {
493 hcode = FLG_FLOATDOUBLE;
494 }
495 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
496 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
497 {
498 hcode = FLG_CHARINTLITERAL;
499 }
500 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
501 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
502 {
503 hcode = FLG_NUMLITERAL;
504 }
505 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
506 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
507 /* evs 2000-07-24: was ctype_isDirectBool */
508 {
509 hcode = FLG_BOOLINT;
510 }
511 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
512 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
513 {
514 hcode = FLG_CHARINT;
515 }
516 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
517 || (ctype_isChar (ut1) && ctype_isChar (ut2))
518 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
519 {
520 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
521 {
522 hcode = FLG_IGNORESIGNS;
523 }
524 else
525 {
526 hcode = FLG_IGNOREQUALS;
527 }
528 }
529 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
530 {
531 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
532 {
533 hcode = FLG_MATCHANYINTEGRAL;
534 }
535 else if (ctype_match (ut2, ctype_ulint))
536 {
537 hcode = FLG_LONGUNSIGNEDINTEGRAL;
538 }
539 else if (ctype_match (ut2, ctype_lint))
540 {
541 hcode = FLG_LONGINTEGRAL;
542 }
543 else if (ctype_isInt (ut2))
544 {
545 hcode = FLG_MATCHANYINTEGRAL;
546 }
547 else
548 {
549 ;
550 }
551 }
552 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
553 {
554 ctype tr = ctype_realType (ut1);
555
556 if (ctype_isArbitraryIntegral (tr))
557 {
558 hcode = FLG_MATCHANYINTEGRAL;
559 }
560 else if (ctype_match (ut1, ctype_ulint))
561 {
562 if (ctype_isUnsignedIntegral (tr))
563 {
564 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
565 }
566 else if (ctype_isSignedIntegral (tr))
567 {
568 ;
569 }
570 else
571 {
572 hcode = FLG_LONGUNSIGNEDINTEGRAL;
573 }
574 }
575 else if (ctype_match (ut1, ctype_lint))
576 {
577 if (ctype_isSignedIntegral (tr))
578 {
579 hcode = FLG_LONGSIGNEDINTEGRAL;
580 }
581 else if (ctype_isSignedIntegral (tr))
582 {
583 ;
584 }
585 else
586 {
587 hcode = FLG_LONGINTEGRAL;
588 }
589 }
590 else if (ctype_isInt (ut1))
591 {
592 hcode = FLG_MATCHANYINTEGRAL;
593 }
594 else
595 {
596 ;
597 }
598 }
599 else if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
600 {
601 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
602 ctype ct = uentry_getType (ue1);
603
604 if (ctype_match (ct, ut2))
605 {
606 code = FLG_ABSTRACT;
607 hint = message ("Underlying types match, but %s is an "
608 "abstract type that is not accessible here.",
609 ctype_unparse (t1));
610 }
611 }
612 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
613 {
614 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
615 ctype ct = uentry_getType (ue);
616
617 if (ctype_match (ct, ut1))
618 {
619 code = FLG_ABSTRACT;
620 hint = message ("Underlying types match, but %s is an "
621 "abstract type that is not accessible here.",
622 ctype_unparse (t2));
623 }
624 }
625 else if ((ctype_isEnum (ut1) && ctype_isArbitraryIntegral (ut2))
626 || (ctype_isEnum (ut2) && ctype_isArbitraryIntegral (ut1)))
627 {
628 code = FLG_ENUMINT;
629 }
630 else if ((ctype_isEnum (ut1) && ctype_isArbitraryIntegral (ut2))
631 || (ctype_isEnum (ut2) && ctype_isArbitraryIntegral (ut1)))
632 {
633 code = FLG_ENUMINT;
634 }
635 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
636 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
637 {
638 code = FLG_CHARUNSIGNEDCHAR;
639 }
640 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
641 {
642 code = FLG_RELAXTYPES;
643 }
644 else
645 {
646 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
647 ctype_unparse (ut2)));
648 }
649
650 if (cstring_isDefined (hint))
651 {
652 if (!context_suppressFlagMsg (ocode, fl))
653 {
654 return llgenhinterror (code, s, hint, fl);
655 }
656 else
657 {
658 cstring_free (s);
659 cstring_free (hint);
660 return FALSE;
661 }
662 }
663 else
664 {
665 if (llgenerroraux (s, fl, TRUE, FALSE))
666 {
667 if (hcode != INVALID_FLAG && hcode != ocode)
668 {
669 code = hcode;
670 llshowhint (code);
671
672 }
673 else
674 {
675 llsuppresshint ('-', code);
676 }
677
678 flagcode_recordError (code);
679 return TRUE;
680 }
681
682 return FALSE;
683 }
684}
685
686bool
687llgentypeerror (ctype t1, exprNode e1, ctype t2, exprNode e2,
688 /*@only@*/ cstring s, fileloc fl)
689{
690 return llgentypeerroraux (FLG_TYPE, t1, e1, t2, e2, s, fl);
691}
692
693bool
694llgenformattypeerror (ctype t1, exprNode e1, ctype t2, exprNode e2,
695 /*@only@*/ cstring s, fileloc fl)
696{
697 return llgentypeerroraux (FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
698}
699
700bool
701llgenerror (flagcode o, /*@only@*/ cstring s, fileloc fl)
702{
703 if (llgenerroraux (s, fl, TRUE, FALSE))
704 {
705 llnosuppresshint (o);
706 flagcode_recordError (o);
707 closeMessage ();
708 return TRUE;
709 }
710 else
711 {
712 flagcode_recordSuppressed (o);
713 return FALSE;
714 }
715}
716
717bool
718llgenhinterror (flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
719 fileloc fl)
720{
721 if (!context_suppressFlagMsg (o, fl))
722 {
723 if (llgenerroraux (s, fl, TRUE, FALSE))
724 {
725 flagcode_recordError (o);
726
727 if (context_getFlag (FLG_HINTS))
728 {
729 llgenhint (hint);
730 }
731 else
732 {
733 cstring_free (hint);
734 }
735
736 closeMessage ();
737 return TRUE;
738 }
739
740 cstring_free (hint);
741 }
742 else
743 {
744 cstring_free (hint);
745 cstring_free (s);
746 }
747
748 flagcode_recordSuppressed (o);
749 return FALSE;
750}
751
752static bool
753llrealerror (/*@only@*/ cstring s, fileloc fl)
754{
755 return (llgenerrorreal (s, fl, TRUE, FALSE));
756}
757
758static bool
759llgenerroraux (/*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
760{
761
762 if (context_inSuppressZone (fl))
763 {
764 cstring_free (s);
765 return FALSE;
766 }
767 else
768 {
769 ;
770 }
771
772 return (llgenerrorreal (s, fl, iserror, indent));
773}
774
775void
776llforceerror (flagcode code, /*@only@*/ cstring s, fileloc fl)
777{
778 flagcode_recordError (code);
779 (void) llgenerrorreal (s, fl, TRUE, FALSE);
780 closeMessage ();
781}
782
783static bool
784llgenerrorreal (/*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
785{
786 cstring flstring;
787
788 /* duplicate message (rescanning a header file */
789
790 if (!messageLog_add (context_messageLog (), fl, s))
791 {
792 cstring_free (s);
793 return FALSE;
794 }
795
796 if (iserror) context_hasError ();
797
798 if (context_unlimitedMessages ())
799 {
800 ;
801 }
802 else
803 {
804 /*
805 ** suppress excessive messages:
806 ** check up to ':'
807 **
808 */
809
810 char *sc = cstring_toCharsSafe (s);
811 char *tmpmsg = strchr (sc, ':');
812
813 if (tmpmsg == NULL)
814 {
815 tmpmsg = sc;
816 }
817 else
818 {
819 char *savechar = tmpmsg;
820 *tmpmsg = '\0';
821 tmpmsg = sc;
822 *savechar = ':';
823 }
824
825 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
826 {
827 mcount++;
828 if (mcount == (context_getLimit () + 1))
829 {
830 limitmessage (s, fl);
831 return FALSE;
832 }
833
834 if (mcount > (context_getLimit ()))
835 {
836 cstring_free (s);
837 return FALSE;
838 }
839 }
840 else
841 {
842 cleanupMessages ();
843 mcount = 0;
844 cstring_free (lastmsg);
845 lastmsg = cstring_fromCharsNew (tmpmsg);
846 }
847 }
848
849 if (context_hasAliasAnnote ())
850 {
851 char *sc = cstring_toCharsSafe (s);
852 char *fcolon = strchr (sc, ':');
853 cstring a = context_getAliasAnnote ();
854
855
856 if (fcolon == NULL)
857 {
858 s = message ("%q (%q)", s, a);
859 }
860 else
861 {
862 cstring afterColon;
863
864 *fcolon = '\0';
865 afterColon = cstring_fromCharsNew (fcolon + 1);
866
867 s = message ("%q (%q):%q", s, a, afterColon);
868 }
869 }
870
871 if (context_hasMessageAnnote ())
872 {
873 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
874
875
876 if (fcolon == NULL)
877 {
878 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
879 s = message ("%q (%q)", s, context_getMessageAnnote ());
880 /*@=dependenttrans@*/
881 }
882 else
883 {
884 cstring afterColon;
885
886 *fcolon = '\0';
887 afterColon = cstring_fromCharsNew (fcolon + 1);
888
889 /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
890 s = message ("%q (%q):%q", s,
891 context_getMessageAnnote (), afterColon);
892 /*@=dependenttrans@*/
893 }
894 }
895
896 context_setNeednl ();
897 prepareMessage ();
898
899 if (context_showFunction ())
900 {
901 cstring fname = fileloc_unparseFilename (g_currentloc);
902
903 if (context_inIterDef ())
904 {
905 fprintf (g_msgstream, "%s: (in iter %s)\n",
906 cstring_toCharsSafe (fname),
907 cstring_toCharsSafe (context_inFunctionName ()));
908 }
909 else if (context_inIterEnd ())
910 {
911 fprintf (g_msgstream, "%s: (in iter finalizer %s)\n",
912 cstring_toCharsSafe (fname),
913 cstring_toCharsSafe (context_inFunctionName ()));
914 }
915 else if (context_inMacro ())
916 {
917 fprintf (g_msgstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
918 cstring_toCharsSafe (context_inFunctionName ()));
919 }
920 else
921 {
922 fprintf (g_msgstream, "%s: (in function %s)\n",
923 cstring_toCharsSafe (fname),
924 cstring_toCharsSafe (context_inFunctionName ()));
925 }
926
927 cstring_free (fname);
928 context_setShownFunction ();
929 }
930
931 flstring = fileloc_unparse (fl);
932
933 lastfileloclen = cstring_length (flstring);
934
935 if (indent)
936 {
937 printError (g_msgstream, message (" %q: %q", flstring, s));
938 }
939 else
940 {
941 printError (g_msgstream, message ("%q: %q", flstring, s));
942 }
943
944 return TRUE;
945}
946
947/*
948** printMessage
949**
950** message contains no '\n'
951** message fits in one line: print it
952** message fits in two lines with 3-space indent after fileloc: print it
953** split line with 5-space indent from left margin: print it
954**
955*/
956
957static
958void printMessage (FILE *stream, /*@only@*/ cstring s)
959{
960 printIndentMessage (stream, s, 0);
961}
962
963static
964void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
965{
966 int maxlen = context_getLineLen ();
967 char *s = cstring_toCharsSafe (sc);
968
969
970 do
971 {
972 char *t = NULL;
973 char *st = s;
974
975 mstring_split (&st, &t, maxlen, &indent);
976 fprintf (stream, "%s\n", st);
977 llassert (t != s);
978 s = t;
979 } while (s != NULL) ;
980
981 cstring_free (sc);
982}
983
984static
985void printError (FILE *stream, /*@only@*/ cstring sc)
986{
987 int maxlen = context_getLineLen ();
988 int nspaces = lastfileloclen + 5;
989 int nextlen = maxlen - nspaces;
990 int len = cstring_length (sc);
991 int indent = 0;
992 char *s = cstring_toCharsSafe (sc);
993 char *os = s;
994 char *t = NULL;
995
996 if (len < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
997 {
998 mstring_split (&s, &t, maxlen, &indent);
999
1000 fprintf (stream, "%s\n", s);
1001
1002 if (t != NULL)
1003 {
1004 len = mstring_length (t);
1005
1006 if (len < (maxlen - 3) && (strchr (t, '\n') == NULL)
1007 && len > (nextlen - 1))
1008 {
1009 fprintf (stream, " %s\n", t);
1010 }
1011 else
1012 {
1013 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1014 int i;
1015
1016 for (i = 0; i < nspaces; i++)
1017 {
1018 spaces[i] = ' ';
1019 }
1020
1021 spaces[nspaces] = '\0';
1022
1023 while (t != NULL)
1024 {
1025 char *st = t;
1026 mstring_split (&st, &t, nextlen, &indent);
1027 fprintf (stream, "%s%s\n", spaces, st);
1028 }
1029
1030 sfree (spaces);
1031 }
1032 }
1033 }
1034 else
1035 {
1036 if (len < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1037 {
1038 nspaces = ((maxlen + maxlen - 1) - len) / 2;
1039
1040 if (nspaces < 1) nspaces = 1;
1041
1042 nextlen = maxlen - nspaces;
1043
1044 mstring_split (&s, &t, maxlen, &indent);
1045
1046 fprintf (stream, "%s\n", s);
1047
1048 if (t != NULL)
1049 {
1050 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1051 int i;
1052
1053 for (i = 0; i < nspaces; i++)
1054 {
1055 spaces[i] = ' ';
1056 }
1057
1058 spaces[nspaces] = '\0';
1059
1060 while (t != NULL)
1061 {
1062 char *st = t;
1063
1064 mstring_split (&st, &t, nextlen, &indent);
1065 fprintf (stream, "%s%s\n", spaces, st);
1066 }
1067
1068 sfree (spaces);
1069 }
1070 }
1071 else
1072 {
1073 nspaces = 4;
1074 nextlen = maxlen - nspaces;
1075
1076 mstring_split (&s, &t, maxlen, &indent);
1077
1078 fprintf (stream, "%s\n", s);
1079
1080 if (t != NULL)
1081 {
1082 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1083 int i;
1084
1085 for (i = 0; i < nspaces; i++)
1086 {
1087 spaces[i] = ' ';
1088 }
1089
1090 spaces[nspaces] = '\0';
1091
1092 while (t != NULL)
1093 {
1094 char *st = t;
1095 mstring_split (&st, &t, nextlen, &indent);
1096 fprintf (stream, "%s%s\n", spaces, st);
1097 }
1098
1099 sfree (spaces);
1100 }
1101 }
1102 }
1103
1104 sfree (os);
1105}
1106
1107void
1108llfatalbug (/*@only@*/ cstring s)
1109{
1110 prepareMessage ();
1111 printError (stderr, message ("%q: *** Fatal bug: %q",
1112 fileloc_unparse (g_currentloc), s));
1113 printCodePoint ();
1114 printBugReport ();
1115 llexit (LLFAILURE);
1116}
1117
1118# ifndef NOLCL
1119void
1120lclfatalbug (char *msg)
1121{
1122 prepareMessage ();
1123 printError (stderr,
1124 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1125 printCodePoint ();
1126 printBugReport ();
1127 llexit (LLFAILURE);
1128}
1129# endif
1130
1131void
1132checkParseError (void)
1133{
1134 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1135 {
1136 llfatalerror (message ("%q: Cannot recover from parse error.",
1137 fileloc_unparse (g_currentloc)));
1138 }
1139}
1140
1141void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1142{
1143 /*@unchecked@*/
1144 static int numbugs = 0;
1145 static bool inbug = FALSE;
1146
1147 if (inbug)
1148 {
1149 cstring temps = fileloc_unparseRaw (file, line);
1150
1151 fprintf (stderr, "%s: Recursive bug detected: %s\n",
1152 cstring_toCharsSafe (temps),
1153 cstring_toCharsSafe (s));
1154 cstring_free (temps);
1155
1156 llexit (LLFAILURE);
1157 }
1158
1159 inbug = TRUE;
1160
1161 prepareMessage ();
1162
1163 if (fileloc_isRealLib (g_currentloc))
1164 {
1165 llfatalerror (message ("%q: Library file appears to be corrupted. Error: %q:%s",
1166 fileloc_unparse (g_currentloc),
1167 fileloc_unparseRaw (file, line), s));
1168 }
1169
1170 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1171 {
1172 llfatalerror (message ("%q: Cannot recover from parse error.",
1173 fileloc_unparse (g_currentloc)));
1174 }
1175
1176 (void) fflush (g_msgstream);
1177 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1178 fileloc_unparse (g_currentloc),
1179 fileloc_unparseRaw (file, line),
1180 s, errno));
1181 printCodePoint ();
1182
1183 (void) fflush (stderr);
1184 perror ("Possible system error diagnostic: ");
1185 (void) fflush (stderr);
1186
1187 printBugReport ();
1188
1189 numbugs++;
1190
1191 if (numbugs > 5 && fileloc_withinLines (lastbug, g_currentloc, 2))
1192 {
1193 llfatalerror (message ("%q: Cannot recover from last bug.",
1194 fileloc_unparse (g_currentloc)));
1195 }
1196
1197 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
1198 fileloc_free (lastbug);
1199 lastbug = fileloc_copy (g_currentloc);
1200 closeMessage ();
1201
1202 (void) fflush (stderr);
1203 inbug = FALSE;
90bc41f7 1204 assert(FALSE); /*drl take this out*/
616915dd 1205}
1206
1207# ifndef NOLCL
1208void
1209lclbug (/*@only@*/ cstring s)
1210{
1211 prepareMessage ();
1212 printError (stderr, message ("*** Internal Bug: %q", s));
1213 printCodePoint ();
1214 printBugReport ();
1215 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
1216 closeMessage ();
1217}
1218# endif
1219
1220void
1221llfatalerror (cstring s)
1222{
1223 prepareMessage ();
1224 printError (stderr, s);
1225 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1226 llexit (LLFAILURE);
1227}
1228
1229void
1230llfatalerrorLoc (/*@only@*/ cstring s)
1231{
1232 prepareMessage ();
1233 (void) fflush (g_msgstream);
1234 printError (stderr, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1235 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1236 llexit (LLFAILURE);
1237}
1238
1239/*
1240** free's s!
1241*/
1242
1243void
1244llgloberror (/*@only@*/ cstring s)
1245{
1246 if (context_inSuppressRegion ())
1247 {
1248 cstring_free (s);
1249 }
1250 else
1251 {
1252 context_setNeednl ();
1253 prepareMessage ();
1254 context_hasError ();
1255 flagcode_recordError (FLG_SPECIAL);
1256 printError (g_msgstream, s);
1257 closeMessage ();
1258 }
1259}
1260
1261# ifndef NOLCL
1262bool
1263lclHadError (void)
1264{
1265 return (lclerrors > 0);
1266}
1267
1268bool
1269lclHadNewError (void)
1270{
1271 static int lastcall = 0;
1272
1273 if (lclerrors > lastcall)
1274 {
1275 lastcall = lclerrors;
1276 return TRUE;
1277 }
1278 else
1279 {
1280 return FALSE;
1281 }
1282}
1283
1284int
1285lclNumberErrors (void)
1286{
1287 return (lclerrors);
1288}
1289
1290void
1291lclerror (ltoken t, /*@only@*/ cstring msg)
1292{
1293 lclerrors++;
1294
1295 if (ltoken_getCode (t) != NOTTOKEN)
1296 {
1297 cstring loc = ltoken_unparseLoc (t);
1298
1299 lastfileloclen = cstring_length (loc);
1300
1301 printError (g_msgstream, message ("%q: %q", loc, msg));
1302 }
1303 else
1304 {
1305 printError (g_msgstream, msg);
1306 }
1307}
1308
1309void
1310lclplainerror (/*@only@*/ cstring msg)
1311{
1312 lclerrors++;
1313
1314 printError (g_msgstream, msg);
1315}
1316
1317void
1318lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1319{
1320 lclerror (t, msg);
1321 (void) fflush (g_msgstream);
1322 printError (stderr, cstring_makeLiteral ("*** Cannot continue"));
1323 llexit (LLFAILURE);
1324}
1325
1326void
1327lclplainfatalerror (/*@only@*/ cstring msg)
1328{
1329 (void) fflush (g_msgstream);
1330 printError (stderr, message ("*** Cannot continue: %q", msg));
1331 llexit (LLFAILURE);
1332}
1333
1334void
1335lclRedeclarationError (ltoken id)
1336{
1337 cstring s = ltoken_getRawString (id);
1338
1339
1340 if (usymtab_existsEither (s))
1341 {
1342 uentry le = usymtab_lookupEither (s);
1343
1344 lclerror (id, message ("Respecification of %s", s));
1345 llgenindentmsg (message ("Previous specification of %q",
1346 uentry_getName (le)),
1347 uentry_whereSpecified (le));
1348 }
1349 else
1350 {
1351 lclerror (id, message ("Identifier redeclared: %s", s));
1352 }
1353}
1354# endif
1355
1356void genppllerror (flagcode code, /*@only@*/ cstring s)
1357{
1358 if (context_inSuppressZone (g_currentloc))
1359 {
1360 cstring_free (s);
1361 }
1362 else
1363 {
1364 if (context_getFlag (code))
1365 {
1366 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
1367 {
1368 fprintf (g_msgstream, " >\n");
1369 }
1370
1371 llerror (code, s);
1372
1373 if (code != FLG_PREPROC)
1374 {
1375 llsuppresshint ('-', code);
1376 }
1377
1378 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
1379 {
1380 fprintf (stderr, "< more preprocessing .");
1381 }
1382 }
1383 else
1384 {
1385 cstring_free (s);
1386 }
1387 }
1388}
1389
1390void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1391 /*@only@*/ cstring hint)
1392{
1393 if (context_inSuppressZone (g_currentloc))
1394 {
1395 cstring_free (s);
1396 cstring_free (hint);
1397 }
1398 else
1399 {
1400 if (context_getFlag (code))
1401 {
1402 prepareMessage ();
1403 context_clearPreprocessing ();
1404 llerror (code, s);
1405 llgenhint (hint);
1406 context_setPreprocessing ();
1407 closeMessage ();
1408 }
1409 else
1410 {
1411 cstring_free (s);
1412 cstring_free (hint);
1413 }
1414 }
1415}
1416
1417void ppllerror (/*@only@*/ cstring s)
1418{
1419 genppllerror (FLG_PREPROC, s);
1420}
1421
1422void pplldiagmsg (cstring s)
1423{
1424 if (context_getDebug (FLG_SHOWSCAN) && !context_isInCommandLine ())
1425 {
1426 fprintf (stderr, " >\n");
1427 lldiagmsg (s);
1428 fprintf (stderr, "< more preprocessing .");
1429 }
1430 else
1431 {
1432 lldiagmsg (s);
1433 }
1434}
1435
1436void loadllmsg (cstring s)
1437{
1438 if (context_getDebug (FLG_SHOWSCAN))
1439 {
1440 fprintf (stderr, " >\n");
1441 lldiagmsg (s);
1442 fprintf (stderr, "< .");
1443 }
1444 else
1445 {
1446 lldiagmsg (s);
1447 }
1448}
1449
1450static void llreportparseerror (/*@only@*/ cstring s)
1451{
1452 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1453 {
1454 cstring_free (s);
1455 }
1456 else
1457 {
1458 llerror (FLG_SYNTAX, s);
1459
1460 fileloc_free (lastparseerror);
1461 lastparseerror = fileloc_copy (g_currentloc);
1462 }
1463}
1464
1465bool lloptgenerror (flagcode o, /*@only@*/ cstring s, fileloc loc)
1466{
1467 if (llrealerror (s, loc))
1468 {
1469 llsuppresshint ('-', o);
1470 closeMessage ();
1471 flagcode_recordError (o);
1472 return TRUE;
1473 }
1474
1475 flagcode_recordSuppressed (o);
1476 return FALSE;
1477}
1478
1479bool optgenerror2 (flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1480{
1481 if (context_suppressFlagMsg (f1, loc))
1482 {
1483 flagcode_recordSuppressed (f1);
1484 cstring_free (s);
1485 }
1486 else
1487 {
1488 if (context_suppressFlagMsg (f2, loc))
1489 {
1490 flagcode_recordSuppressed (f2);
1491 cstring_free (s);
1492 }
1493 else
1494 {
1495 if (llrealerror (s, loc))
1496 {
1497 llsuppresshint ('-', f2);
1498 flagcode_recordError (f2);
1499 closeMessage ();
1500 return TRUE;
1501 }
1502
1503 flagcode_recordSuppressed (f2);
1504 }
1505 }
1506 return FALSE;
1507}
1508
1509bool optgenerror2n (flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1510{
1511
1512 if (context_suppressFlagMsg (f1, loc))
1513 {
1514 flagcode_recordSuppressed (f1);
1515 cstring_free (s);
1516 }
1517 else
1518 {
1519 if (context_suppressNotFlagMsg (f2, loc))
1520 {
1521 flagcode_recordSuppressed (f2);
1522 cstring_free (s);
1523 }
1524 else
1525 {
1526 if (llrealerror (s, loc))
1527 {
1528 llsuppresshint ('+', f2);
1529 flagcode_recordError (f2);
1530 closeMessage ();
1531 return TRUE;
1532 }
1533
1534 flagcode_recordSuppressed (f2);
1535 }
1536 }
1537 return FALSE;
1538}
1539
1540bool llnoptgenerror (flagcode o, /*@only@*/ cstring s, fileloc loc)
1541{
1542 if (llrealerror (s, loc))
1543 {
1544 llsuppresshint ('+', o);
1545 flagcode_recordError (o);
1546 closeMessage ();
1547 return TRUE;
1548 }
1549
1550 flagcode_recordSuppressed (o);
1551 return FALSE;
1552}
1553
1554void llparseerror (cstring s)
1555{
1556 if (context_getFlag (FLG_TRYTORECOVER))
1557 {
1558 parseerrorcount++;
1559
1560 if (parseerrorcount > GIVEUPPARSE)
1561 {
1562 if (cstring_isDefined (s))
1563 {
1564 llfatalerror (message ("%q: Parse Error: %q. "
1565 "Too many errors, giving up.",
1566 fileloc_unparse (g_currentloc), s));
1567 }
1568 else
1569 {
1570 llfatalerror (message ("%q: Parse Error. Too many errors, giving up.",
1571 fileloc_unparse (g_currentloc)));
1572 }
1573 }
1574 else
1575 {
1576 if (cstring_isDefined (s))
1577 {
1578 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1579 s));
1580 }
1581 else
1582 {
1583 llreportparseerror (message ("Parse Error. Attempting to continue."));
1584 }
1585 }
1586 }
1587 else
1588 {
1589 cstring msg;
1590
1591 if (cstring_isDefined (s))
1592 {
1593 msg = message ("Parse Error: %q.", s);
1594 }
1595 else
1596 {
1597 msg = message ("Parse Error.");
1598 }
1599
1600 llfatalerror
1601 (message ("%q: %s (For help on parse errors, "
1602 "see lclint -help parseerrors.)",
1603 fileloc_unparse (g_currentloc), msg));
1604 }
1605}
1606
1607bool doCheck (bool x, cstring pred, cstring file, int line)
1608{
1609 if (!x) {
1610 llbug (message ("%q: Check Failed: %s",
1611 fileloc_unparseRaw (file, line),
1612 pred));
1613 }
1614
1615 return x;
1616}
1617
1618/*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1619{
1620 char *result;
1621
1622#ifndef VMS
1623#ifndef HAVE_STRERROR
1624 result = NULL;
1625#else
1626 result = strerror (errnum);
1627#endif
1628#else /* VMS */
1629 /* VAXCRTL's strerror() takes an optional second argument, which only
1630 matters when the first argument is EVMSERR. However, it's simplest
1631 just to pass it unconditionally. `vaxc$errno' is declared in
1632 <errno.h>, and maintained by the library in parallel with `errno'.
1633 We assume that caller's `errnum' either matches the last setting of
1634 `errno' by the library or else does not have the value `EVMSERR'. */
1635
1636 result = strerror (errnum, vaxc$errno);
1637#endif
1638
1639 if (result == NULL)
1640 {
1641 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1642 }
1643
1644 return cstring_fromChars (result);
1645}
1646
1647void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1648{
1649# if 0
1650# ifdef HOMEVERSION
1651 llflush ();
1652 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1653 fileloc_unparse (g_currentloc),
1654 fileloc_unparseRaw (file, line),
1655 s, errno));
1656 printCodePoint ();
1657 llflush ();
1658# endif
1659# else
1660 cstring_free (s);
1661# endif
1662}
1663
1664void llflush (void)
1665{
1666 (void) fflush (g_msgstream);
1667 (void) fflush (stderr);
1668}
This page took 0.271283 seconds and 5 git commands to generate.