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