]> andersk Git - splint.git/blob - src/llerror.c
Committed my changes (but there are several splintme errors currently).
[splint.git] / src / llerror.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** llerror.c
26 **
27 ** error reporting procedures
28 */
29
30 # include "splintMacros.nf"
31 # include <string.h>
32 # include <errno.h>
33 # include "llbasic.h"
34 # include "llmain.h"
35 # include "cpperror.h"
36 # include "Headers/version.h" /* Visual C++ finds a different version.h on some path! */
37
38 /* Don't allow possibly-recursive assertion failures. */
39 # undef llassert
40 # define llassert llassertprotect
41
42 static void printIndentMessage (FILE *p_stream, /*@only@*/ cstring p_sc, int p_indent)
43    /*@modifies *p_stream@*/ ;
44
45 static int lclerrors = 0;
46 static size_t lastfileloclen = 10;
47 static /*@only@*/ cstring lastmsg = cstring_undefined;
48 static int mcount = 0;
49 static /*@only@*/ cstring saveOneMessage = cstring_undefined;
50 static /*@only@*/ fileloc lastparseerror = fileloc_undefined;
51 static /*@only@*/ fileloc lastbug = fileloc_undefined;
52 static bool llgenerrorreal (char *p_srcFile, int p_srcLine, 
53                             /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
54                  /*@modifies g_warningstream@*/ ;
55 static bool llgenerroraux (char *p_srcFile, int p_srcLine, 
56                            /*@only@*/ cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
57                  /*@modifies g_warningstream@*/ ;
58
59 static void printError (FILE *p_stream, /*@only@*/ cstring p_sc)
60    /*@globals lastfileloclen @*/
61    /*@modifies *p_stream@*/ ;
62 static void printMessage (FILE *p_stream, /*@only@*/ cstring p_s)
63    /*@modifies *p_stream@*/ ;
64
65 static void llgenhint (/*@only@*/ cstring p_s) /*@modifies g_warningstream@*/ ;
66
67 static void showSourceLoc (char *srcFile, int srcLine)
68      /*@modifies g_warningstream@*/
69 {
70   if (context_getFlag (FLG_SHOWSOURCELOC)) {
71     llgenhint (message ("%s:%d: Source code error generation point.",
72                         cstring_fromChars (srcFile), srcLine));
73   }
74   
75 }
76
77 static /*@null@*/ char *
78 maxcp (/*@null@*/ /*@returned@*/ char *a, /*@null@*/ /*@returned@*/ char *b)
79 {
80   if (a > b) return a;
81   else return b;
82 }
83
84 static void
85 printBugReport (void)
86 {
87   fprintf (g_errorstream, "     *** Please report bug to %s ***\n",
88            SPLINT_MAINTAINER);
89   llflush ();
90   /* don't exit (EXIT_FAILURE); */
91 }
92
93 static bool s_needsPrepare = TRUE;
94
95 void prepareMessage ()
96 {
97   DPRINTF (("Prepare message: %s", bool_unparse (context_loadingLibrary ())));
98   showHerald ();
99
100   if ((context_isPreprocessing () || context_loadingLibrary ())
101       && s_needsPrepare
102       && context_getFlag (FLG_SHOWSCAN))
103     {
104       llflush ();
105       displayScanClose ();
106       s_needsPrepare = FALSE;
107     }
108
109   llflush ();
110 }
111
112 void closeMessage (void)
113 {
114   if (context_isPreprocessing ()
115       && context_getFlag (FLG_SHOWSCAN))
116     {
117       llflush ();
118       displayScanOpen (cstring_makeLiteral ("more preprocessing ."));
119       llassertprotect (!s_needsPrepare);
120       s_needsPrepare = TRUE;
121     }
122   else
123     {
124       llflush ();
125     }
126 }
127
128 void
129 llmsg (/*@only@*/ cstring s)
130 {
131   context_setNeednl ();
132   prepareMessage ();
133   printMessage (g_messagestream, s);
134   closeMessage ();
135 }
136
137 void
138 lldiagmsg (/*@only@*/ cstring s)
139 {
140   static bool inmsg = FALSE;
141
142   if (inmsg)
143     {
144       fprintf (g_errorstream,
145                "Recursive message call detected: %s\n", 
146                cstring_toCharsSafe (s));
147       llexit (LLFAILURE);
148     }
149
150   inmsg = TRUE;
151
152   context_setNeednl ();
153   prepareMessage ();
154   printMessage (g_messagestream, s);
155   closeMessage ();
156
157   inmsg = FALSE;
158 }
159
160 void
161 llmsgplain (/*@only@*/ cstring s)
162 {
163   context_setNeednl ();
164   prepareMessage ();
165   printMessage (g_messagestream, s);
166   closeMessage ();
167 }
168
169 void llerror_flagWarning (cstring s)
170 {
171   if (context_getFlag (FLG_WARNFLAGS))
172     {
173       llgenmsg (s, g_currentloc);
174     }
175   else
176     {
177       cstring_free (s);
178     }
179 }
180
181 static void
182 llgenhint (/*@only@*/ cstring s) /*@modifies g_warningstream@*/
183 {
184   int indent = context_getIndentSpaces () - 1;
185
186   if (indent < 0) indent = 0;
187
188   context_setNeednl ();
189   printIndentMessage (g_warningstream, s, indent);
190 }
191
192 void
193 llhint (cstring s)
194 {
195   if (context_getFlag (FLG_HINTS) &&
196       !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
197     {
198       llgenhint (s);
199     }
200   else
201     {
202       cstring_free (s);
203     }
204 }
205
206 static void
207 llshowhint (flagcode f)
208 {
209   if (context_getFlag (FLG_HINTS))
210     {
211       if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
212         {
213           cstring desc = flagcodeHint (f);
214
215           if (cstring_isDefined (desc))
216             {
217               llgenhint (cstring_copy (desc));
218             }
219         }
220     }
221 }
222
223 static void
224 llsuppresshint2 (char c, flagcode f1, flagcode f2)
225 {
226
227   if (context_getFlag (FLG_HINTS))
228     {
229       if ((flagcode_numReported (f1) == 0
230            || flagcode_numReported (f2) == 0)
231           || context_getFlag (FLG_FORCEHINTS))
232         {
233           cstring desc = flagcodeHint (f1);
234           context_setNeednl ();
235           lastfileloclen = 8;
236
237           if (cstring_isUndefined (desc))
238             {
239               desc = flagcodeHint (f2);
240             }
241
242           if (flagcode_isNamePrefixFlag (f1))
243             {
244               f1 = FLG_NAMECHECKS;
245             }
246
247           if (flagcode_isNamePrefixFlag (f2))
248             {
249               f2 = FLG_NAMECHECKS;
250             }
251
252           if (f1 == f2)
253             {
254               if (cstring_isDefined (desc))
255                 {
256                   llgenhint (message ("%s (Use %h%s to inhibit warning)", desc,
257                                       c,
258                                       flagcode_unparse (f1)));
259                 }
260               else
261                 {
262                   llgenhint (message ("(Use %h%s to inhibit warning)", 
263                                       c, flagcode_unparse (f1)));
264                 }
265             }
266           else
267             {
268               if (cstring_isDefined (desc))
269                 {
270                   llgenhint (message ("%s (Use either %h%s or %h%s to inhibit warning)", desc, 
271                                       c,
272                                       flagcode_unparse (f1),
273                                       c,
274                                       flagcode_unparse (f2)));
275                 }
276               else
277                 {
278                   llgenhint (message ("(Use either %h%s or %h%s to inhibit warning)", c,
279                                       flagcode_unparse (f1),
280                                       c, flagcode_unparse (f2)));
281                 }
282             }
283         }
284     }
285 }
286
287 static void
288 llsuppresshint (char c, flagcode f)
289 {
290   if (context_getFlag (FLG_HINTS))
291     {
292       if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
293         {
294           cstring desc = flagcodeHint (f);
295           context_setNeednl ();
296           lastfileloclen = 8;
297
298           if (flagcode_isNamePrefixFlag (f))
299             {
300               f = FLG_NAMECHECKS;
301             }
302
303           if (cstring_isDefined (desc))
304             {
305               llgenhint (message ("%s (Use %h%s to inhibit warning)", desc, c,
306                                   flagcode_unparse (f)));
307             }
308           else
309             {
310               llgenhint (message ("(Use %h%s to inhibit warning)", c,
311                                   flagcode_unparse (f)));
312             }
313         }
314     }
315 }
316
317 static void
318 llnosuppresshint (flagcode f)
319 {
320   if (context_getFlag (FLG_FORCEHINTS))
321     {
322       cstring desc = flagcodeHint (f);
323       context_setNeednl ();
324       lastfileloclen = 8;
325
326       if (cstring_isDefined (desc))
327         {
328           printError (g_warningstream, message ("    %s", desc));
329         }
330     }
331 }
332
333 /*@constant int MAXSEARCH; @*/
334 # define MAXSEARCH 20
335
336 /*@constant int MINLINE; @*/
337 # define MINLINE 35
338
339 typedef /*@null@*/ /*@dependent@*/ char *nd_charp;
340
341 static void
342 mstring_split (/*@returned@*/ char **sp,
343                /*@out@*/ nd_charp *tp,
344                int maxline, /*@in@*/ int *indentchars)
345 {
346   char *nl;
347   char *t;
348   char *s = *sp;
349   char *osp = *sp;
350
351   *tp = NULL;
352
353   DPRINTF (("Split: %s / %d", *sp, maxline));
354
355   if (maxline < MINLINELEN)
356     {
357       maxline = MINLINELEN;
358     }
359
360   if (*indentchars > 0)
361     {
362       s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
363       osp = s;
364     }
365
366   nl = strchr (s, '\n');
367
368   /*
369   ** splitting:
370   **
371   **    if there is a newline in first maxline characters, split there
372   **    if line len is <= maxline, return no split
373   **    if there is a ':' or ';' or ',' followed by ' ' in first maxline characters,
374   **       split there unless the ' ' is followed by a '}', then
375   **       split after '}'
376   **       of the ';' is inside quotation marks
377   **    if there is a space or tab in last maxsearch characters, split there
378   **    else, split at maxline
379   **
380   **    special code: slash [1-9] after a newline means indent the rest <n> chars
381   **
382   */
383
384   if ((nl != NULL) && ((nl - s) < maxline))
385     {
386       *nl = '\0';
387       t = nl + 1;
388
389       if (*t == '\0')
390         {
391           llassertprotect (*tp == NULL || (*tp > osp));
392           return;
393         }
394
395       if (*t >= '\1' && *t <= '\7')
396         {
397           *indentchars += (int) (*t - '\1') + 1;
398           t++;
399         }
400       
401       *tp = t;
402       return;
403     }
404   else if (size_toInt (strlen (s)) < maxline)
405     {
406       llassertprotect (*tp == NULL || (*tp > osp));
407       return;
408     }
409   else
410     {
411       int i = 0;
412       char savechar;
413       char *lcolon, *lsemi, *lcomma;
414       char *splitat;
415       
416       splitat = NULL;
417
418       t = s + maxline - 1;
419       savechar = *t;
420
421       *t = '\0';
422       lcolon = strrchr (s, ':');
423       lsemi = strrchr (s, ';');
424       lcomma = strrchr (s, ',');
425
426       *t = savechar;
427
428       splitat = maxcp (lcolon, lsemi);
429
430       if (splitat != NULL && ((int)(splitat - s) > MINLINE)
431           && *(splitat) != '\0'
432           && *(splitat + 1) == ' ' 
433           && (*(splitat + 2) != '}'
434               && *(splitat + 2) != ',' 
435               && (*(splitat + 2) != '\0'))) 
436         {
437           *(splitat + 1) = '\0';
438           t = splitat + 2;
439           *tp = t;
440           llassertprotect (*tp == NULL || (*tp > osp));
441           return;
442         }
443
444       if (lcomma != NULL && ((lcomma - s) > maxline - 5))
445         {
446           splitat = lcomma;
447           
448           if (splitat != NULL && ((int)(splitat - s) > MINLINE)
449               && *(splitat) != '\0'
450               && *(splitat + 1) == ' ' 
451               && (*(splitat + 2) != '}'
452                   && (*(splitat + 2) != '\0'))) 
453             {
454               *(splitat + 1) = '\0';
455               t = splitat + 2;
456               *tp = t;
457               llassertprotect (*tp == NULL || (*tp > osp));
458               return;
459             }
460         }
461       
462       while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
463         {
464           t--;
465           i++;
466         }
467
468       if (*t != ' ' && *t != '\t')
469         {
470           llassertprotect (maxline > 0);
471           t = mstring_copy (s + maxline);
472           *(s + maxline) = '\0';
473
474           if (*t == '\0')
475             {
476               sfree (t);
477               llassertprotect (*tp == NULL || (*tp > osp));
478               return;
479             }
480
481           mstring_markFree (t);
482           *tp = t;
483           /* Won't be true since t is a copy: llassertprotect (*tp == NULL || (*tp > osp)); */
484           return;
485         }
486       else
487         {
488
489           *t = '\0';
490           t++;
491           
492           if (*t == '\0') return;
493
494           /*
495           ** returns unqualified as only
496           */
497
498           *tp = t;
499
500 # if 0
501           /* Hack to prevent error case for wierd strings. */
502           if (t <= osp)
503             {
504               *tp = NULL;
505               return;
506             }
507           llassertprotect (*tp == NULL || (*tp > osp));
508 # endif   
509
510           return;
511         }
512     }
513
514   BADBRANCH;
515 }
516
517 static
518 void limitmessage (/*@only@*/ cstring s, fileloc loc)
519 {
520   if (mcount > context_getLimit () + 1)
521     {
522       cstring_free (s);
523     }
524   else
525     {
526       cstring flstring = fileloc_unparse (loc);
527
528       lastfileloclen = cstring_length (flstring);
529       cstring_free (saveOneMessage);
530       saveOneMessage = message ("%q: %q", flstring, s);
531     }
532 }
533
534 static int parseerrorcount = 0;
535
536 void cleanupMessages ()
537 {
538   parseerrorcount = 0;
539
540   if (context_unlimitedMessages ())
541     {
542      ;
543     }
544   else
545     {
546       int unprinted = mcount - context_getLimit ();
547
548       if (unprinted > 0)
549         {
550           if (unprinted == 1 && cstring_isDefined (saveOneMessage))
551             {
552               prepareMessage ();
553               printError (g_warningstream, saveOneMessage);
554               closeMessage ();
555               saveOneMessage = cstring_undefined;
556             }
557           else
558             {
559               if (cstring_isDefined (saveOneMessage))
560                 {
561                   /* cstring_free (saveOneMessage); */
562                   saveOneMessage = cstring_undefined;
563                 }
564
565               fprintf (g_warningstream, "%s: (%d more similar errors unprinted)\n",
566                        cstring_toCharsSafe (fileloc_filename (g_currentloc)),
567                        mcount - context_getLimit ());
568             }
569         }
570     }
571
572   mcount = 0;
573 }
574
575 void
576 llgenmsg (/*@only@*/ cstring s, fileloc fl)
577 {
578   cstring flstring = fileloc_unparse (fl);
579   lastfileloclen = cstring_length (flstring);
580
581   prepareMessage ();
582   (void) printError (g_warningstream, message ("%q: %q", flstring, s));
583   closeMessage ();
584 }
585
586 void
587 llgenindentmsg (/*@only@*/ cstring s, fileloc fl)
588 {
589   cstring flstring = fileloc_unparse (fl);
590
591   prepareMessage ();
592   (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s), context_getIndentSpaces ());
593   closeMessage ();
594 }
595
596 void
597 llgenindentmsgnoloc (/*@only@*/ cstring s)
598 {
599   prepareMessage ();
600   (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
601   closeMessage ();
602 }
603
604 static bool
605 llgentypeerroraux (char *srcFile, int srcLine,
606                    flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
607                    /*@only@*/ cstring s, fileloc fl)
608 {
609   cstring hint = cstring_undefined;
610   flagcode code = ocode;
611   flagcode hcode = INVALID_FLAG;
612   ctype ut1 = t1;
613   ctype ut2 = t2;
614
615   DPRINTF (("Type error [%s]: %s / %s : %s / %s",
616             flagcode_unparse (ocode),
617             exprNode_unparse (e1), exprNode_unparse (e2),
618             ctype_unparse (t1), ctype_unparse (t2)));
619   
620   DPRINTF (("Bool: %s / %s",
621             bool_unparse (ctype_isBool (t1)),
622             bool_unparse (ctype_isBool (t2))));
623
624   /* 
625   ** Set the flag using the underlying types that didn't match.
626   */
627
628   while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
629     ut1 = ctype_baseArrayPtr (ut1);
630     ut2 = ctype_baseArrayPtr (ut2);
631   }
632
633   if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
634       || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
635     {
636       hcode = FLG_FLOATDOUBLE;
637     }
638   else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
639            || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
640     {
641       hcode = FLG_CHARINTLITERAL;
642     }
643   else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
644            || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
645     {
646       hcode = FLG_NUMLITERAL;
647     }
648   else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
649            || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
650     /* evs 2000-07-24: was ctype_isDirectBool */
651     {
652       hcode = FLG_BOOLINT;
653     }
654   else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
655            || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
656     {
657       hcode = FLG_CHARINT;
658     }
659   else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
660            || (ctype_isChar (ut1) && ctype_isChar (ut2))
661            || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
662     {
663       if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
664         {
665           if (ctype_isArbitraryIntegral (ctype_realType (ut1))
666               && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
667             {
668               hcode = FLG_MATCHANYINTEGRAL;
669             }
670           else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
671                    && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
672             {
673               hcode = FLG_MATCHANYINTEGRAL;
674             }
675           else
676             {
677               hcode = FLG_IGNORESIGNS;
678             }
679         }
680       else
681         {
682           hcode = FLG_IGNOREQUALS;
683         }
684     }
685   else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
686     {
687       if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
688         {
689           hcode = FLG_MATCHANYINTEGRAL;
690         }
691       else if (ctype_match (ut2, ctype_ulint))
692         {
693           hcode = FLG_LONGUNSIGNEDINTEGRAL;
694         }
695       else if (ctype_match (ut2, ctype_lint))
696         {
697           hcode = FLG_LONGINTEGRAL;
698         }
699       else if (ctype_isInt (ut2))
700         {
701           hcode = FLG_MATCHANYINTEGRAL;
702         }
703       else
704         {
705           ;
706         }
707     }
708   else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
709     {
710       ctype tr = ctype_realType (ut1);
711
712       if (ctype_isArbitraryIntegral (tr))
713         {
714           hcode = FLG_MATCHANYINTEGRAL;
715         }
716       else if (ctype_match (ut1, ctype_ulint))
717         {
718           if (ctype_isUnsignedIntegral (tr))
719             {
720               hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
721             }
722           else if (ctype_isSignedIntegral (tr))
723             {
724               ;
725             }
726           else
727             {
728               hcode = FLG_LONGUNSIGNEDINTEGRAL;
729             }
730         }
731       else if (ctype_match (ut1, ctype_lint))
732         {
733           if (ctype_isSignedIntegral (tr))
734             {
735               hcode = FLG_LONGSIGNEDINTEGRAL;
736             }
737           else if (ctype_isSignedIntegral (tr))
738             {
739               ;
740             }
741           else
742             {
743               hcode = FLG_LONGINTEGRAL;
744             }
745         }
746       else if (ctype_isInt (ut1))
747         {
748           hcode = FLG_MATCHANYINTEGRAL;
749         }
750       else
751         {
752           ;
753         }
754     }
755   else
756     {
757       ;
758     }
759
760   if (hcode == INVALID_FLAG)
761     {
762       DPRINTF (("[%s] %s - %s / %s",
763                 ctype_unparse (ut1),
764                 bool_unparse (ctype_isEnum (ut1)),
765                 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
766                 bool_unparse (ctype_isInt (ut2))));
767
768       if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
769         {
770           uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
771           ctype ct = uentry_getType (ue1);
772           
773           if (ctype_match (ct, ut2))
774             {
775               code = FLG_ABSTRACT;
776               hint = message ("Underlying types match, but %s is an "
777                               "abstract type that is not accessible here.",
778                               ctype_unparse (t1));
779             }
780         }
781       else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
782         {
783           uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
784           ctype ct = uentry_getType (ue);
785           
786           if (ctype_match (ct, ut1))
787             {
788               code = FLG_ABSTRACT;
789               hint = message ("Underlying types match, but %s is an "
790                               "abstract type that is not accessible here.",
791                               ctype_unparse (t2));
792             }
793         }
794       else
795         {
796           ; /* Not an abstract mismatch. */
797         }
798                                        
799
800       if (hcode == INVALID_FLAG)
801         {
802           if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
803               || (ctype_isEnum (ut2) && ctype_isInt (ut1))) 
804             {
805               hcode = FLG_ENUMINT;
806             }
807           else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
808                    || (ctype_isEnum (ut2) && ctype_isInt (ut1))) 
809             {
810               hcode = FLG_ENUMINT;
811             }
812           else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
813                    || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
814             {
815               hcode = FLG_CHARUNSIGNEDCHAR;
816             }
817           else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2)) 
818             {
819               hcode = FLG_RELAXTYPES;
820               DPRINTF (("Setting relax types!"));
821             }
822           else
823             {
824               DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
825                         ctype_unparse (ut2)));
826             }
827         }
828     }
829
830   if (cstring_isDefined (hint))
831     {
832       if (!context_suppressFlagMsg (ocode, fl))
833         {
834           return llgenhinterror (code, s, hint, fl);
835         }
836       else
837         {
838           cstring_free (s);
839           cstring_free (hint);
840           return FALSE;
841         }
842     }
843   else
844     {
845       if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
846         {
847           if (hcode != INVALID_FLAG && hcode != ocode)
848             {
849               code = hcode;
850
851               if (context_flagOn (code, fl))
852                 {
853                   /* The flag is alreay set, something buggy in the flag code */
854                   llcontbug (message ("No hint available, flag %s is already set.",
855                                       flagcode_unparse (code)));
856                 }
857               else
858                 {
859                   llshowhint (code);
860                 }
861             }
862           else
863             {
864               llsuppresshint ('-', code);
865             }
866
867           flagcode_recordError (code);
868           return TRUE;
869         }
870
871       return FALSE;
872     }
873 }
874
875 bool
876 xllgentypeerror (char *srcFile, int srcLine,
877                  ctype t1, exprNode e1, ctype t2, exprNode e2,
878                  /*@only@*/ cstring s, fileloc fl)
879 {
880   return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
881 }
882
883 bool
884 xllgenformattypeerror (char *srcFile, int srcLine,
885                        ctype t1, exprNode e1, ctype t2, exprNode e2,
886                        /*@only@*/ cstring s, fileloc fl)
887 {
888   if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
889     {
890       return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
891     }
892   else
893     {
894       cstring_free (s);
895       return FALSE;
896     }
897 }
898
899 bool
900 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
901 {
902   if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
903     {
904       llnosuppresshint (o);
905       flagcode_recordError (o);
906       closeMessage ();
907       return TRUE;
908     }
909   else
910     {
911       flagcode_recordSuppressed (o);
912       return FALSE;
913     }
914 }
915
916 bool
917 xllgenhinterror (char *srcFile, int srcLine,
918                  flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
919                  fileloc fl)
920 {
921   if (!context_suppressFlagMsg (o, fl))
922     {
923       if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
924         {
925           flagcode_recordError (o);
926
927           if (context_getFlag (FLG_HINTS))
928             {
929               llgenhint (hint);
930             }
931           else
932             {
933               cstring_free (hint);
934             }
935
936           closeMessage ();
937           return TRUE;
938         }
939
940       cstring_free (hint);
941     }
942   else
943     {
944       cstring_free (hint);
945       cstring_free (s);
946     }
947
948   flagcode_recordSuppressed (o);
949   return FALSE;
950 }
951
952 static bool
953 llrealerror (char *srcFile, int srcLine, /*@only@*/ cstring s, fileloc fl)
954 {
955   return (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE));
956 }
957
958 static bool
959 llgenerroraux (char *srcFile, int srcLine,
960                /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
961 {
962   if (context_inSuppressZone (fl))
963     {
964       cstring_free (s);
965       return FALSE;
966     }
967   
968   if (llgenerrorreal (srcFile, srcLine, s, fl, iserror, indent)) {
969     return TRUE;
970   } else {
971     return FALSE;
972   }
973 }
974
975 bool
976 xllforceerror (char *srcFile, int srcLine, 
977                flagcode code, /*@only@*/ cstring s, fileloc fl)
978 {
979   flagcode_recordError (code);
980
981   if (llgenerrorreal (srcFile, srcLine, s, fl, TRUE, FALSE)) {
982     closeMessage ();
983     return TRUE;
984   } else {
985     return FALSE;
986   }
987 }
988
989 static bool
990 llgenerrorreal (char *srcFile, int srcLine, 
991                 /*@only@*/ cstring s, fileloc fl, bool iserror, bool indent)
992 {
993   cstring flstring;
994
995   /* duplicate message (rescanning a header file */
996
997   if (!messageLog_add (context_messageLog (), fl, s))
998     {
999       DPRINTF (("Duplicate message suppressed! %s / %s",
1000                 fileloc_unparse (fl), s));
1001       cstring_free (s);
1002       return FALSE;
1003     }
1004
1005   /*
1006   ** If herald has not been displayed, display it before the first message.
1007   */
1008
1009   showHerald ();
1010
1011   if (iserror) context_hasError ();
1012
1013   if (context_unlimitedMessages ())
1014     {
1015       ;
1016     }
1017   else
1018     {
1019       /*
1020       ** suppress excessive messages:
1021       **    check up to ':'
1022       **
1023       */
1024
1025       char *sc = cstring_toCharsSafe (s);
1026       char *tmpmsg = strchr (sc, ':');
1027
1028       if (tmpmsg == NULL)
1029         {
1030           tmpmsg = sc;
1031         }
1032       else
1033         {
1034           char *savechar = tmpmsg;
1035           *tmpmsg = '\0';
1036           tmpmsg = sc;
1037           *savechar = ':';
1038         }
1039
1040       if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1041         {
1042           mcount++;
1043           if (mcount == (context_getLimit () + 1))
1044             {
1045               limitmessage (s, fl);
1046               return FALSE;
1047             }
1048
1049           if (mcount > (context_getLimit ()))
1050             {
1051               cstring_free (s);
1052               return FALSE;
1053             }
1054         }
1055       else
1056         {
1057           cleanupMessages ();
1058           mcount = 0;
1059           cstring_free (lastmsg);
1060           lastmsg = cstring_fromCharsNew (tmpmsg);
1061         }
1062     }
1063
1064   DPRINTF (("Here..."));
1065
1066   if (context_hasAliasAnnote ())
1067     {
1068       char *sc = cstring_toCharsSafe (s);
1069       char *fcolon = strchr (sc, ':');
1070       cstring a = context_getAliasAnnote ();
1071
1072
1073       if (fcolon == NULL)
1074         {
1075           s = message ("%q (%q)", s, a);
1076         }
1077       else
1078         {
1079           cstring afterColon;
1080
1081           *fcolon = '\0';
1082           afterColon = cstring_fromCharsNew (fcolon + 1);
1083
1084           s = message ("%q (%q):%q", s, a, afterColon);
1085         }
1086           }
1087
1088   if (context_hasMessageAnnote ())
1089     {
1090       char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1091
1092
1093       if (fcolon == NULL)
1094         {
1095           /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1096           s = message ("%q (%q)", s, context_getMessageAnnote ());
1097           /*@=dependenttrans@*/
1098         }
1099       else
1100         {
1101           cstring afterColon;
1102
1103           *fcolon = '\0';
1104           afterColon = cstring_fromCharsNew (fcolon + 1);
1105
1106           /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1107           s = message ("%q (%q):%q", s,
1108                        context_getMessageAnnote (), afterColon);
1109           /*@=dependenttrans@*/
1110         }
1111      }
1112
1113   context_setNeednl ();
1114   prepareMessage ();
1115
1116   if (context_showFunction ())
1117     {
1118       cstring fname = fileloc_unparseFilename (g_currentloc);
1119
1120       if (context_inIterDef ())
1121         {
1122           fprintf (g_warningstream, "%s: (in iter %s)\n",
1123                    cstring_toCharsSafe (fname),
1124                    cstring_toCharsSafe (context_inFunctionName ()));
1125         }
1126       else if (context_inIterEnd ())
1127         {
1128           fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1129                    cstring_toCharsSafe (fname),
1130                    cstring_toCharsSafe (context_inFunctionName ()));
1131         }
1132       else if (context_inMacro ())
1133         {
1134           fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1135                    cstring_toCharsSafe (context_inFunctionName ()));
1136         }
1137       else
1138         {
1139           fprintf (g_warningstream, "%s: (in function %s)\n",
1140                    cstring_toCharsSafe (fname),
1141                    cstring_toCharsSafe (context_inFunctionName ()));
1142         }
1143
1144       cstring_free (fname);
1145       context_setShownFunction ();
1146     }
1147
1148   flstring = fileloc_unparse (fl);
1149   lastfileloclen = cstring_length (flstring);
1150
1151   if (indent)
1152     {
1153       printError (g_warningstream, message ("   %q: %q", flstring, s));
1154     }
1155   else
1156     {
1157       printError (g_warningstream, message ("%q: %q", flstring, s));
1158     }
1159
1160   showSourceLoc (srcFile, srcLine);
1161   return TRUE;
1162 }
1163
1164 /*
1165 ** printMessage
1166 **
1167 ** message contains no '\n'
1168 **    message fits in one line: print it
1169 **    message fits in two lines with 3-space indent after fileloc: print it
1170 **    split line with 5-space indent from left margin: print it
1171 **
1172 */
1173
1174 static
1175 void printMessage (FILE *stream, /*@only@*/ cstring s)
1176 {
1177   printIndentMessage (stream, s, 0);
1178 }
1179
1180 static
1181 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1182 {
1183   static bool inbody = FALSE;
1184   int maxlen = context_getLineLen ();
1185   char *s = cstring_toCharsSafe (sc);
1186   char *olds = NULL;
1187
1188   llassertprotect (!inbody);
1189   inbody = TRUE;
1190
1191   do
1192     {
1193       char *t = NULL;
1194       char *st = s;
1195
1196       llassertprotect (st != olds);
1197       olds = st;
1198       mstring_split (&st, &t, maxlen, &indent);
1199       fprintf (stream, "%s\n", st);
1200       llassertprotect (t != s);
1201       s = t;
1202     } while (s != NULL) ;
1203
1204   cstring_free (sc);
1205   inbody = FALSE;
1206 }
1207
1208 static
1209 void printError (FILE *stream, /*@only@*/ cstring sc)
1210 {
1211   int maxlen = context_getLineLen ();
1212   size_t nspaces = lastfileloclen + 5;
1213   int nextlen = maxlen - nspaces;
1214   size_t len = cstring_length (sc);
1215   int indent = 0;
1216   char *s = cstring_toCharsSafe (sc);
1217   char *os = s;
1218   char *t = NULL;
1219
1220   DPRINTF (("Print error: [%s]", sc));
1221
1222   if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1223     {
1224       mstring_split (&s, &t, maxlen, &indent);
1225
1226       fprintf (stream, "%s\n", s);
1227
1228       if (t != NULL)
1229         {
1230           len = mstring_length (t);
1231
1232           if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1233               && size_toInt (len) > (nextlen - 1))
1234             {
1235               fprintf (stream, "    %s\n", t);
1236             }
1237           else
1238             {
1239               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1240               int i;
1241
1242               for (i = 0; i < size_toInt (nspaces); i++)
1243                 {
1244                   spaces[i] = ' ';
1245                 }
1246
1247               spaces[nspaces] = '\0';
1248
1249               while (t != NULL)
1250                 {
1251                   char *st = t;
1252                   mstring_split (&st, &t, nextlen, &indent);
1253                   fprintf (stream, "%s%s\n", spaces, st);
1254                 }
1255
1256               sfree (spaces);
1257             }
1258         }
1259     }
1260   else
1261     {
1262       DPRINTF (("Here 1: [%s]", sc));
1263
1264       if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1265         {
1266           nspaces = ((maxlen + maxlen - 1) - len) / 2;
1267
1268           if (nspaces < 1) nspaces = 1;
1269
1270           nextlen = maxlen - nspaces;
1271
1272           mstring_split (&s, &t, maxlen, &indent);
1273
1274           fprintf (stream, "%s\n", s);
1275
1276           if (t != NULL)
1277             {
1278               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1279               int i;
1280
1281               for (i = 0; i < size_toInt (nspaces); i++)
1282                 {
1283                   spaces[i] = ' ';
1284                 }
1285
1286               spaces[nspaces] = '\0';
1287
1288               while (t != NULL)
1289                 {
1290                   char *st = t;
1291
1292                   mstring_split (&st, &t, nextlen, &indent);
1293                   fprintf (stream, "%s%s\n", spaces, st);
1294                 }
1295
1296               sfree (spaces);
1297             }
1298         }
1299       else
1300         {
1301           nspaces = 4;
1302           nextlen = maxlen - nspaces;
1303
1304           DPRINTF (("Here 2: [%s]", s));
1305           mstring_split (&s, &t, maxlen, &indent);
1306           DPRINTF (("Here 3: [%s] [%s]", s, t));
1307
1308           fprintf (stream, "%s\n", s);
1309
1310           if (t != NULL)
1311             {
1312               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1313               size_t i;
1314
1315               for (i = 0; i < nspaces; i++)
1316                 {
1317                   spaces[i] = ' ';
1318                 }
1319
1320               spaces[nspaces] = '\0';
1321
1322               while (t != NULL)
1323                 {
1324                   char *st = t;
1325                   DPRINTF (("Loop: [%s]", t));
1326                   mstring_split (&st, &t, nextlen, &indent);
1327                   DPRINTF (("Split: [%s] [%s]", st, t));
1328                   fprintf (stream, "%s%s\n", spaces, st);
1329                   DPRINTF (("Next..."));
1330                 }
1331
1332               sfree (spaces);
1333             }
1334         }
1335     }
1336
1337   DPRINTF (("Done"));
1338   sfree (os);
1339 }
1340
1341 void
1342 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1343 {
1344   prepareMessage ();
1345   printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1346                                       fileloc_unparse (g_currentloc), s));
1347   showSourceLoc (srcFile, srcLine);
1348   printCodePoint ();
1349   printBugReport ();
1350   llexit (LLFAILURE);
1351 }
1352
1353 void
1354 lclfatalbug (char *msg)
1355 {
1356   prepareMessage ();
1357   printError (g_errorstream,
1358               message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1359   printCodePoint ();
1360   printBugReport ();
1361   llexit (LLFAILURE);
1362 }
1363
1364 void
1365 checkParseError (void)
1366 {
1367   if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1368     {
1369       llfatalerror (message ("%q: Cannot recover from parse error.",
1370                              fileloc_unparse (g_currentloc)));
1371     }
1372 }
1373
1374 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1375 {
1376   /*@unchecked@*/
1377   static int numbugs = 0;
1378   static bool inbug = FALSE;
1379
1380   if (inbug)
1381     {
1382       cstring temps = fileloc_unparseRaw (file, line);
1383
1384       fprintf (g_errorstream,
1385                "%s: Recursive bug detected: %s\n",
1386                cstring_toCharsSafe (temps),
1387                cstring_toCharsSafe (s));
1388       cstring_free (temps);
1389
1390       llexit (LLFAILURE);
1391     }
1392
1393   inbug = TRUE;
1394
1395   prepareMessage ();
1396
1397   if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1398     {
1399       llfatalerror (message ("%q: Cannot recover from parse error.",
1400                              fileloc_unparse (g_currentloc)));
1401     }
1402
1403   (void) fflush (g_warningstream);
1404
1405   printError (g_errorstream,
1406               message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1407                        fileloc_unparse (g_currentloc),
1408                        fileloc_unparseRaw (file, line),
1409                        s, errno));
1410   
1411   /* printCodePoint (); no longer useful */
1412
1413   llflush ();
1414   
1415   /*
1416   ** This is confusing, and hardly ever useful.
1417
1418   if (errno != 0)
1419     {
1420       perror ("Possible system error diagnostic: ");
1421     }
1422
1423   **
1424   */
1425
1426   printBugReport ();
1427   llflush ();
1428
1429   numbugs++;
1430
1431   if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1432     {
1433       llfatalerror
1434         (message ("%q: Cannot recover from last bug. "
1435                   "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1436                   fileloc_unparse (g_currentloc)));
1437     }
1438   
1439   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1440   fileloc_free (lastbug);
1441   lastbug = fileloc_copy (g_currentloc);
1442   closeMessage ();
1443   inbug = FALSE;
1444 }
1445
1446 void
1447 lclbug (/*@only@*/ cstring s)
1448 {
1449   prepareMessage ();
1450   printError (g_errorstream, message ("*** Internal Bug: %q", s));
1451   printCodePoint ();
1452   printBugReport ();
1453   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1454   closeMessage ();
1455 }
1456
1457 void
1458 xllfatalerror (char *srcFile, int srcLine, cstring s)
1459 {
1460   prepareMessage ();
1461   printError (g_errorstream, s);
1462   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1463   showSourceLoc (srcFile, srcLine);
1464   llexit (LLFAILURE);
1465 }
1466
1467 void
1468 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1469 {
1470   prepareMessage ();
1471   (void) fflush (g_warningstream);
1472   printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1473   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1474   showSourceLoc (srcFile, srcLine);
1475   (void) fflush (g_warningstream);
1476   llexit (LLFAILURE);
1477 }
1478
1479 bool
1480 lclHadError (void)
1481 {
1482   return (lclerrors > 0);
1483 }
1484
1485 bool
1486 lclHadNewError (void)
1487 {
1488   static int lastcall = 0;
1489
1490   if (lclerrors > lastcall)
1491     {
1492       lastcall = lclerrors;
1493       return TRUE;
1494     }
1495   else
1496     {
1497       return FALSE;
1498     }
1499 }
1500
1501 int
1502 lclNumberErrors (void)
1503 {
1504   return (lclerrors);
1505 }
1506
1507 void
1508 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1509 {
1510   lclerrors++;
1511
1512   if (ltoken_getCode (t) != NOTTOKEN)
1513     {
1514       cstring loc = ltoken_unparseLoc (t);
1515       lastfileloclen = cstring_length (loc);
1516
1517       printError (g_warningstream, message ("%q: %q", loc, msg));
1518       showSourceLoc (srcFile, srcLine);
1519     }
1520   else
1521     {
1522       printError (g_warningstream, msg);
1523       showSourceLoc (srcFile, srcLine);
1524     }
1525 }
1526
1527 void
1528 lclplainerror (/*@only@*/ cstring msg)
1529 {
1530   lclerrors++;
1531   printError (g_warningstream, msg);
1532 }
1533
1534 void
1535 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1536 {
1537   if (ltoken_getCode (t) != NOTTOKEN)
1538     {
1539       cstring loc = ltoken_unparseLoc (t);
1540       lastfileloclen = cstring_length (loc);
1541       printError (g_errorstream, message ("%q: %q", loc, msg));
1542     }
1543   else
1544     {
1545       printError (g_errorstream, msg);
1546     }
1547
1548   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1549   llexit (LLFAILURE);
1550 }
1551
1552 void
1553 lclplainfatalerror (/*@only@*/ cstring msg)
1554 {
1555   (void) fflush (g_warningstream);
1556   printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1557   llexit (LLFAILURE);
1558 }
1559
1560 void
1561 lclRedeclarationError (ltoken id)
1562 {
1563   cstring s = ltoken_getRawString (id);
1564
1565
1566   if (usymtab_existsEither (s))
1567     {
1568       uentry le = usymtab_lookupEither (s);
1569
1570       lclerror (id, message ("Respecification of %s", s));
1571       llgenindentmsg (message ("Previous specification of %q",
1572                                uentry_getName (le)),
1573                 uentry_whereSpecified (le));
1574     }
1575   else
1576     {
1577       lclerror (id, message ("Identifier redeclared: %s", s));
1578     }
1579 }
1580
1581 void genppllerror (flagcode code, /*@only@*/ cstring s)
1582 {
1583   if (context_inSuppressZone (g_currentloc))
1584     {
1585       cstring_free (s);
1586     }
1587   else
1588     {
1589       if (context_getFlag (code))
1590         {
1591           if (!context_isInCommandLine ())
1592             {
1593               displayScanClose ();
1594             }
1595
1596           llerror (code, s);
1597
1598           if (code != FLG_PREPROC)
1599             {
1600               llsuppresshint ('-', code);
1601             }
1602
1603           if (!context_isInCommandLine ())
1604             {
1605               displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1606             }
1607         }
1608       else
1609         {
1610           cstring_free (s);
1611         }
1612     }
1613 }
1614
1615 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1616                        /*@only@*/ cstring hint)
1617 {
1618   if (context_inSuppressZone (g_currentloc))
1619     {
1620       cstring_free (s);
1621       cstring_free (hint);
1622     }
1623   else
1624     {
1625       if (context_getFlag (code))
1626         {
1627           prepareMessage ();
1628           context_clearPreprocessing ();
1629           llerror (code, s);
1630           llgenhint (hint);
1631           context_setPreprocessing ();
1632           closeMessage ();
1633         }
1634       else
1635         {
1636           cstring_free (s);
1637           cstring_free (hint);
1638         }
1639     }
1640 }
1641
1642 void ppllerror (/*@only@*/ cstring s)
1643 {
1644   genppllerror (FLG_PREPROC, s);
1645 }
1646
1647 void pplldiagmsg (cstring s)
1648 {
1649   if (!context_isInCommandLine ())
1650     {
1651       displayScanClose ();
1652       lldiagmsg (s);
1653       displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1654     }
1655   else
1656     {
1657       lldiagmsg (s);
1658     }
1659 }
1660
1661 void loadllmsg (cstring s)
1662 {
1663   displayScanClose ();
1664   lldiagmsg (s);
1665   displayScanOpen (cstring_makeLiteral ("< ."));
1666 }
1667
1668 static void llreportparseerror (/*@only@*/ cstring s)
1669 {
1670   if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1671     {
1672       cstring_free (s);
1673     }
1674   else
1675     {
1676       llerror (FLG_SYNTAX, s);
1677
1678       fileloc_free (lastparseerror);
1679       lastparseerror = fileloc_copy (g_currentloc);
1680     }
1681 }
1682
1683 bool xcppoptgenerror (char *srcFile, int srcLine,
1684                       flagcode o,
1685                       /*@only@*/ cstring s,
1686                       cppReader *pfile)
1687 {
1688   bool res = FALSE;
1689   fileloc loc = cppReader_getLoc (pfile);
1690
1691   if (context_flagOn (o, loc))
1692     {
1693       if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1694         {
1695           cppReader_printContainingFiles (pfile);
1696           res = TRUE;
1697         }
1698     }
1699   else
1700     {
1701       cstring_free (s);
1702     }
1703
1704   fileloc_free (loc);
1705
1706   return res;
1707 }
1708
1709 bool xlloptgenerror (char *srcFile, int srcLine, 
1710                      flagcode o, /*@only@*/ cstring s, fileloc loc)
1711 {
1712   DPRINTF (("xllopt: %s", s));
1713
1714   if (llrealerror (srcFile, srcLine, s, loc))
1715     {
1716       DPRINTF (("Here we are!"));
1717       llsuppresshint ('-', o);
1718       closeMessage ();
1719       flagcode_recordError (o);
1720       return TRUE;
1721     }
1722   else
1723     {
1724       DPRINTF (("Suppressed!"));
1725       flagcode_recordSuppressed (o);
1726       return FALSE;
1727     }
1728 }
1729
1730 bool xoptgenerror2 (char *srcFile, int srcLine,
1731                     flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1732 {
1733   if (context_suppressFlagMsg (f1, loc))
1734     {
1735       flagcode_recordSuppressed (f1);
1736       cstring_free (s);
1737     }
1738   else
1739     {
1740       if (context_suppressFlagMsg (f2, loc))
1741         {
1742           flagcode_recordSuppressed (f2);
1743           cstring_free (s);
1744         }
1745       else
1746         {
1747           if (llrealerror (srcFile, srcLine, s, loc))
1748             {
1749               llsuppresshint2 ('-', f1, f2);
1750               flagcode_recordError (f2);
1751               closeMessage ();
1752               return TRUE;
1753             }
1754           else
1755             {
1756               flagcode_recordSuppressed (f2);
1757             }
1758         }
1759     }
1760
1761   return FALSE;
1762 }
1763
1764 bool xoptgenerror2n (char *srcFile, int srcLine,
1765                      flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1766 {
1767
1768   if (context_suppressFlagMsg (f1, loc))
1769     {
1770       flagcode_recordSuppressed (f1);
1771       cstring_free (s);
1772     }
1773   else
1774     {
1775       if (context_suppressNotFlagMsg (f2, loc))
1776         {
1777           flagcode_recordSuppressed (f2);
1778           cstring_free (s);
1779         }
1780       else
1781         {
1782           if (llrealerror (srcFile, srcLine, s, loc))
1783             {
1784               llsuppresshint ('+', f2);
1785               flagcode_recordError (f2);
1786               closeMessage ();
1787               return TRUE;
1788             }
1789
1790           flagcode_recordSuppressed (f2);
1791         }
1792     }
1793   return FALSE;
1794 }
1795
1796 bool xllnoptgenerror (char *srcFile, int srcLine,
1797                       flagcode o, /*@only@*/ cstring s, fileloc loc)
1798 {
1799   if (llrealerror (srcFile, srcLine, s, loc))
1800     {
1801       llsuppresshint ('+', o);
1802       flagcode_recordError (o);
1803       closeMessage ();
1804       return TRUE;
1805     }
1806
1807   flagcode_recordSuppressed (o);
1808   return FALSE;
1809 }
1810
1811 void xllparseerror (char *srcFile, int srcLine, cstring s)
1812 {
1813   if (context_getFlag (FLG_TRYTORECOVER))
1814     {
1815       parseerrorcount++;
1816
1817       if (parseerrorcount > GIVEUPPARSE)
1818         {
1819           if (cstring_isDefined (s))
1820             {
1821               xllfatalerror (srcFile, srcLine,
1822                              message ("%q: Parse Error: %q.  "
1823                                       "Too many errors, giving up.",
1824                                       fileloc_unparse (g_currentloc), s));
1825             }
1826           else
1827             {
1828               xllfatalerror (srcFile, srcLine,
1829                              message ("%q: Parse Error.  Too many errors, giving up.",
1830                                       fileloc_unparse (g_currentloc)));
1831             }
1832         }
1833       else
1834         {
1835           if (cstring_isDefined (s))
1836             {
1837               llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1838                                            s));
1839               showSourceLoc (srcFile, srcLine);
1840             }
1841           else
1842             {
1843               llreportparseerror (message ("Parse Error. Attempting to continue."));
1844               showSourceLoc (srcFile, srcLine);
1845             }
1846         }
1847     }
1848   else
1849     {
1850       cstring msg;
1851
1852       if (cstring_isDefined (s))
1853         {
1854           msg = message ("Parse Error: %q.", s);
1855         }
1856       else
1857         {
1858           msg = message ("Parse Error.");
1859         }
1860
1861       xllfatalerror
1862         (srcFile, srcLine,
1863          message ("%q: %s (For help on parse errors, "
1864                   "see splint -help parseerrors.)",
1865                   fileloc_unparse (g_currentloc), msg));
1866     }
1867 }
1868
1869 bool xfsgenerror (char *srcFile, int srcLine,
1870                    flagSpec fs, /*@only@*/ cstring s, fileloc fl) 
1871 {
1872   if (flagSpec_isOn (fs, fl))
1873     {
1874       if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1875         {
1876           llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1877           flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1878           return TRUE;
1879         }
1880       else
1881         {
1882           flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1883           return FALSE;
1884         }
1885     }
1886   else
1887     {
1888       flagcode_recordSuppressed (flagSpec_getDominant (fs));
1889       cstring_free (s);
1890       return FALSE;
1891     }
1892 }
1893
1894 bool doCheck (bool x, cstring pred, cstring file, int line)
1895 {
1896   if (!x) {
1897     llbug (message ("%q: Check Failed: %s",
1898                     fileloc_unparseRaw (file, line),
1899                     pred));
1900   }
1901
1902   return x;
1903 }
1904
1905 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1906 {
1907   char *result;
1908
1909 #ifndef VMS
1910 #ifndef HAVE_STRERROR
1911   result = NULL;
1912 #else
1913   result = strerror (errnum);
1914 #endif
1915 #else   /* VMS */
1916   /* VAXCRTL's strerror() takes an optional second argument, which only
1917      matters when the first argument is EVMSERR.  However, it's simplest
1918      just to pass it unconditionally.  `vaxc$errno' is declared in
1919      <errno.h>, and maintained by the library in parallel with `errno'.
1920      We assume that caller's `errnum' either matches the last setting of
1921      `errno' by the library or else does not have the value `EVMSERR'.  */
1922
1923   result = strerror (errnum, vaxc$errno);
1924 #endif
1925
1926   if (result == NULL)
1927     {
1928       result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1929     }
1930
1931   return cstring_fromChars (result);
1932 }
1933
1934 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1935 {
1936 # if 0
1937 # ifdef HOMEVERSION
1938   llflush ();
1939   printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1940                                       fileloc_unparse (g_currentloc),
1941                                       fileloc_unparseRaw (file, line),
1942                                       s, errno));
1943   printCodePoint ();
1944   llflush ();
1945 # endif
1946 # else
1947   cstring_free (s);
1948 # endif
1949 }
1950
1951 void llflush (void)
1952 {
1953   (void) fflush (g_warningstream);
1954   (void) fflush (g_messagestream);
1955 }
1956
1957 static bool s_scanOpen = FALSE;
1958
1959 void displayScan (cstring msg)
1960 {
1961   if (s_scanOpen)
1962     {
1963       displayScanClose ();
1964     }
1965
1966   llassert (!s_scanOpen);
1967
1968   if (context_getFlag (FLG_SHOWSCAN))
1969     {
1970       showHerald ();
1971       fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
1972       (void) fflush (g_messagestream);
1973     }
1974
1975   cstring_free (msg);
1976 }
1977
1978 void displayScanOpen (cstring msg)
1979 {
1980   if (s_scanOpen)
1981     {
1982       displayScanClose ();
1983     }
1984
1985   llassert (!s_scanOpen);
1986   s_scanOpen = TRUE;
1987
1988   if (context_getFlag (FLG_SHOWSCAN))
1989     {
1990       fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
1991       (void) fflush (g_messagestream);
1992     }
1993
1994   cstring_free (msg);
1995 }
1996
1997 void displayScanContinue (/*@temp@*/ cstring msg)
1998 {
1999   if (context_getFlag (FLG_SHOWSCAN))
2000     {
2001       if (s_scanOpen) 
2002         {
2003           fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2004           (void) fflush (g_messagestream);
2005         }
2006       else
2007         {
2008           /*
2009           ** Don't call bug recursively
2010           */
2011
2012           fprintf (stderr, "*** Bug: scan continue scan not open\n");
2013         }
2014     }
2015 }
2016
2017 void displayScanClose (void)
2018 {
2019   if (s_scanOpen)
2020     {
2021       if (context_getFlag (FLG_SHOWSCAN))
2022         {
2023           fprintf (g_messagestream, " >\n");
2024           (void) fflush (g_messagestream);
2025         }
2026     }
2027   else
2028     {
2029       /*
2030       ** Don't call bug recursively
2031       */
2032       
2033       fprintf (stderr, "*** Bug: scan close scan not open\n");
2034     }
2035   
2036   s_scanOpen = FALSE;
2037 }
2038
2039
This page took 3.926628 seconds and 5 git commands to generate.