]> andersk Git - splint.git/blob - src/llerror.c
Merged with Dave Evans's changes.
[splint.git] / src / llerror.c
1 #include <assert.h> /*drl take this out*/
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
38 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
39    /*@modifies *p_stream@*/ ;
40
41 # ifndef NOLCL
42 static int lclerrors = 0;
43 # endif
44
45 static int lastfileloclen = 10;
46 static /*@only@*/ cstring lastmsg = cstring_undefined;
47 static int mcount = 0;
48 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
49 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
50 static /*@only@*/ fileloc lastbug = fileloc_undefined;
51 static bool llgenerrorreal (/*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
52                  /*@modifies g_msgstream@*/ ;
53 static bool llgenerroraux (/*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
54                  /*@modifies g_msgstream@*/ ;
55 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
56    /*@globals lastfileloclen @*/
57    /*@modifies *p_stream@*/ ;
58 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
59    /*@modifies *p_stream@*/ ;
60
61 static /*@null@*/ char *
62 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
63 {
64   if (a > b) return a;
65   else return b;
66 }
67
68 static void
69 printBugReport (void)
70 {
71   fprintf (stderr, "     *** Please report bug to %s ***\n",
72            LCLINT_MAINTAINER);
73   llflush ();
74   /* don't exit (EXIT_FAILURE); */
75 }
76
77 static bool s_needsPrepare = TRUE;
78
79 void 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
93 void 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
110 void
111 llmsg (/*@only@*/ cstring s)
112 {
113   context_setNeednl ();
114   prepareMessage ();
115   printMessage (g_msgstream, s);
116   closeMessage ();
117 }
118
119 void
120 lldiagmsg (/*@only@*/ cstring s)
121 {
122   context_setNeednl ();
123   prepareMessage ();
124   printMessage (stderr, s);
125   closeMessage ();
126 }
127
128 void
129 llmsgplain (/*@only@*/ cstring s)
130 {
131   context_setNeednl ();
132   prepareMessage ();
133   printMessage (g_msgstream, s);
134   closeMessage ();
135 }
136
137 void 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
154 static void
155 llgenhint (/*@only@*/ cstring s) /*@modifies g_msgstream@*/
156 {
157   context_setNeednl ();
158   printIndentMessage (g_msgstream, s, 2);
159 }
160
161 void
162 llhint (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
175 static void
176 llshowhint (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
193 static void
194 llsuppresshint (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
224 static void
225 llnosuppresshint (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
247 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
248
249 static void
250 mstring_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
376 static
377 void 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
393 static int parseerrorcount = 0;
394
395 void 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
434 void
435 llgenmsg (/*@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
445 void
446 llgenindentmsg (/*@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
455 void
456 llgenindentmsgnoloc (/*@only@*/ cstring s)
457 {
458   prepareMessage ();
459   (void) printIndentMessage (g_msgstream, s, 3);
460   closeMessage ();
461 }
462
463 static 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
686 bool
687 llgentypeerror (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
693 bool
694 llgenformattypeerror (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
700 bool
701 llgenerror (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
717 bool
718 llgenhinterror (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
752 static bool
753 llrealerror (/*@only@*/ cstring s, fileloc fl)
754 {
755   return (llgenerrorreal (s, fl, TRUE, FALSE));
756 }
757
758 static bool
759 llgenerroraux (/*@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
775 void
776 llforceerror (flagcode code, /*@only@*/ cstring s, fileloc fl)
777 {
778   flagcode_recordError (code);
779   (void) llgenerrorreal (s, fl, TRUE, FALSE);
780   closeMessage ();
781 }
782
783 static bool
784 llgenerrorreal (/*@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
957 static
958 void printMessage (FILE *stream, /*@only@*/ cstring s)
959 {
960   printIndentMessage (stream, s, 0);
961 }
962
963 static
964 void 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
984 static
985 void 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
1107 void
1108 llfatalbug (/*@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
1119 void
1120 lclfatalbug (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
1131 void
1132 checkParseError (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
1141 void 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;
1204   assert(FALSE); /*drl take this out*/
1205 }
1206
1207 # ifndef NOLCL
1208 void
1209 lclbug (/*@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
1220 void
1221 llfatalerror (cstring s)
1222 {
1223   prepareMessage ();
1224   printError (stderr, s);
1225   printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
1226   llexit (LLFAILURE);
1227 }
1228
1229 void
1230 llfatalerrorLoc (/*@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
1243 void
1244 llgloberror (/*@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
1262 bool
1263 lclHadError (void)
1264 {
1265   return (lclerrors > 0);
1266 }
1267
1268 bool
1269 lclHadNewError (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
1284 int
1285 lclNumberErrors (void)
1286 {
1287   return (lclerrors);
1288 }
1289
1290 void
1291 lclerror (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
1309 void
1310 lclplainerror (/*@only@*/ cstring msg)
1311 {
1312   lclerrors++;
1313
1314   printError (g_msgstream, msg);
1315 }
1316
1317 void
1318 lclfatalerror (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
1326 void
1327 lclplainfatalerror (/*@only@*/ cstring msg)
1328 {
1329   (void) fflush (g_msgstream);
1330   printError (stderr, message ("*** Cannot continue: %q", msg));
1331   llexit (LLFAILURE);
1332 }
1333
1334 void
1335 lclRedeclarationError (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
1356 void 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
1390 void 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
1417 void ppllerror (/*@only@*/ cstring s)
1418 {
1419   genppllerror (FLG_PREPROC, s);
1420 }
1421
1422 void 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
1436 void 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
1450 static 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
1465 bool 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
1479 bool 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
1509 bool 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
1540 bool 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
1554 void 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
1607 bool 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
1647 void 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
1664 void llflush (void)
1665 {
1666   (void) fflush (g_msgstream);
1667   (void) fflush (stderr);
1668 }
This page took 0.216506 seconds and 5 git commands to generate.