]> andersk Git - splint.git/blob - src/llerror.c
056092084dfe398603c721a2b290e5360345e02c
[splint.git] / src / llerror.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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   int indentspaces = context_getLocIndentSpaces ();
599   prepareMessage ();
600   
601   (void) printIndentMessage (g_warningstream, message ("%q: %q", flstring, s),
602                              indentspaces);
603
604   closeMessage ();
605 }
606
607 void
608 llgenindentmsgnoloc (/*@only@*/ cstring s)
609 {
610   prepareMessage ();
611   (void) printIndentMessage (g_warningstream, s, context_getIndentSpaces ());
612   closeMessage ();
613 }
614
615 static bool
616 llgentypeerroraux (char *srcFile, int srcLine,
617                    flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
618                    /*@only@*/ cstring s, fileloc fl)
619 {
620   cstring hint = cstring_undefined;
621   flagcode code = ocode;
622   flagcode hcode = INVALID_FLAG;
623   ctype ut1 = t1;
624   ctype ut2 = t2;
625
626   DPRINTF (("Type error [%s]: %s / %s : %s / %s",
627             flagcode_unparse (ocode),
628             exprNode_unparse (e1), exprNode_unparse (e2),
629             ctype_unparse (t1), ctype_unparse (t2)));
630   
631   DPRINTF (("Bool: %s / %s",
632             bool_unparse (ctype_isBool (t1)),
633             bool_unparse (ctype_isBool (t2))));
634
635   /* 
636   ** Set the flag using the underlying types that didn't match.
637   */
638
639   while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
640     ut1 = ctype_baseArrayPtr (ut1);
641     ut2 = ctype_baseArrayPtr (ut2);
642   }
643
644   if (ctype_isRealNumAbstract (ut1) && exprNode_isNumLiteral (e2)) 
645     {
646       hcode = FLG_NUMABSTRACTLIT;
647     }
648   else if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
649            || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
650     {
651       hcode = FLG_FLOATDOUBLE;
652     }
653   else if ((exprNode_isCharLiteral (e1) && ctype_isInt (ut2))
654            || (exprNode_isCharLiteral (e2) && ctype_isInt (ut1)))
655     {
656       hcode = FLG_CHARINTLITERAL;
657     }
658   else if ((exprNode_isNumLiteral (e1) && ctype_isReal (ut2))
659            || (exprNode_isNumLiteral (e2) && ctype_isReal (ut1)))
660     {
661       hcode = FLG_NUMLITERAL;
662     }
663   else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
664            || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
665     /* evs 2000-07-24: was ctype_isDirectBool */
666     {
667       hcode = FLG_BOOLINT;
668     }
669   else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
670            || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
671     {
672       hcode = FLG_CHARINT;
673     }
674   else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
675            || (ctype_isChar (ut1) && ctype_isChar (ut2))
676            || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
677     {
678       if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
679         {
680           if (ctype_isArbitraryIntegral (ctype_realType (ut1))
681               && !ctype_isArbitraryIntegral (ctype_realType (ut2)))
682             {
683               hcode = FLG_MATCHANYINTEGRAL;
684             }
685           else if (ctype_isArbitraryIntegral (ctype_realType (ut2))
686                    && !ctype_isArbitraryIntegral (ctype_realType (ut1)))
687             {
688               hcode = FLG_MATCHANYINTEGRAL;
689             }
690           else
691             {
692               hcode = FLG_IGNORESIGNS;
693             }
694         }
695       else
696         {
697           hcode = FLG_IGNOREQUALS;
698         }
699     }
700   else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
701     {
702       if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
703         {
704           hcode = FLG_MATCHANYINTEGRAL;
705         }
706       else if (ctype_match (ut2, ctype_ulint))
707         {
708           hcode = FLG_LONGUNSIGNEDINTEGRAL;
709         }
710       else if (ctype_match (ut2, ctype_lint))
711         {
712           hcode = FLG_LONGINTEGRAL;
713         }
714       else if (ctype_isInt (ut2))
715         {
716           hcode = FLG_MATCHANYINTEGRAL;
717         }
718       else
719         {
720           ;
721         }
722     }
723   else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
724     {
725       ctype tr = ctype_realType (ut1);
726
727       if (ctype_isArbitraryIntegral (tr))
728         {
729           hcode = FLG_MATCHANYINTEGRAL;
730         }
731       else if (ctype_match (ut1, ctype_ulint))
732         {
733           if (ctype_isUnsignedIntegral (tr))
734             {
735               hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
736             }
737           else if (ctype_isSignedIntegral (tr))
738             {
739               ;
740             }
741           else
742             {
743               hcode = FLG_LONGUNSIGNEDINTEGRAL;
744             }
745         }
746       else if (ctype_match (ut1, ctype_lint))
747         {
748           if (ctype_isSignedIntegral (tr))
749             {
750               hcode = FLG_LONGSIGNEDINTEGRAL;
751             }
752           else if (ctype_isSignedIntegral (tr))
753             {
754               ;
755             }
756           else
757             {
758               hcode = FLG_LONGINTEGRAL;
759             }
760         }
761       else if (ctype_isInt (ut1))
762         {
763           hcode = FLG_MATCHANYINTEGRAL;
764         }
765       else
766         {
767           ;
768         }
769     }
770   else
771     {
772       ;
773     }
774
775   if (hcode == INVALID_FLAG)
776     {
777       DPRINTF (("[%s] %s - %s / %s",
778                 ctype_unparse (ut1),
779                 bool_unparse (ctype_isEnum (ut1)),
780                 bool_unparse (ctype_isEnum (ctype_realType (ut1))),
781                 bool_unparse (ctype_isInt (ut2))));
782
783       if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
784         {
785           uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
786           ctype ct = uentry_getType (ue1);
787           
788           if (ctype_match (ct, ut2))
789             {
790               code = FLG_ABSTRACT;
791               hint = message ("Underlying types match, but %s is an "
792                               "abstract type that is not accessible here.",
793                               ctype_unparse (t1));
794             }
795         }
796       else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
797         {
798           uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
799           ctype ct = uentry_getType (ue);
800           
801           if (ctype_match (ct, ut1))
802             {
803               if (ctype_isNumAbstract (ut2)) 
804                 {
805                   if (exprNode_isNumLiteral (e1))
806                     {
807                       code = FLG_NUMABSTRACTLIT;
808                       hint = message ("Underlying types match, but %s is a "
809                                       "numabstract type that is not accessible here. "
810                                       "(Use +numabstractlit to allow numeric literals "
811                                       "to be used as numabstract type values.)",
812                                       ctype_unparse (t2));
813                     }
814                   else
815                     {
816                       code = FLG_NUMABSTRACT;
817                       hint = message ("Underlying types match, but %s is a "
818                                       "numabstract type that is not accessible here.",
819                                       ctype_unparse (t2));
820                     }
821                 }
822               else
823                 {
824                   code = FLG_ABSTRACT;
825                   hint = message ("Underlying types match, but %s is an "
826                                   "abstract type that is not accessible here.",
827                                   ctype_unparse (t2));
828                 }
829             }
830         }
831       else
832         {
833           ; /* Not an abstract mismatch. */
834         }
835                                        
836
837       if (hcode == INVALID_FLAG)
838         {
839           if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
840               || (ctype_isEnum (ut2) && ctype_isInt (ut1))) 
841             {
842               hcode = FLG_ENUMINT;
843             }
844           else if ((ctype_isEnum (ut1) && ctype_isInt (ut2))
845                    || (ctype_isEnum (ut2) && ctype_isInt (ut1))) 
846             {
847               hcode = FLG_ENUMINT;
848             }
849           else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
850                    || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
851             {
852               hcode = FLG_CHARUNSIGNEDCHAR;
853             }
854           else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2)) 
855             {
856               hcode = FLG_RELAXTYPES;
857               DPRINTF (("Setting relax types!"));
858             }
859           else
860             {
861               DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
862                         ctype_unparse (ut2)));
863             }
864         }
865     }
866
867   if (cstring_isDefined (hint))
868     {
869       if (!context_suppressFlagMsg (ocode, fl))
870         {
871           return xllgenhinterror (srcFile, srcLine, code, s, hint, fl);
872         }
873       else
874         {
875           cstring_free (s);
876           cstring_free (hint);
877           return FALSE;
878         }
879     }
880   else
881     {
882       if (hcode != INVALID_FLAG && hcode != ocode)
883         {
884           code = hcode;
885         }
886       
887       if (llgenerroraux (ocode, srcFile, srcLine, s,
888                          flagcodeHint (code), fl, TRUE, FALSE))
889         {
890           if (code != ocode) 
891             {
892               if (context_flagOn (code, fl))
893                 {
894                   /* The flag is alreay set, something buggy in the flag code */
895                   llcontbug (message ("No hint available, flag %s is already set.",
896                                       flagcode_unparse (code)));
897                 }
898               else
899                 {
900                   llshowhint (code);
901                 }
902           } 
903           else
904             {
905               llsuppresshint ('-', code);
906             }
907
908           flagcode_recordError (code);
909           return TRUE;
910         }
911
912       return FALSE;
913     }
914 }
915
916 bool
917 xllgentypeerror (char *srcFile, int srcLine,
918                  ctype t1, exprNode e1, ctype t2, exprNode e2,
919                  /*@only@*/ cstring s, fileloc fl)
920 {
921   return llgentypeerroraux (srcFile, srcLine, FLG_TYPE, t1, e1, t2, e2, s, fl);
922 }
923
924 bool
925 xllgenformattypeerror (char *srcFile, int srcLine,
926                        ctype t1, exprNode e1, ctype t2, exprNode e2,
927                        /*@only@*/ cstring s, fileloc fl)
928 {
929   if (!context_suppressFlagMsg (FLG_FORMATTYPE, fl))
930     {
931       return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
932     }
933   else
934     {
935       cstring_free (s);
936       return FALSE;
937     }
938 }
939
940 bool
941 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
942 {
943   if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
944     {
945       llnosuppresshint (o);
946       flagcode_recordError (o);
947       closeMessage ();
948       return TRUE;
949     }
950   else
951     {
952       flagcode_recordSuppressed (o);
953       return FALSE;
954     }
955 }
956
957 bool
958 xllgenhinterror (char *srcFile, int srcLine,
959                  flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
960                  fileloc fl)
961 {
962   if (!context_suppressFlagMsg (o, fl))
963     {
964       if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
965         {
966           flagcode_recordError (o);
967
968           if (context_getFlag (FLG_HINTS))
969             {
970               llgenhint (hint);
971             }
972           else
973             {
974               cstring_free (hint);
975             }
976
977           closeMessage ();
978           return TRUE;
979         }
980
981       cstring_free (hint);
982     }
983   else
984     {
985       cstring_free (hint);
986       cstring_free (s);
987     }
988
989   flagcode_recordSuppressed (o);
990   return FALSE;
991 }
992
993 static bool
994 llrealerror (flagcode code, char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
995 {
996   return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
997 }
998
999 static bool
1000 llgenerroraux (flagcode code,
1001                char *srcFile, int srcLine,
1002                /*@only@*/ cstring s, 
1003                cstring addtext,
1004                fileloc fl, bool iserror, bool indent)
1005 {
1006   if (context_inSuppressZone (fl))
1007     {
1008       cstring_free (s);
1009       return FALSE;
1010     }
1011   
1012   if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1013     return TRUE;
1014   } else {
1015     return FALSE;
1016   }
1017 }
1018
1019 bool
1020 xllforceerror (char *srcFile, int srcLine, 
1021                flagcode code, /*@only@*/ cstring s, fileloc fl)
1022 {
1023   flagcode_recordError (code);
1024
1025   if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1026     closeMessage ();
1027     return TRUE;
1028   } else {
1029     return FALSE;
1030   }
1031 }
1032
1033 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1034 {
1035
1036   if (g_csvstream != NULL) {
1037     /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1038     fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1039              context_numErrors (),
1040              (int) code, /* flag code */
1041              cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1042              flagcode_priority (code), /* priority */
1043              cstring_toCharsSafe (fileloc_outputFilename (fl)),
1044              fileloc_lineno (fl),
1045              fileloc_column (fl),
1046              cstring_toCharsSafe (s));
1047
1048     if (cstring_isDefined (addtext)) {
1049       fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1050     } else {
1051       fprintf (g_csvstream, "\n");
1052     }
1053   }
1054 }
1055
1056 static bool
1057 llgenerrorreal (flagcode code, char *srcFile, int srcLine, 
1058                 /*@only@*/ cstring s, 
1059                 cstring addtext,
1060                 fileloc fl, bool iserror, bool indent)
1061 {
1062   cstring flstring;
1063
1064   /* duplicate message (rescanning a header file */
1065
1066   if (!messageLog_add (context_messageLog (), fl, s))
1067     {
1068       DPRINTF (("Duplicate message suppressed! %s / %s",
1069                 fileloc_unparse (fl), s));
1070       cstring_free (s);
1071       return FALSE;
1072     }
1073
1074   /*
1075   ** If herald has not been displayed, display it before the first message.
1076   */
1077
1078   showHerald ();
1079
1080   if (iserror) context_hasError ();
1081
1082   if (context_unlimitedMessages ())
1083     {
1084       ;
1085     }
1086   else
1087     {
1088       /*
1089       ** suppress excessive messages:
1090       **    check up to ':'
1091       **
1092       */
1093
1094       char *sc = cstring_toCharsSafe (s);
1095       char *tmpmsg = strchr (sc, ':');
1096
1097       if (tmpmsg == NULL)
1098         {
1099           tmpmsg = sc;
1100         }
1101       else
1102         {
1103           char *savechar = tmpmsg;
1104           *tmpmsg = '\0';
1105           tmpmsg = sc;
1106           *savechar = ':';
1107         }
1108
1109       if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1110         {
1111           mcount++;
1112           if (mcount == (context_getLimit () + 1))
1113             {
1114               limitmessage (s, fl);
1115               return FALSE;
1116             }
1117
1118           if (mcount > (context_getLimit ()))
1119             {
1120               cstring_free (s);
1121               return FALSE;
1122             }
1123         }
1124       else
1125         {
1126           cleanupMessages ();
1127           mcount = 0;
1128           cstring_free (lastmsg);
1129           lastmsg = cstring_fromCharsNew (tmpmsg);
1130         }
1131     }
1132
1133   DPRINTF (("Here..."));
1134
1135   if (context_hasAliasAnnote ())
1136     {
1137       char *sc = cstring_toCharsSafe (s);
1138       char *fcolon = strchr (sc, ':');
1139       cstring a = context_getAliasAnnote ();
1140
1141
1142       if (fcolon == NULL)
1143         {
1144           s = message ("%q (%q)", s, a);
1145         }
1146       else
1147         {
1148           cstring afterColon;
1149
1150           *fcolon = '\0';
1151           afterColon = cstring_fromCharsNew (fcolon + 1);
1152
1153           s = message ("%q (%q):%q", s, a, afterColon);
1154         }
1155           }
1156
1157   if (context_hasMessageAnnote ())
1158     {
1159       char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1160
1161
1162       if (fcolon == NULL)
1163         {
1164           /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1165           s = message ("%q (%q)", s, context_getMessageAnnote ());
1166           /*@=dependenttrans@*/
1167         }
1168       else
1169         {
1170           cstring afterColon;
1171
1172           *fcolon = '\0';
1173           afterColon = cstring_fromCharsNew (fcolon + 1);
1174
1175           /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1176           s = message ("%q (%q):%q", s,
1177                        context_getMessageAnnote (), afterColon);
1178           /*@=dependenttrans@*/
1179         }
1180      }
1181
1182   context_setNeednl ();
1183   prepareMessage ();
1184
1185   if (context_showFunction ())
1186     {
1187       cstring fname = fileloc_unparseFilename (g_currentloc);
1188
1189       if (context_inIterDef ())
1190         {
1191           fprintf (g_warningstream, "%s: (in iter %s)\n",
1192                    cstring_toCharsSafe (fname),
1193                    cstring_toCharsSafe (context_inFunctionName ()));
1194         }
1195       else if (context_inIterEnd ())
1196         {
1197           fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1198                    cstring_toCharsSafe (fname),
1199                    cstring_toCharsSafe (context_inFunctionName ()));
1200         }
1201       else if (context_inMacro ())
1202         {
1203           fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1204                    cstring_toCharsSafe (context_inFunctionName ()));
1205         }
1206       else
1207         {
1208           fprintf (g_warningstream, "%s: (in function %s)\n",
1209                    cstring_toCharsSafe (fname),
1210                    cstring_toCharsSafe (context_inFunctionName ()));
1211         }
1212
1213       cstring_free (fname);
1214       context_setShownFunction ();
1215     }
1216
1217   flstring = fileloc_unparse (fl);
1218   lastfileloclen = cstring_length (flstring);
1219
1220   generateCSV (code, s, addtext, fl);
1221
1222   if (indent)
1223     {
1224       printError (g_warningstream, message ("   %q: %q", flstring, s));
1225     }
1226   else
1227     {
1228       printError (g_warningstream, message ("%q: %q", flstring, s));
1229     }
1230
1231   showSourceLoc (srcFile, srcLine);
1232              
1233   return TRUE;
1234 }
1235
1236 /*
1237 ** printMessage
1238 **
1239 ** message contains no '\n'
1240 **    message fits in one line: print it
1241 **    message fits in two lines with 3-space indent after fileloc: print it
1242 **    split line with 5-space indent from left margin: print it
1243 **
1244 */
1245
1246 static
1247 void printMessage (FILE *stream, /*@only@*/ cstring s)
1248 {
1249   printIndentMessage (stream, s, 0);
1250 }
1251
1252 static
1253 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1254 {
1255   static bool inbody = FALSE;
1256   int maxlen = context_getLineLen ();
1257   char *s = cstring_toCharsSafe (sc);
1258   char *olds = NULL;
1259
1260   llassertprotect (!inbody);
1261   inbody = TRUE;
1262
1263   do
1264     {
1265       char *t = NULL;
1266       char *st = s;
1267
1268       llassertprotect (st != olds);
1269       olds = st;
1270       mstring_split (&st, &t, maxlen, &indent);
1271       fprintf (stream, "%s\n", st);
1272       llassertprotect (t != s);
1273       s = t;
1274     } while (s != NULL) ;
1275
1276   cstring_free (sc);
1277   inbody = FALSE;
1278 }
1279
1280 static
1281 void printError (FILE *stream, /*@only@*/ cstring sc)
1282 {
1283   int maxlen = context_getLineLen ();
1284   size_t nspaces = lastfileloclen + 5;
1285   int nextlen = maxlen - size_toInt (nspaces);
1286   size_t len = cstring_length (sc);
1287   int indent = 0;
1288   char *s = cstring_toCharsSafe (sc);
1289   char *os = s;
1290   char *t = NULL;
1291
1292   DPRINTF (("Print error: [%s]", sc));
1293
1294   if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1295     {
1296       mstring_split (&s, &t, maxlen, &indent);
1297
1298       fprintf (stream, "%s\n", s);
1299
1300       if (t != NULL)
1301         {
1302           len = mstring_length (t);
1303
1304           if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1305               && size_toInt (len) > (nextlen - 1))
1306             {
1307               fprintf (stream, "    %s\n", t);
1308             }
1309           else
1310             {
1311               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1312               int i;
1313
1314               for (i = 0; i < size_toInt (nspaces); i++)
1315                 {
1316                   spaces[i] = ' ';
1317                 }
1318
1319               spaces[nspaces] = '\0';
1320
1321               while (t != NULL)
1322                 {
1323                   char *st = t;
1324                   mstring_split (&st, &t, nextlen, &indent);
1325                   fprintf (stream, "%s%s\n", spaces, st);
1326                 }
1327
1328               sfree (spaces);
1329             }
1330         }
1331     }
1332   else
1333     {
1334       DPRINTF (("Here 1: [%s]", sc));
1335
1336       if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1337         {
1338           nspaces = ((maxlen + maxlen - 1) - len) / 2;
1339
1340           if (nspaces < 1) nspaces = 1;
1341
1342           nextlen = size_toInt (maxlen - nspaces);
1343
1344           mstring_split (&s, &t, maxlen, &indent);
1345
1346           fprintf (stream, "%s\n", s);
1347
1348           if (t != NULL)
1349             {
1350               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1351               int i;
1352
1353               for (i = 0; i < size_toInt (nspaces); i++)
1354                 {
1355                   spaces[i] = ' ';
1356                 }
1357
1358               spaces[nspaces] = '\0';
1359
1360               while (t != NULL)
1361                 {
1362                   char *st = t;
1363
1364                   mstring_split (&st, &t, nextlen, &indent);
1365                   fprintf (stream, "%s%s\n", spaces, st);
1366                 }
1367
1368               sfree (spaces);
1369             }
1370         }
1371       else
1372         {
1373           nspaces = 4;
1374           nextlen = size_toInt (maxlen - nspaces);
1375
1376           DPRINTF (("Here 2: [%s]", s));
1377           mstring_split (&s, &t, maxlen, &indent);
1378           DPRINTF (("Here 3: [%s] [%s]", s, t));
1379
1380           fprintf (stream, "%s\n", s);
1381
1382           if (t != NULL)
1383             {
1384               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1385               size_t i;
1386
1387               for (i = 0; i < nspaces; i++)
1388                 {
1389                   spaces[i] = ' ';
1390                 }
1391
1392               spaces[nspaces] = '\0';
1393
1394               while (t != NULL)
1395                 {
1396                   char *st = t;
1397                   DPRINTF (("Loop: [%s]", t));
1398                   mstring_split (&st, &t, nextlen, &indent);
1399                   DPRINTF (("Split: [%s] [%s]", st, t));
1400                   fprintf (stream, "%s%s\n", spaces, st);
1401                   DPRINTF (("Next..."));
1402                 }
1403
1404               sfree (spaces);
1405             }
1406         }
1407     }
1408
1409   DPRINTF (("Done"));
1410   sfree (os);
1411 }
1412
1413 void
1414 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1415 {
1416   prepareMessage ();
1417   printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1418                                       fileloc_unparse (g_currentloc), s));
1419   showSourceLoc (srcFile, srcLine);
1420   printCodePoint ();
1421   printBugReport ();
1422   llexit (LLFAILURE);
1423 }
1424
1425 void
1426 lclfatalbug (char *msg)
1427 {
1428   prepareMessage ();
1429   printError (g_errorstream,
1430               message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1431   printCodePoint ();
1432   printBugReport ();
1433   llexit (LLFAILURE);
1434 }
1435
1436 void
1437 checkParseError (void)
1438 {
1439   if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1440     {
1441       llfatalerror (message ("%q: Cannot recover from parse error.",
1442                              fileloc_unparse (g_currentloc)));
1443     }
1444 }
1445
1446 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1447 {
1448   /*@unchecked@*/
1449   static int numbugs = 0;
1450   static bool inbug = FALSE;
1451
1452   if (inbug)
1453     {
1454       cstring temps = fileloc_unparseRaw (file, line);
1455
1456       fprintf (g_errorstream,
1457                "%s: Recursive bug detected: %s\n",
1458                cstring_toCharsSafe (temps),
1459                cstring_toCharsSafe (s));
1460       cstring_free (temps);
1461
1462       llexit (LLFAILURE);
1463     }
1464
1465   inbug = TRUE;
1466
1467   prepareMessage ();
1468
1469   if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1470     {
1471       llfatalerror (message ("%q: Cannot recover from parse error.",
1472                              fileloc_unparse (g_currentloc)));
1473     }
1474
1475   (void) fflush (g_warningstream);
1476
1477   printError (g_errorstream,
1478               message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1479                        fileloc_unparse (g_currentloc),
1480                        fileloc_unparseRaw (file, line),
1481                        s, errno));
1482   
1483   /* printCodePoint (); no longer useful */
1484
1485   llflush ();
1486   
1487   /*
1488   ** This is confusing, and hardly ever useful.
1489
1490   if (errno != 0)
1491     {
1492       perror ("Possible system error diagnostic: ");
1493     }
1494
1495   **
1496   */
1497
1498   printBugReport ();
1499   llflush ();
1500
1501   numbugs++;
1502
1503   if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1504     {
1505       llfatalerror
1506         (message ("%q: Cannot recover from last bug. "
1507                   "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1508                   fileloc_unparse (g_currentloc)));
1509     }
1510   
1511   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1512   fileloc_free (lastbug);
1513   lastbug = fileloc_copy (g_currentloc);
1514   closeMessage ();
1515   inbug = FALSE;
1516 }
1517
1518 void
1519 lclbug (/*@only@*/ cstring s)
1520 {
1521   prepareMessage ();
1522   printError (g_errorstream, message ("*** Internal Bug: %q", s));
1523   printCodePoint ();
1524   printBugReport ();
1525   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1526   closeMessage ();
1527 }
1528
1529 void
1530 xllfatalerror (char *srcFile, int srcLine, cstring s)
1531 {
1532   prepareMessage ();
1533   printError (g_errorstream, s);
1534   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1535   showSourceLoc (srcFile, srcLine);
1536   llexit (LLFAILURE);
1537 }
1538
1539 void
1540 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1541 {
1542   prepareMessage ();
1543   (void) fflush (g_warningstream);
1544   printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1545   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1546   showSourceLoc (srcFile, srcLine);
1547   (void) fflush (g_warningstream);
1548   llexit (LLFAILURE);
1549 }
1550
1551 bool
1552 lclHadError (void)
1553 {
1554   return (lclerrors > 0);
1555 }
1556
1557 bool
1558 lclHadNewError (void)
1559 {
1560   static int lastcall = 0;
1561
1562   if (lclerrors > lastcall)
1563     {
1564       lastcall = lclerrors;
1565       return TRUE;
1566     }
1567   else
1568     {
1569       return FALSE;
1570     }
1571 }
1572
1573 int
1574 lclNumberErrors (void)
1575 {
1576   return (lclerrors);
1577 }
1578
1579 void
1580 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1581 {
1582   lclerrors++;
1583
1584   if (ltoken_getCode (t) != NOTTOKEN)
1585     {
1586       cstring loc = ltoken_unparseLoc (t);
1587       lastfileloclen = cstring_length (loc);
1588
1589       printError (g_warningstream, message ("%q: %q", loc, msg));
1590       showSourceLoc (srcFile, srcLine);
1591     }
1592   else
1593     {
1594       printError (g_warningstream, msg);
1595       showSourceLoc (srcFile, srcLine);
1596     }
1597 }
1598
1599 void
1600 lclplainerror (/*@only@*/ cstring msg)
1601 {
1602   lclerrors++;
1603   printError (g_warningstream, msg);
1604 }
1605
1606 void
1607 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1608 {
1609   if (ltoken_getCode (t) != NOTTOKEN)
1610     {
1611       cstring loc = ltoken_unparseLoc (t);
1612       lastfileloclen = cstring_length (loc);
1613       printError (g_errorstream, message ("%q: %q", loc, msg));
1614     }
1615   else
1616     {
1617       printError (g_errorstream, msg);
1618     }
1619
1620   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1621   llexit (LLFAILURE);
1622 }
1623
1624 void
1625 lclplainfatalerror (/*@only@*/ cstring msg)
1626 {
1627   (void) fflush (g_warningstream);
1628   printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1629   llexit (LLFAILURE);
1630 }
1631
1632 void
1633 lclRedeclarationError (ltoken id)
1634 {
1635   cstring s = ltoken_getRawString (id);
1636
1637
1638   if (usymtab_existsEither (s))
1639     {
1640       uentry le = usymtab_lookupEither (s);
1641
1642       lclerror (id, message ("Respecification of %s", s));
1643       llgenindentmsg (message ("Previous specification of %q",
1644                                uentry_getName (le)),
1645                 uentry_whereSpecified (le));
1646     }
1647   else
1648     {
1649       lclerror (id, message ("Identifier redeclared: %s", s));
1650     }
1651 }
1652
1653 void genppllerror (flagcode code, /*@only@*/ cstring s)
1654 {
1655   if (context_inSuppressZone (g_currentloc))
1656     {
1657       cstring_free (s);
1658     }
1659   else
1660     {
1661       if (context_getFlag (code))
1662         {
1663           if (!context_isInCommandLine ())
1664             {
1665               displayScanClose ();
1666             }
1667
1668           llerror (code, s);
1669
1670           if (code != FLG_PREPROC)
1671             {
1672               llsuppresshint ('-', code);
1673             }
1674
1675           if (!context_isInCommandLine ())
1676             {
1677               displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1678             }
1679         }
1680       else
1681         {
1682           cstring_free (s);
1683         }
1684     }
1685 }
1686
1687 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1688                        /*@only@*/ cstring hint)
1689 {
1690   if (context_inSuppressZone (g_currentloc))
1691     {
1692       cstring_free (s);
1693       cstring_free (hint);
1694     }
1695   else
1696     {
1697       if (context_getFlag (code))
1698         {
1699           generateCSV (code, s, hint, g_currentloc);
1700           prepareMessage ();
1701           context_clearPreprocessing ();
1702           llerror (code, s);
1703           llgenhint (hint);
1704           context_setPreprocessing ();
1705           closeMessage ();
1706         }
1707       else
1708         {
1709           cstring_free (s);
1710           cstring_free (hint);
1711         }
1712     }
1713 }
1714
1715 void ppllerror (/*@only@*/ cstring s)
1716 {
1717   genppllerror (FLG_PREPROC, s);
1718 }
1719
1720 void pplldiagmsg (cstring s)
1721 {
1722   if (!context_isInCommandLine ())
1723     {
1724       displayScanClose ();
1725       lldiagmsg (s);
1726       displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1727     }
1728   else
1729     {
1730       lldiagmsg (s);
1731     }
1732 }
1733
1734 void loadllmsg (cstring s)
1735 {
1736   displayScanClose ();
1737   lldiagmsg (s);
1738   displayScanOpen (cstring_makeLiteral ("< ."));
1739 }
1740
1741 static void llreportparseerror (/*@only@*/ cstring s)
1742 {
1743   if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1744     {
1745       cstring_free (s);
1746     }
1747   else
1748     {
1749       llerror (FLG_SYNTAX, s);
1750
1751       fileloc_free (lastparseerror);
1752       lastparseerror = fileloc_copy (g_currentloc);
1753     }
1754 }
1755
1756 bool xcppoptgenerror (char *srcFile, int srcLine,
1757                       flagcode o,
1758                       /*@only@*/ cstring s,
1759                       cppReader *pfile)
1760 {
1761   bool res = FALSE;
1762   fileloc loc = cppReader_getLoc (pfile);
1763
1764   if (context_flagOn (o, loc))
1765     {
1766       if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1767         {
1768           cppReader_printContainingFiles (pfile);
1769           res = TRUE;
1770         }
1771     }
1772   else
1773     {
1774       cstring_free (s);
1775     }
1776
1777   fileloc_free (loc);
1778
1779   return res;
1780 }
1781
1782 bool xlloptgenerror (char *srcFile, int srcLine, 
1783                      flagcode o, /*@only@*/ cstring s, fileloc loc)
1784 {
1785   DPRINTF (("xllopt: %s", s));
1786
1787   if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1788     {
1789       DPRINTF (("Here we are!"));
1790       llsuppresshint ('-', o);
1791       closeMessage ();
1792       flagcode_recordError (o);
1793       return TRUE;
1794     }
1795   else
1796     {
1797       DPRINTF (("Suppressed!"));
1798       flagcode_recordSuppressed (o);
1799       return FALSE;
1800     }
1801 }
1802
1803 bool xoptgenerror2 (char *srcFile, int srcLine,
1804                     flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1805 {
1806   if (context_suppressFlagMsg (f1, loc))
1807     {
1808       flagcode_recordSuppressed (f1);
1809       cstring_free (s);
1810     }
1811   else
1812     {
1813       if (context_suppressFlagMsg (f2, loc))
1814         {
1815           flagcode_recordSuppressed (f2);
1816           cstring_free (s);
1817         }
1818       else
1819         {
1820           if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1821             {
1822               llsuppresshint2 ('-', f1, f2);
1823               flagcode_recordError (f2);
1824               closeMessage ();
1825               return TRUE;
1826             }
1827           else
1828             {
1829               flagcode_recordSuppressed (f2);
1830             }
1831         }
1832     }
1833
1834   return FALSE;
1835 }
1836
1837 bool xoptgenerror2n (char *srcFile, int srcLine,
1838                      flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1839 {
1840
1841   if (context_suppressFlagMsg (f1, loc))
1842     {
1843       flagcode_recordSuppressed (f1);
1844       cstring_free (s);
1845     }
1846   else
1847     {
1848       if (context_suppressNotFlagMsg (f2, loc))
1849         {
1850           flagcode_recordSuppressed (f2);
1851           cstring_free (s);
1852         }
1853       else
1854         {
1855           if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1856             {
1857               llsuppresshint ('+', f2);
1858               flagcode_recordError (f2);
1859               closeMessage ();
1860               return TRUE;
1861             }
1862
1863           flagcode_recordSuppressed (f2);
1864         }
1865     }
1866   return FALSE;
1867 }
1868
1869 bool xllnoptgenerror (char *srcFile, int srcLine,
1870                       flagcode o, /*@only@*/ cstring s, fileloc loc)
1871 {
1872   if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1873     {
1874       llsuppresshint ('+', o);
1875       flagcode_recordError (o);
1876       closeMessage ();
1877       return TRUE;
1878     }
1879
1880   flagcode_recordSuppressed (o);
1881   return FALSE;
1882 }
1883
1884 void xllparseerror (char *srcFile, int srcLine, cstring s)
1885 {
1886   if (context_getFlag (FLG_TRYTORECOVER))
1887     {
1888       parseerrorcount++;
1889
1890       if (parseerrorcount > GIVEUPPARSE)
1891         {
1892           if (cstring_isDefined (s))
1893             {
1894               xllfatalerror (srcFile, srcLine,
1895                              message ("%q: Parse Error: %q.  "
1896                                       "Too many errors, giving up.",
1897                                       fileloc_unparse (g_currentloc), s));
1898             }
1899           else
1900             {
1901               xllfatalerror (srcFile, srcLine,
1902                              message ("%q: Parse Error.  Too many errors, giving up.",
1903                                       fileloc_unparse (g_currentloc)));
1904             }
1905         }
1906       else
1907         {
1908           if (cstring_isDefined (s))
1909             {
1910               llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1911                                            s));
1912               showSourceLoc (srcFile, srcLine);
1913             }
1914           else
1915             {
1916               llreportparseerror (message ("Parse Error. Attempting to continue."));
1917               showSourceLoc (srcFile, srcLine);
1918             }
1919         }
1920     }
1921   else
1922     {
1923       cstring msg;
1924
1925       if (cstring_isDefined (s))
1926         {
1927           msg = message ("Parse Error: %q.", s);
1928         }
1929       else
1930         {
1931           msg = message ("Parse Error.");
1932         }
1933
1934       xllfatalerror
1935         (srcFile, srcLine,
1936          message ("%q: %s (For help on parse errors, "
1937                   "see splint -help parseerrors.)",
1938                   fileloc_unparse (g_currentloc), msg));
1939     }
1940 }
1941
1942 bool xfsgenerror (char *srcFile, int srcLine,
1943                   flagSpec fs, /*@only@*/ cstring s, fileloc fl) 
1944 {
1945   if (flagSpec_isOn (fs, fl))
1946     {
1947       flagcode firston = flagSpec_getFirstOn (fs, fl);
1948
1949       if (llgenerroraux (firston, srcFile, srcLine, s, 
1950                          flagcodeHint (firston),
1951                          fl, TRUE, FALSE))
1952         {
1953           llsuppresshint ('-', firston);
1954           flagcode_recordError (firston);
1955           return TRUE;
1956         }
1957       else
1958         {
1959           flagcode_recordSuppressed (firston);
1960           return FALSE;
1961         }
1962     }
1963   else
1964     {
1965       flagcode_recordSuppressed (flagSpec_getDominant (fs));
1966       cstring_free (s);
1967       return FALSE;
1968     }
1969 }
1970
1971 bool doCheck (bool x, cstring pred, cstring file, int line)
1972 {
1973   if (!x) {
1974     llbug (message ("%q: Check Failed: %s",
1975                     fileloc_unparseRaw (file, line),
1976                     pred));
1977   }
1978
1979   return x;
1980 }
1981
1982 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1983 {
1984   char *result;
1985
1986 #ifndef VMS
1987 #ifndef HAVE_STRERROR
1988   result = NULL;
1989 #else
1990   result = strerror (errnum);
1991 #endif
1992 #else   /* VMS */
1993   /* VAXCRTL's strerror() takes an optional second argument, which only
1994      matters when the first argument is EVMSERR.  However, it's simplest
1995      just to pass it unconditionally.  `vaxc$errno' is declared in
1996      <errno.h>, and maintained by the library in parallel with `errno'.
1997      We assume that caller's `errnum' either matches the last setting of
1998      `errno' by the library or else does not have the value `EVMSERR'.  */
1999
2000   result = strerror (errnum, vaxc$errno);
2001 #endif
2002
2003   if (result == NULL)
2004     {
2005       result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2006     }
2007
2008   return cstring_fromChars (result);
2009 }
2010
2011 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2012 {
2013 # if 0
2014 # ifdef HOMEVERSION
2015   llflush ();
2016   printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2017                                       fileloc_unparse (g_currentloc),
2018                                       fileloc_unparseRaw (file, line),
2019                                       s, errno));
2020   printCodePoint ();
2021   llflush ();
2022 # endif
2023 # else
2024   cstring_free (s);
2025 # endif
2026 }
2027
2028 void llflush (void)
2029 {
2030   (void) fflush (g_warningstream);
2031   (void) fflush (g_messagestream);
2032 }
2033
2034 static bool s_scanOpen = FALSE;
2035
2036 void displayScan (cstring msg)
2037 {
2038   if (s_scanOpen)
2039     {
2040       displayScanClose ();
2041     }
2042
2043   llassert (!s_scanOpen);
2044
2045   if (context_getFlag (FLG_SHOWSCAN))
2046     {
2047       showHerald ();
2048       fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2049       (void) fflush (g_messagestream);
2050     }
2051
2052   cstring_free (msg);
2053 }
2054
2055 void displayScanOpen (cstring msg)
2056 {
2057   if (s_scanOpen)
2058     {
2059       displayScanClose ();
2060     }
2061
2062   llassert (!s_scanOpen);
2063   s_scanOpen = TRUE;
2064
2065   if (context_getFlag (FLG_SHOWSCAN))
2066     {
2067       fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2068       (void) fflush (g_messagestream);
2069     }
2070
2071   cstring_free (msg);
2072 }
2073
2074 void displayScanContinue (/*@temp@*/ cstring msg)
2075 {
2076   if (context_getFlag (FLG_SHOWSCAN))
2077     {
2078       if (s_scanOpen) 
2079         {
2080           fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2081           (void) fflush (g_messagestream);
2082         }
2083       else
2084         {
2085           /*
2086           ** Don't call bug recursively
2087           */
2088
2089           fprintf (stderr, "*** Bug: scan continue scan not open\n");
2090         }
2091     }
2092 }
2093
2094 void displayScanClose (void)
2095 {
2096   if (s_scanOpen)
2097     {
2098       if (context_getFlag (FLG_SHOWSCAN))
2099         {
2100           fprintf (g_messagestream, " >\n");
2101           (void) fflush (g_messagestream);
2102         }
2103     }
2104   else
2105     {
2106       /*
2107       ** Don't call bug recursively
2108       */
2109       
2110       fprintf (stderr, "*** Bug: scan close scan not open\n");
2111     }
2112   
2113   s_scanOpen = FALSE;
2114 }
2115
2116
This page took 0.200397 seconds and 3 git commands to generate.