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