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