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