]> andersk Git - splint.git/blob - src/llerror.c
4f108c481e19ab70751f63ee7b43895eb93f4391
[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 "basic.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       if (ctype_isInt (t1)
932           && ctype_isNumAbstract (t2))
933         {
934           if (!context_suppressFlagMsg (FLG_NUMABSTRACTPRINT, fl))
935             {
936               return llgentypeerroraux (srcFile, srcLine, FLG_NUMABSTRACTPRINT, t1, e1, t2, e2, s, fl);
937             }
938           else
939             {
940               return FALSE;
941             }
942         }
943       else
944         {
945           return llgentypeerroraux (srcFile, srcLine, FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
946         }
947     }
948   else
949     {
950       cstring_free (s);
951       return FALSE;
952     }
953 }
954
955 bool
956 xllgenerror (char *srcFile, int srcLine, flagcode o, /*@only@*/ cstring s, fileloc fl)
957 {
958   if (llgenerroraux (o, srcFile, srcLine, s, flagcodeHint (o), fl, TRUE, FALSE))
959     {
960       llnosuppresshint (o);
961       flagcode_recordError (o);
962       closeMessage ();
963       return TRUE;
964     }
965   else
966     {
967       flagcode_recordSuppressed (o);
968       return FALSE;
969     }
970 }
971
972 bool
973 xllgenhinterror (char *srcFile, int srcLine,
974                  flagcode o, /*@only@*/ cstring s, /*@only@*/ cstring hint,
975                  fileloc fl)
976 {
977   if (!context_suppressFlagMsg (o, fl))
978     {
979       if (llgenerroraux (o, srcFile, srcLine, s, hint, fl, TRUE, FALSE))
980         {
981           flagcode_recordError (o);
982
983           if (context_getFlag (FLG_HINTS))
984             {
985               llgenhint (hint);
986             }
987           else
988             {
989               cstring_free (hint);
990             }
991
992           closeMessage ();
993           return TRUE;
994         }
995
996       cstring_free (hint);
997     }
998   else
999     {
1000       cstring_free (hint);
1001       cstring_free (s);
1002     }
1003
1004   flagcode_recordSuppressed (o);
1005   return FALSE;
1006 }
1007
1008 static bool
1009 llrealerror (flagcode code, char *srcFile, int srcLine, /*@only@*/ cstring s, /*@temp@*/ cstring addtext, fileloc fl)
1010 {
1011   return (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, TRUE, FALSE));
1012 }
1013
1014 static bool
1015 llgenerroraux (flagcode code,
1016                char *srcFile, int srcLine,
1017                /*@only@*/ cstring s, 
1018                cstring addtext,
1019                fileloc fl, bool iserror, bool indent)
1020 {
1021   if (context_inSuppressZone (fl))
1022     {
1023       cstring_free (s);
1024       return FALSE;
1025     }
1026   
1027   if (llgenerrorreal (code, srcFile, srcLine, s, addtext, fl, iserror, indent)) {
1028     return TRUE;
1029   } else {
1030     return FALSE;
1031   }
1032 }
1033
1034 bool
1035 xllforceerror (char *srcFile, int srcLine, 
1036                flagcode code, /*@only@*/ cstring s, fileloc fl)
1037 {
1038   flagcode_recordError (code);
1039
1040   if (llgenerrorreal (code, srcFile, srcLine, s, cstring_undefined, fl, TRUE, FALSE)) {
1041     closeMessage ();
1042     return TRUE;
1043   } else {
1044     return FALSE;
1045   }
1046 }
1047
1048 static void generateCSV (flagcode code, cstring s, cstring addtext, fileloc fl)
1049 {
1050
1051   if (g_csvstream != NULL) {
1052     /* Warning, Flag Code, Flag Name, Priority, File, Line, Column, Warning Text, Additional Text */
1053     fprintf (g_csvstream, "%d,%d,%s,%d,%s,%d,%d,\"%s\"",
1054              context_numErrors (),
1055              (int) code, /* flag code */
1056              cstring_toCharsSafe (flagcode_unparse (code)), /* flag name */
1057              flagcode_priority (code), /* priority */
1058              cstring_toCharsSafe (fileloc_outputFilename (fl)),
1059              fileloc_lineno (fl),
1060              fileloc_column (fl),
1061              cstring_toCharsSafe (s));
1062
1063     if (cstring_isDefined (addtext)) {
1064       fprintf (g_csvstream, ",\"%s\"\n", cstring_toCharsSafe (addtext));
1065     } else {
1066       fprintf (g_csvstream, "\n");
1067     }
1068   }
1069 }
1070
1071 static bool
1072 llgenerrorreal (flagcode code, char *srcFile, int srcLine, 
1073                 /*@only@*/ cstring s, 
1074                 cstring addtext,
1075                 fileloc fl, bool iserror, bool indent)
1076 {
1077   cstring flstring;
1078
1079   /* duplicate message (rescanning a header file */
1080
1081   if (!messageLog_add (context_messageLog (), fl, s))
1082     {
1083       DPRINTF (("Duplicate message suppressed! %s / %s",
1084                 fileloc_unparse (fl), s));
1085       cstring_free (s);
1086       return FALSE;
1087     }
1088
1089   /*
1090   ** If herald has not been displayed, display it before the first message.
1091   */
1092
1093   showHerald ();
1094
1095   if (iserror) context_hasError ();
1096
1097   if (context_unlimitedMessages ())
1098     {
1099       ;
1100     }
1101   else
1102     {
1103       /*
1104       ** suppress excessive messages:
1105       **    check up to ':'
1106       **
1107       */
1108
1109       char *sc = cstring_toCharsSafe (s);
1110       char *tmpmsg = strchr (sc, ':');
1111
1112       if (tmpmsg == NULL)
1113         {
1114           tmpmsg = sc;
1115         }
1116       else
1117         {
1118           char *savechar = tmpmsg;
1119           *tmpmsg = '\0';
1120           tmpmsg = sc;
1121           *savechar = ':';
1122         }
1123
1124       if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
1125         {
1126           mcount++;
1127           if (mcount == (context_getLimit () + 1))
1128             {
1129               limitmessage (s, fl);
1130               return FALSE;
1131             }
1132
1133           if (mcount > (context_getLimit ()))
1134             {
1135               cstring_free (s);
1136               return FALSE;
1137             }
1138         }
1139       else
1140         {
1141           cleanupMessages ();
1142           mcount = 0;
1143           cstring_free (lastmsg);
1144           lastmsg = cstring_fromCharsNew (tmpmsg);
1145         }
1146     }
1147
1148   DPRINTF (("Here..."));
1149
1150   if (context_hasAliasAnnote ())
1151     {
1152       char *sc = cstring_toCharsSafe (s);
1153       char *fcolon = strchr (sc, ':');
1154       cstring a = context_getAliasAnnote ();
1155
1156
1157       if (fcolon == NULL)
1158         {
1159           s = message ("%q (%q)", s, a);
1160         }
1161       else
1162         {
1163           cstring afterColon;
1164
1165           *fcolon = '\0';
1166           afterColon = cstring_fromCharsNew (fcolon + 1);
1167
1168           s = message ("%q (%q):%q", s, a, afterColon);
1169         }
1170           }
1171
1172   if (context_hasMessageAnnote ())
1173     {
1174       char *fcolon = strchr (cstring_toCharsSafe (s), ':');
1175
1176
1177       if (fcolon == NULL)
1178         {
1179           /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1180           s = message ("%q (%q)", s, context_getMessageAnnote ());
1181           /*@=dependenttrans@*/
1182         }
1183       else
1184         {
1185           cstring afterColon;
1186
1187           *fcolon = '\0';
1188           afterColon = cstring_fromCharsNew (fcolon + 1);
1189
1190           /*@-dependenttrans@*/ /* s becomes dependent for fcolon */
1191           s = message ("%q (%q):%q", s,
1192                        context_getMessageAnnote (), afterColon);
1193           /*@=dependenttrans@*/
1194         }
1195      }
1196
1197   context_setNeednl ();
1198   prepareMessage ();
1199
1200   if (context_showFunction ())
1201     {
1202       cstring fname = fileloc_unparseFilename (g_currentloc);
1203
1204       if (context_inIterDef ())
1205         {
1206           fprintf (g_warningstream, "%s: (in iter %s)\n",
1207                    cstring_toCharsSafe (fname),
1208                    cstring_toCharsSafe (context_inFunctionName ()));
1209         }
1210       else if (context_inIterEnd ())
1211         {
1212           fprintf (g_warningstream, "%s: (in iter finalizer %s)\n",
1213                    cstring_toCharsSafe (fname),
1214                    cstring_toCharsSafe (context_inFunctionName ()));
1215         }
1216       else if (context_inMacro ())
1217         {
1218           fprintf (g_warningstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
1219                    cstring_toCharsSafe (context_inFunctionName ()));
1220         }
1221       else
1222         {
1223           fprintf (g_warningstream, "%s: (in function %s)\n",
1224                    cstring_toCharsSafe (fname),
1225                    cstring_toCharsSafe (context_inFunctionName ()));
1226         }
1227
1228       cstring_free (fname);
1229       context_setShownFunction ();
1230     }
1231
1232   flstring = fileloc_unparse (fl);
1233   lastfileloclen = cstring_length (flstring);
1234
1235   generateCSV (code, s, addtext, fl);
1236
1237   if (indent)
1238     {
1239       printError (g_warningstream, message ("   %q: %q", flstring, s));
1240     }
1241   else
1242     {
1243       printError (g_warningstream, message ("%q: %q", flstring, s));
1244     }
1245
1246   showSourceLoc (srcFile, srcLine);
1247              
1248   return TRUE;
1249 }
1250
1251 /*
1252 ** printMessage
1253 **
1254 ** message contains no '\n'
1255 **    message fits in one line: print it
1256 **    message fits in two lines with 3-space indent after fileloc: print it
1257 **    split line with 5-space indent from left margin: print it
1258 **
1259 */
1260
1261 static
1262 void printMessage (FILE *stream, /*@only@*/ cstring s)
1263 {
1264   printIndentMessage (stream, s, 0);
1265 }
1266
1267 static
1268 void printIndentMessage (FILE *stream, /*@only@*/ cstring sc, int indent)
1269 {
1270   static bool inbody = FALSE;
1271   int maxlen = context_getLineLen ();
1272   char *s = cstring_toCharsSafe (sc);
1273   char *olds = NULL;
1274
1275   llassertprotect (!inbody);
1276   inbody = TRUE;
1277
1278   do
1279     {
1280       char *t = NULL;
1281       char *st = s;
1282
1283       llassertprotect (st != olds);
1284       olds = st;
1285       mstring_split (&st, &t, maxlen, &indent);
1286       fprintf (stream, "%s\n", st);
1287       llassertprotect (t != s);
1288       s = t;
1289     } while (s != NULL) ;
1290
1291   cstring_free (sc);
1292   inbody = FALSE;
1293 }
1294
1295 static
1296 void printError (FILE *stream, /*@only@*/ cstring sc)
1297 {
1298   int maxlen = context_getLineLen ();
1299   size_t nspaces = lastfileloclen + 5;
1300   int nextlen = maxlen - size_toInt (nspaces);
1301   size_t len = cstring_length (sc);
1302   int indent = 0;
1303   char *s = cstring_toCharsSafe (sc);
1304   char *os = s;
1305   char *t = NULL;
1306
1307   DPRINTF (("Print error: [%s]", sc));
1308
1309   if (size_toInt (len) < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
1310     {
1311       mstring_split (&s, &t, maxlen, &indent);
1312
1313       fprintf (stream, "%s\n", s);
1314
1315       if (t != NULL)
1316         {
1317           len = mstring_length (t);
1318
1319           if (size_toInt (len) < (maxlen - 3) && (strchr (t, '\n') == NULL)
1320               && size_toInt (len) > (nextlen - 1))
1321             {
1322               fprintf (stream, "    %s\n", t);
1323             }
1324           else
1325             {
1326               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1327               int i;
1328
1329               for (i = 0; i < size_toInt (nspaces); i++)
1330                 {
1331                   spaces[i] = ' ';
1332                 }
1333
1334               spaces[nspaces] = '\0';
1335
1336               while (t != NULL)
1337                 {
1338                   char *st = t;
1339                   mstring_split (&st, &t, nextlen, &indent);
1340                   fprintf (stream, "%s%s\n", spaces, st);
1341                 }
1342
1343               sfree (spaces);
1344             }
1345         }
1346     }
1347   else
1348     {
1349       DPRINTF (("Here 1: [%s]", sc));
1350
1351       if (size_toInt (len) < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
1352         {
1353           nspaces = ((maxlen + maxlen - 1) - len) / 2;
1354
1355           if (nspaces < 1) nspaces = 1;
1356
1357           nextlen = size_toInt (maxlen - nspaces);
1358
1359           mstring_split (&s, &t, maxlen, &indent);
1360
1361           fprintf (stream, "%s\n", s);
1362
1363           if (t != NULL)
1364             {
1365               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1366               int i;
1367
1368               for (i = 0; i < size_toInt (nspaces); i++)
1369                 {
1370                   spaces[i] = ' ';
1371                 }
1372
1373               spaces[nspaces] = '\0';
1374
1375               while (t != NULL)
1376                 {
1377                   char *st = t;
1378
1379                   mstring_split (&st, &t, nextlen, &indent);
1380                   fprintf (stream, "%s%s\n", spaces, st);
1381                 }
1382
1383               sfree (spaces);
1384             }
1385         }
1386       else
1387         {
1388           nspaces = 4;
1389           nextlen = size_toInt (maxlen - nspaces);
1390
1391           DPRINTF (("Here 2: [%s]", s));
1392           mstring_split (&s, &t, maxlen, &indent);
1393           DPRINTF (("Here 3: [%s] [%s]", s, t));
1394
1395           fprintf (stream, "%s\n", s);
1396
1397           if (t != NULL)
1398             {
1399               char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
1400               size_t i;
1401
1402               for (i = 0; i < nspaces; i++)
1403                 {
1404                   spaces[i] = ' ';
1405                 }
1406
1407               spaces[nspaces] = '\0';
1408
1409               while (t != NULL)
1410                 {
1411                   char *st = t;
1412                   DPRINTF (("Loop: [%s]", t));
1413                   mstring_split (&st, &t, nextlen, &indent);
1414                   DPRINTF (("Split: [%s] [%s]", st, t));
1415                   fprintf (stream, "%s%s\n", spaces, st);
1416                   DPRINTF (("Next..."));
1417                 }
1418
1419               sfree (spaces);
1420             }
1421         }
1422     }
1423
1424   DPRINTF (("Done"));
1425   sfree (os);
1426 }
1427
1428 void
1429 xllfatalbug (char *srcFile, int srcLine, /*@only@*/ cstring s)
1430 {
1431   prepareMessage ();
1432   printError (g_errorstream, message ("%q: *** Fatal bug: %q",
1433                                       fileloc_unparse (g_currentloc), s));
1434   showSourceLoc (srcFile, srcLine);
1435   printCodePoint ();
1436   printBugReport ();
1437   llexit (LLFAILURE);
1438 }
1439
1440 void
1441 lclfatalbug (char *msg)
1442 {
1443   prepareMessage ();
1444   printError (g_errorstream,
1445               message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
1446   printCodePoint ();
1447   printBugReport ();
1448   llexit (LLFAILURE);
1449 }
1450
1451 void
1452 checkParseError (void)
1453 {
1454   if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
1455     {
1456       llfatalerror (message ("%q: Cannot recover from parse error.",
1457                              fileloc_unparse (g_currentloc)));
1458     }
1459 }
1460
1461 void llbugaux (cstring file, int line, /*@only@*/ cstring s)
1462 {
1463   /*@unchecked@*/
1464   static int numbugs = 0;
1465   static bool inbug = FALSE;
1466
1467   if (inbug)
1468     {
1469       cstring temps = fileloc_unparseRaw (file, line);
1470
1471       fprintf (g_errorstream,
1472                "%s: Recursive bug detected: %s\n",
1473                cstring_toCharsSafe (temps),
1474                cstring_toCharsSafe (s));
1475       cstring_free (temps);
1476
1477       llexit (LLFAILURE);
1478     }
1479
1480   inbug = TRUE;
1481
1482   prepareMessage ();
1483
1484   if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1485     {
1486       llfatalerror (message ("%q: Cannot recover from parse error.",
1487                              fileloc_unparse (g_currentloc)));
1488     }
1489
1490   (void) fflush (g_warningstream);
1491
1492   printError (g_errorstream,
1493               message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1494                        fileloc_unparse (g_currentloc),
1495                        fileloc_unparseRaw (file, line),
1496                        s, errno));
1497   
1498   /* printCodePoint (); no longer useful */
1499
1500   llflush ();
1501   
1502   /*
1503   ** This is confusing, and hardly ever useful.
1504
1505   if (errno != 0)
1506     {
1507       perror ("Possible system error diagnostic: ");
1508     }
1509
1510   **
1511   */
1512
1513   printBugReport ();
1514   llflush ();
1515
1516   numbugs++;
1517
1518   if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1519     {
1520       llfatalerror
1521         (message ("%q: Cannot recover from last bug. "
1522                   "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1523                   fileloc_unparse (g_currentloc)));
1524     }
1525   
1526   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1527   fileloc_free (lastbug);
1528   lastbug = fileloc_copy (g_currentloc);
1529   closeMessage ();
1530   inbug = FALSE;
1531 }
1532
1533 void
1534 lclbug (/*@only@*/ cstring s)
1535 {
1536   prepareMessage ();
1537   printError (g_errorstream, message ("*** Internal Bug: %q", s));
1538   printCodePoint ();
1539   printBugReport ();
1540   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1541   closeMessage ();
1542 }
1543
1544 void
1545 xllfatalerror (char *srcFile, int srcLine, cstring s)
1546 {
1547   prepareMessage ();
1548   printError (g_errorstream, s);
1549   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1550   showSourceLoc (srcFile, srcLine);
1551   llexit (LLFAILURE);
1552 }
1553
1554 void
1555 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1556 {
1557   prepareMessage ();
1558   (void) fflush (g_warningstream);
1559   printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1560   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1561   showSourceLoc (srcFile, srcLine);
1562   (void) fflush (g_warningstream);
1563   llexit (LLFAILURE);
1564 }
1565
1566 bool
1567 lclHadError (void)
1568 {
1569   return (lclerrors > 0);
1570 }
1571
1572 bool
1573 lclHadNewError (void)
1574 {
1575   static int lastcall = 0;
1576
1577   if (lclerrors > lastcall)
1578     {
1579       lastcall = lclerrors;
1580       return TRUE;
1581     }
1582   else
1583     {
1584       return FALSE;
1585     }
1586 }
1587
1588 int
1589 lclNumberErrors (void)
1590 {
1591   return (lclerrors);
1592 }
1593
1594 void
1595 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1596 {
1597   lclerrors++;
1598
1599   if (ltoken_getCode (t) != NOTTOKEN)
1600     {
1601       cstring loc = ltoken_unparseLoc (t);
1602       lastfileloclen = cstring_length (loc);
1603
1604       printError (g_warningstream, message ("%q: %q", loc, msg));
1605       showSourceLoc (srcFile, srcLine);
1606     }
1607   else
1608     {
1609       printError (g_warningstream, msg);
1610       showSourceLoc (srcFile, srcLine);
1611     }
1612 }
1613
1614 void
1615 lclplainerror (/*@only@*/ cstring msg)
1616 {
1617   lclerrors++;
1618   printError (g_warningstream, msg);
1619 }
1620
1621 void
1622 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1623 {
1624   if (ltoken_getCode (t) != NOTTOKEN)
1625     {
1626       cstring loc = ltoken_unparseLoc (t);
1627       lastfileloclen = cstring_length (loc);
1628       printError (g_errorstream, message ("%q: %q", loc, msg));
1629     }
1630   else
1631     {
1632       printError (g_errorstream, msg);
1633     }
1634
1635   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1636   llexit (LLFAILURE);
1637 }
1638
1639 void
1640 lclplainfatalerror (/*@only@*/ cstring msg)
1641 {
1642   (void) fflush (g_warningstream);
1643   printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1644   llexit (LLFAILURE);
1645 }
1646
1647 void
1648 lclRedeclarationError (ltoken id)
1649 {
1650   cstring s = ltoken_getRawString (id);
1651
1652
1653   if (usymtab_existsEither (s))
1654     {
1655       uentry le = usymtab_lookupEither (s);
1656
1657       lclerror (id, message ("Respecification of %s", s));
1658       llgenindentmsg (message ("Previous specification of %q",
1659                                uentry_getName (le)),
1660                 uentry_whereSpecified (le));
1661     }
1662   else
1663     {
1664       lclerror (id, message ("Identifier redeclared: %s", s));
1665     }
1666 }
1667
1668 void genppllerror (flagcode code, /*@only@*/ cstring s)
1669 {
1670   if (context_inSuppressZone (g_currentloc))
1671     {
1672       cstring_free (s);
1673     }
1674   else
1675     {
1676       if (context_getFlag (code))
1677         {
1678           if (!context_isInCommandLine ())
1679             {
1680               displayScanClose ();
1681             }
1682
1683           llerror (code, s);
1684
1685           if (code != FLG_PREPROC)
1686             {
1687               llsuppresshint ('-', code);
1688             }
1689
1690           if (!context_isInCommandLine ())
1691             {
1692               displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1693             }
1694         }
1695       else
1696         {
1697           cstring_free (s);
1698         }
1699     }
1700 }
1701
1702 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1703                        /*@only@*/ cstring hint)
1704 {
1705   if (context_inSuppressZone (g_currentloc))
1706     {
1707       cstring_free (s);
1708       cstring_free (hint);
1709     }
1710   else
1711     {
1712       if (context_getFlag (code))
1713         {
1714           generateCSV (code, s, hint, g_currentloc);
1715           prepareMessage ();
1716           context_clearPreprocessing ();
1717           llerror (code, s);
1718           llgenhint (hint);
1719           context_setPreprocessing ();
1720           closeMessage ();
1721         }
1722       else
1723         {
1724           cstring_free (s);
1725           cstring_free (hint);
1726         }
1727     }
1728 }
1729
1730 void ppllerror (/*@only@*/ cstring s)
1731 {
1732   genppllerror (FLG_PREPROC, s);
1733 }
1734
1735 void pplldiagmsg (cstring s)
1736 {
1737   if (!context_isInCommandLine ())
1738     {
1739       displayScanClose ();
1740       lldiagmsg (s);
1741       displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1742     }
1743   else
1744     {
1745       lldiagmsg (s);
1746     }
1747 }
1748
1749 void loadllmsg (cstring s)
1750 {
1751   displayScanClose ();
1752   lldiagmsg (s);
1753   displayScanOpen (cstring_makeLiteral ("< ."));
1754 }
1755
1756 static void llreportparseerror (/*@only@*/ cstring s)
1757 {
1758   if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1759     {
1760       cstring_free (s);
1761     }
1762   else
1763     {
1764       llerror (FLG_SYNTAX, s);
1765
1766       fileloc_free (lastparseerror);
1767       lastparseerror = fileloc_copy (g_currentloc);
1768     }
1769 }
1770
1771 bool xcppoptgenerror (char *srcFile, int srcLine,
1772                       flagcode o,
1773                       /*@only@*/ cstring s,
1774                       cppReader *pfile)
1775 {
1776   bool res = FALSE;
1777   fileloc loc = cppReader_getLoc (pfile);
1778
1779   if (context_flagOn (o, loc))
1780     {
1781       if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1782         {
1783           cppReader_printContainingFiles (pfile);
1784           res = TRUE;
1785         }
1786     }
1787   else
1788     {
1789       cstring_free (s);
1790     }
1791
1792   fileloc_free (loc);
1793
1794   return res;
1795 }
1796
1797 bool xlloptgenerror (char *srcFile, int srcLine, 
1798                      flagcode o, /*@only@*/ cstring s, fileloc loc)
1799 {
1800   DPRINTF (("xllopt: %s", s));
1801
1802   if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1803     {
1804       DPRINTF (("Here we are!"));
1805       llsuppresshint ('-', o);
1806       closeMessage ();
1807       flagcode_recordError (o);
1808       return TRUE;
1809     }
1810   else
1811     {
1812       DPRINTF (("Suppressed!"));
1813       flagcode_recordSuppressed (o);
1814       return FALSE;
1815     }
1816 }
1817
1818 bool xoptgenerror2 (char *srcFile, int srcLine,
1819                     flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1820 {
1821   if (context_suppressFlagMsg (f1, loc))
1822     {
1823       flagcode_recordSuppressed (f1);
1824       cstring_free (s);
1825     }
1826   else
1827     {
1828       if (context_suppressFlagMsg (f2, loc))
1829         {
1830           flagcode_recordSuppressed (f2);
1831           cstring_free (s);
1832         }
1833       else
1834         {
1835           if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1836             {
1837               llsuppresshint2 ('-', f1, f2);
1838               flagcode_recordError (f2);
1839               closeMessage ();
1840               return TRUE;
1841             }
1842           else
1843             {
1844               flagcode_recordSuppressed (f2);
1845             }
1846         }
1847     }
1848
1849   return FALSE;
1850 }
1851
1852 bool xoptgenerror2n (char *srcFile, int srcLine,
1853                      flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1854 {
1855
1856   if (context_suppressFlagMsg (f1, loc))
1857     {
1858       flagcode_recordSuppressed (f1);
1859       cstring_free (s);
1860     }
1861   else
1862     {
1863       if (context_suppressNotFlagMsg (f2, loc))
1864         {
1865           flagcode_recordSuppressed (f2);
1866           cstring_free (s);
1867         }
1868       else
1869         {
1870           if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1871             {
1872               llsuppresshint ('+', f2);
1873               flagcode_recordError (f2);
1874               closeMessage ();
1875               return TRUE;
1876             }
1877
1878           flagcode_recordSuppressed (f2);
1879         }
1880     }
1881   return FALSE;
1882 }
1883
1884 bool xllnoptgenerror (char *srcFile, int srcLine,
1885                       flagcode o, /*@only@*/ cstring s, fileloc loc)
1886 {
1887   if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1888     {
1889       llsuppresshint ('+', o);
1890       flagcode_recordError (o);
1891       closeMessage ();
1892       return TRUE;
1893     }
1894
1895   flagcode_recordSuppressed (o);
1896   return FALSE;
1897 }
1898
1899 void xllparseerror (char *srcFile, int srcLine, cstring s)
1900 {
1901   if (context_getFlag (FLG_TRYTORECOVER))
1902     {
1903       parseerrorcount++;
1904
1905       if (parseerrorcount > GIVEUPPARSE)
1906         {
1907           if (cstring_isDefined (s))
1908             {
1909               xllfatalerror (srcFile, srcLine,
1910                              message ("%q: Parse Error: %q.  "
1911                                       "Too many errors, giving up.",
1912                                       fileloc_unparse (g_currentloc), s));
1913             }
1914           else
1915             {
1916               xllfatalerror (srcFile, srcLine,
1917                              message ("%q: Parse Error.  Too many errors, giving up.",
1918                                       fileloc_unparse (g_currentloc)));
1919             }
1920         }
1921       else
1922         {
1923           if (cstring_isDefined (s))
1924             {
1925               llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1926                                            s));
1927               showSourceLoc (srcFile, srcLine);
1928             }
1929           else
1930             {
1931               llreportparseerror (message ("Parse Error. Attempting to continue."));
1932               showSourceLoc (srcFile, srcLine);
1933             }
1934         }
1935     }
1936   else
1937     {
1938       cstring msg;
1939
1940       if (cstring_isDefined (s))
1941         {
1942           msg = message ("Parse Error: %q.", s);
1943         }
1944       else
1945         {
1946           msg = message ("Parse Error.");
1947         }
1948
1949       xllfatalerror
1950         (srcFile, srcLine,
1951          message ("%q: %s (For help on parse errors, "
1952                   "see splint -help parseerrors.)",
1953                   fileloc_unparse (g_currentloc), msg));
1954     }
1955 }
1956
1957 bool xfsgenerror (char *srcFile, int srcLine,
1958                   flagSpec fs, /*@only@*/ cstring s, fileloc fl) 
1959 {
1960   if (flagSpec_isOn (fs, fl))
1961     {
1962       flagcode firston = flagSpec_getFirstOn (fs, fl);
1963
1964       if (llgenerroraux (firston, srcFile, srcLine, s, 
1965                          flagcodeHint (firston),
1966                          fl, TRUE, FALSE))
1967         {
1968           llsuppresshint ('-', firston);
1969           flagcode_recordError (firston);
1970           return TRUE;
1971         }
1972       else
1973         {
1974           flagcode_recordSuppressed (firston);
1975           return FALSE;
1976         }
1977     }
1978   else
1979     {
1980       flagcode_recordSuppressed (flagSpec_getDominant (fs));
1981       cstring_free (s);
1982       return FALSE;
1983     }
1984 }
1985
1986 bool doCheck (bool x, cstring pred, cstring file, int line)
1987 {
1988   if (!x) {
1989     llbug (message ("%q: Check Failed: %s",
1990                     fileloc_unparseRaw (file, line),
1991                     pred));
1992   }
1993
1994   return x;
1995 }
1996
1997 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1998 {
1999   char *result;
2000
2001 #ifndef VMS
2002 #ifndef HAVE_STRERROR
2003   result = NULL;
2004 #else
2005   result = strerror (errnum);
2006 #endif
2007 #else   /* VMS */
2008   /* VAXCRTL's strerror() takes an optional second argument, which only
2009      matters when the first argument is EVMSERR.  However, it's simplest
2010      just to pass it unconditionally.  `vaxc$errno' is declared in
2011      <errno.h>, and maintained by the library in parallel with `errno'.
2012      We assume that caller's `errnum' either matches the last setting of
2013      `errno' by the library or else does not have the value `EVMSERR'.  */
2014
2015   result = strerror (errnum, vaxc$errno);
2016 #endif
2017
2018   if (result == NULL)
2019     {
2020       result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2021     }
2022
2023   return cstring_fromChars (result);
2024 }
2025
2026 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2027 {
2028 # if 0
2029 # ifdef HOMEVERSION
2030   llflush ();
2031   printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2032                                       fileloc_unparse (g_currentloc),
2033                                       fileloc_unparseRaw (file, line),
2034                                       s, errno));
2035   printCodePoint ();
2036   llflush ();
2037 # endif
2038 # else
2039   cstring_free (s);
2040 # endif
2041 }
2042
2043 void llflush (void)
2044 {
2045   (void) fflush (g_warningstream);
2046   (void) fflush (g_messagestream);
2047 }
2048
2049 static bool s_scanOpen = FALSE;
2050
2051 void displayScan (cstring msg)
2052 {
2053   if (s_scanOpen)
2054     {
2055       displayScanClose ();
2056     }
2057
2058   llassert (!s_scanOpen);
2059
2060   if (context_getFlag (FLG_SHOWSCAN))
2061     {
2062       showHerald ();
2063       fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2064       (void) fflush (g_messagestream);
2065     }
2066
2067   cstring_free (msg);
2068 }
2069
2070 void displayScanOpen (cstring msg)
2071 {
2072   if (s_scanOpen)
2073     {
2074       displayScanClose ();
2075     }
2076
2077   llassert (!s_scanOpen);
2078   s_scanOpen = TRUE;
2079
2080   if (context_getFlag (FLG_SHOWSCAN))
2081     {
2082       fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2083       (void) fflush (g_messagestream);
2084     }
2085
2086   cstring_free (msg);
2087 }
2088
2089 void displayScanContinue (/*@temp@*/ cstring msg)
2090 {
2091   if (context_getFlag (FLG_SHOWSCAN))
2092     {
2093       if (s_scanOpen) 
2094         {
2095           fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2096           (void) fflush (g_messagestream);
2097         }
2098       else
2099         {
2100           /*
2101           ** Don't call bug recursively
2102           */
2103
2104           fprintf (stderr, "*** Bug: scan continue scan not open\n");
2105         }
2106     }
2107 }
2108
2109 void displayScanClose (void)
2110 {
2111   if (s_scanOpen)
2112     {
2113       if (context_getFlag (FLG_SHOWSCAN))
2114         {
2115           fprintf (g_messagestream, " >\n");
2116           (void) fflush (g_messagestream);
2117         }
2118     }
2119   else
2120     {
2121       /*
2122       ** Don't call bug recursively
2123       */
2124       
2125       fprintf (stderr, "*** Bug: scan close scan not open\n");
2126     }
2127   
2128   s_scanOpen = FALSE;
2129 }
2130
2131
This page took 0.189972 seconds and 3 git commands to generate.