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