]> andersk Git - splint.git/blob - src/llerror.c
Finshed basic merge. Still trying to get it through the test suit.
[splint.git] / src / llerror.c
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
37 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
38    /*@modifies *p_stream@*/ ;
39
40 # ifndef NOLCL
41 static int lclerrors = 0;
42 # endif
43
44 static int lastfileloclen = 10;
45 static /*@only@*/ cstring lastmsg = cstring_undefined;
46 static int mcount = 0;
47 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
48 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
49 static /*@only@*/ fileloc lastbug = fileloc_undefined;
50 static bool llgenerrorreal (/*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
51                  /*@modifies g_msgstream@*/ ;
52 static bool llgenerroraux (/*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
53                  /*@modifies g_msgstream@*/ ;
54 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
55    /*@globals lastfileloclen @*/
56    /*@modifies *p_stream@*/ ;
57 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
58    /*@modifies *p_stream@*/ ;
59
60 static /*@null@*/ char *
61 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
62 {
63   if (a > b) return a;
64   else return b;
65 }
66
67 static void
68 printBugReport (void)
69 {
70   fprintf (stderr, "     *** Please report bug to %s ***\n",
71            LCLINT_MAINTAINER);
72   llflush ();
73   /* don't exit (EXIT_FAILURE); */
74 }
75
76 static bool s_needsPrepare = TRUE;
77
78 void 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
92 void 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
109 void
110 llmsg (/*@only@*/ cstring s)
111 {
112   context_setNeednl ();
113   prepareMessage ();
114   printMessage (g_msgstream, s);
115   closeMessage ();
116 }
117
118 void
119 lldiagmsg (/*@only@*/ cstring s)
120 {
121   context_setNeednl ();
122   prepareMessage ();
123   printMessage (stderr, s);
124   closeMessage ();
125 }
126
127 void
128 llmsgplain (/*@only@*/ cstring s)
129 {
130   context_setNeednl ();
131   prepareMessage ();
132   printMessage (g_msgstream, s);
133   closeMessage ();
134 }
135
136 void 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
153 static void
154 llgenhint (/*@only@*/ cstring s) /*@modifies g_msgstream@*/
155 {
156   context_setNeednl ();
157   printIndentMessage (g_msgstream, s, 2);
158 }
159
160 void
161 llhint (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
174 static void
175 llshowhint (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
192 static void
193 llsuppresshint (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
223 static void
224 llnosuppresshint (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
246 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
247
248 static void
249 mstring_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
375 static
376 void 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
392 static int parseerrorcount = 0;
393
394 void 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
433 void
434 llgenmsg (/*@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
444 void
445 llgenindentmsg (/*@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
454 void
455 llgenindentmsgnoloc (/*@only@*/ cstring s)
456 {
457   prepareMessage ();
458   (void) printIndentMessage (g_msgstream, s, 3);
459   closeMessage ();
460 }
461
462 static 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
685 bool
686 llgentypeerror (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
692 bool
693 llgenformattypeerror (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
699 bool
700 llgenerror (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
716 bool
717 llgenhinterror (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
751 static bool
752 llrealerror (/*@only@*/ cstring s, fileloc fl)
753 {
754   return (llgenerrorreal (s, fl, TRUE, FALSE));
755 }
756
757 static bool
758 llgenerroraux (/*@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
774 void
775 llforceerror (flagcode code, /*@only@*/ cstring s, fileloc fl)
776 {
777   flagcode_recordError (code);
778   (void) llgenerrorreal (s, fl, TRUE, FALSE);
779   closeMessage ();
780 }
781
782 static bool
783 llgenerrorreal (/*@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
956 static
957 void printMessage (FILE *stream, /*@only@*/ cstring s)
958 {
959   printIndentMessage (stream, s, 0);
960 }
961
962 static
963 void 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
983 static
984 void 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
1106 void
1107 llfatalbug (/*@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
1118 void
1119 lclfatalbug (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
1130 void
1131 checkParseError (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
1140 void 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
1206 void
1207 lclbug (/*@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
1218 void
1219 llfatalerror (cstring s)
1220 {
1221   prepareMessage ();
1222   printError (stderr, s);
1223   printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1224   llexit (LLFAILURE);
1225 }
1226
1227 void
1228 llfatalerrorLoc (/*@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
1241 void
1242 llgloberror (/*@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
1260 bool
1261 lclHadError (void)
1262 {
1263   return (lclerrors > 0);
1264 }
1265
1266 bool
1267 lclHadNewError (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
1282 int
1283 lclNumberErrors (void)
1284 {
1285   return (lclerrors);
1286 }
1287
1288 void
1289 lclerror (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
1307 void
1308 lclplainerror (/*@only@*/ cstring msg)
1309 {
1310   lclerrors++;
1311
1312   printError (g_msgstream, msg);
1313 }
1314
1315 void
1316 lclfatalerror (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
1324 void
1325 lclplainfatalerror (/*@only@*/ cstring msg)
1326 {
1327   (void) fflush (g_msgstream);
1328   printError (stderr, message ("*** Cannot continue: %q", msg));
1329   llexit (LLFAILURE);
1330 }
1331
1332 void
1333 lclRedeclarationError (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
1354 void 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
1388 void 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
1415 void ppllerror (/*@only@*/ cstring s)
1416 {
1417   genppllerror (FLG_PREPROC, s);
1418 }
1419
1420 void 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
1434 void 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
1448 static 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
1463 bool 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
1477 bool 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
1507 bool 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
1538 bool 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
1552 void 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
1605 bool 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
1645 void 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
1662 void llflush (void)
1663 {
1664   (void) fflush (g_msgstream);
1665   (void) fflush (stderr);
1666 }
This page took 0.161299 seconds and 5 git commands to generate.