]> andersk Git - splint.git/blob - src/llerror.c
cd92b010e9df6779ad7479103cc6617e47e55256
[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   if (inbug)
1490     {
1491       cstring temps = fileloc_unparseRaw (file, line);
1492
1493       fprintf (g_errorstream,
1494                "%s: Recursive bug detected: %s\n",
1495                cstring_toCharsSafe (temps),
1496                cstring_toCharsSafe (s));
1497       cstring_free (temps);
1498
1499       llexit (LLFAILURE);
1500     }
1501
1502   inbug = TRUE;
1503
1504   prepareMessage ();
1505
1506   if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
1507     {
1508       llfatalerror (message ("%q: Cannot recover from parse error.",
1509                              fileloc_unparse (g_currentloc)));
1510     }
1511
1512   (void) fflush (g_warningstream);
1513
1514   printError (g_errorstream,
1515               message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1516                        fileloc_unparse (g_currentloc),
1517                        fileloc_unparseRaw (file, line),
1518                        s, errno));
1519   
1520   /* printCodePoint (); no longer useful */
1521
1522   llflush ();
1523   
1524   /*
1525   ** This is confusing, and hardly ever useful.
1526
1527   if (errno != 0)
1528     {
1529       perror ("Possible system error diagnostic: ");
1530     }
1531
1532   **
1533   */
1534
1535   printBugReport ();
1536   llflush ();
1537
1538   numbugs++;
1539
1540   if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1541     {
1542       llfatalerror
1543         (message ("%q: Cannot recover from last bug. "
1544                   "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1545                   fileloc_unparse (g_currentloc)));
1546     }
1547   
1548   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1549   fileloc_free (lastbug);
1550   lastbug = fileloc_copy (g_currentloc);
1551   closeMessage ();
1552   inbug = FALSE;
1553 }
1554
1555 void
1556 lclbug (/*@only@*/ cstring s)
1557 {
1558   prepareMessage ();
1559   printError (g_errorstream, message ("*** Internal Bug: %q", s));
1560   printCodePoint ();
1561   printBugReport ();
1562   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1563   closeMessage ();
1564 }
1565
1566 void
1567 xllfatalerror (char *srcFile, int srcLine, cstring s)
1568 {
1569   prepareMessage ();
1570   printError (g_errorstream, s);
1571   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1572   showSourceLoc (srcFile, srcLine);
1573   llexit (LLFAILURE);
1574 }
1575
1576 void
1577 xllfatalerrorLoc (char *srcFile, int srcLine, /*@only@*/ cstring s)
1578 {
1579   prepareMessage ();
1580   (void) fflush (g_warningstream);
1581   printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1582   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1583   showSourceLoc (srcFile, srcLine);
1584   (void) fflush (g_warningstream);
1585   llexit (LLFAILURE);
1586 }
1587
1588 bool
1589 lclHadError (void)
1590 {
1591   return (s_lclerrors > 0);
1592 }
1593
1594 bool
1595 lclHadNewError (void)
1596 {
1597   static int lastcall = 0;
1598
1599   if (s_lclerrors > lastcall)
1600     {
1601       lastcall = s_lclerrors;
1602       return TRUE;
1603     }
1604   else
1605     {
1606       return FALSE;
1607     }
1608 }
1609
1610 int
1611 lclNumberErrors (void)
1612 {
1613   return (s_lclerrors);
1614 }
1615
1616 void
1617 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1618 {
1619   s_lclerrors++;
1620
1621   if (ltoken_getCode (t) != NOTTOKEN)
1622     {
1623       cstring loc = ltoken_unparseLoc (t);
1624       s_lastfileloclen = cstring_length (loc);
1625
1626       printError (g_warningstream, message ("%q: %q", loc, msg));
1627       showSourceLoc (srcFile, srcLine);
1628     }
1629   else
1630     {
1631       printError (g_warningstream, msg);
1632       showSourceLoc (srcFile, srcLine);
1633     }
1634 }
1635
1636 void
1637 lclplainerror (/*@only@*/ cstring msg)
1638 {
1639   s_lclerrors++;
1640   printError (g_warningstream, msg);
1641 }
1642
1643 void
1644 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1645 {
1646   if (ltoken_getCode (t) != NOTTOKEN)
1647     {
1648       cstring loc = ltoken_unparseLoc (t);
1649       s_lastfileloclen = cstring_length (loc);
1650       printError (g_errorstream, message ("%q: %q", loc, msg));
1651     }
1652   else
1653     {
1654       printError (g_errorstream, msg);
1655     }
1656
1657   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1658   llexit (LLFAILURE);
1659 }
1660
1661 void
1662 lclplainfatalerror (/*@only@*/ cstring msg)
1663 {
1664   (void) fflush (g_warningstream);
1665   printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1666   llexit (LLFAILURE);
1667 }
1668
1669 void
1670 lclRedeclarationError (ltoken id)
1671 {
1672   cstring s = ltoken_getRawString (id);
1673
1674
1675   if (usymtab_existsEither (s))
1676     {
1677       uentry le = usymtab_lookupEither (s);
1678
1679       lclerror (id, message ("Respecification of %s", s));
1680       llgenindentmsg (message ("Previous specification of %q",
1681                                uentry_getName (le)),
1682                 uentry_whereSpecified (le));
1683     }
1684   else
1685     {
1686       lclerror (id, message ("Identifier redeclared: %s", s));
1687     }
1688 }
1689
1690 void genppllerror (flagcode code, /*@only@*/ cstring s)
1691 {
1692   if (context_inSuppressZone (g_currentloc))
1693     {
1694       cstring_free (s);
1695     }
1696   else
1697     {
1698       if (context_getFlag (code))
1699         {
1700           if (s_scanOpen)
1701             {
1702               displayScanClose ();
1703             }
1704
1705           llerror (code, s);
1706
1707           if (code != FLG_PREPROC)
1708             {
1709               llsuppresshint ('-', code);
1710             }
1711
1712           if (!context_isInCommandLine ())
1713             {
1714               displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1715             }
1716         }
1717       else
1718         {
1719           cstring_free (s);
1720         }
1721     }
1722 }
1723
1724 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1725                        /*@only@*/ cstring hint)
1726 {
1727   if (context_inSuppressZone (g_currentloc))
1728     {
1729       cstring_free (s);
1730       cstring_free (hint);
1731     }
1732   else
1733     {
1734       if (context_getFlag (code))
1735         {
1736           generateCSV (code, s, hint, g_currentloc);
1737           prepareMessage ();
1738           context_clearPreprocessing ();
1739           llerror (code, s);
1740           llgenhint (hint);
1741           context_setPreprocessing ();
1742           closeMessage ();
1743         }
1744       else
1745         {
1746           cstring_free (s);
1747           cstring_free (hint);
1748         }
1749     }
1750 }
1751
1752 void ppllerror (/*@only@*/ cstring s)
1753 {
1754   genppllerror (FLG_PREPROC, s);
1755 }
1756
1757 void pplldiagmsg (cstring s)
1758 {
1759   if (!context_isInCommandLine ())
1760     {
1761       if (s_scanOpen) 
1762         {
1763           displayScanClose ();
1764         }
1765
1766       lldiagmsg (s);
1767       displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1768     }
1769   else
1770     {
1771       lldiagmsg (s);
1772     }
1773 }
1774
1775 void loadllmsg (cstring s)
1776 {
1777   displayScanClose ();
1778   lldiagmsg (s);
1779   displayScanOpen (cstring_makeLiteral ("< ."));
1780 }
1781
1782 static void llreportparseerror (/*@only@*/ cstring s)
1783 {
1784   if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1785     {
1786       cstring_free (s);
1787     }
1788   else
1789     {
1790       llerror (FLG_SYNTAX, s);
1791
1792       fileloc_free (lastparseerror);
1793       lastparseerror = fileloc_copy (g_currentloc);
1794     }
1795 }
1796
1797 bool xcppoptgenerror (char *srcFile, int srcLine,
1798                       flagcode o,
1799                       /*@only@*/ cstring s,
1800                       cppReader *pfile)
1801 {
1802   bool res = FALSE;
1803   fileloc loc = cppReader_getLoc (pfile);
1804
1805   if (context_flagOn (o, loc))
1806     {
1807       if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1808         {
1809           cppReader_printContainingFiles (pfile);
1810           res = TRUE;
1811         }
1812     }
1813   else
1814     {
1815       cstring_free (s);
1816     }
1817
1818   fileloc_free (loc);
1819
1820   return res;
1821 }
1822
1823 bool xlloptgenerror (char *srcFile, int srcLine, 
1824                      flagcode o, /*@only@*/ cstring s, fileloc loc)
1825 {
1826   DPRINTF (("xllopt: %s", s));
1827
1828   if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1829     {
1830       DPRINTF (("Here we are!"));
1831       llsuppresshint ('-', o);
1832       closeMessage ();
1833       flagcode_recordError (o);
1834       return TRUE;
1835     }
1836   else
1837     {
1838       DPRINTF (("Suppressed!"));
1839       flagcode_recordSuppressed (o);
1840       return FALSE;
1841     }
1842 }
1843
1844 bool xoptgenerror2 (char *srcFile, int srcLine,
1845                     flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1846 {
1847   if (context_suppressFlagMsg (f1, loc))
1848     {
1849       flagcode_recordSuppressed (f1);
1850       cstring_free (s);
1851     }
1852   else
1853     {
1854       if (context_suppressFlagMsg (f2, loc))
1855         {
1856           flagcode_recordSuppressed (f2);
1857           cstring_free (s);
1858         }
1859       else
1860         {
1861           if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f1), loc))
1862             {
1863               llsuppresshint2 ('-', f1, f2);
1864               flagcode_recordError (f2);
1865               closeMessage ();
1866               return TRUE;
1867             }
1868           else
1869             {
1870               flagcode_recordSuppressed (f2);
1871             }
1872         }
1873     }
1874
1875   return FALSE;
1876 }
1877
1878 bool xoptgenerror2n (char *srcFile, int srcLine,
1879                      flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1880 {
1881
1882   if (context_suppressFlagMsg (f1, loc))
1883     {
1884       flagcode_recordSuppressed (f1);
1885       cstring_free (s);
1886     }
1887   else
1888     {
1889       if (context_suppressNotFlagMsg (f2, loc))
1890         {
1891           flagcode_recordSuppressed (f2);
1892           cstring_free (s);
1893         }
1894       else
1895         {
1896           if (llrealerror (f1, srcFile, srcLine, s, flagcodeHint (f2), loc))
1897             {
1898               llsuppresshint ('+', f2);
1899               flagcode_recordError (f2);
1900               closeMessage ();
1901               return TRUE;
1902             }
1903
1904           flagcode_recordSuppressed (f2);
1905         }
1906     }
1907   return FALSE;
1908 }
1909
1910 bool xllnoptgenerror (char *srcFile, int srcLine,
1911                       flagcode o, /*@only@*/ cstring s, fileloc loc)
1912 {
1913   if (llrealerror (o, srcFile, srcLine, s, flagcodeHint (o), loc))
1914     {
1915       llsuppresshint ('+', o);
1916       flagcode_recordError (o);
1917       closeMessage ();
1918       return TRUE;
1919     }
1920
1921   flagcode_recordSuppressed (o);
1922   return FALSE;
1923 }
1924
1925 void xllparseerror (char *srcFile, int srcLine, cstring s)
1926 {
1927   if (context_getFlag (FLG_TRYTORECOVER))
1928     {
1929       parseerrorcount++;
1930
1931       if (parseerrorcount > GIVEUPPARSE)
1932         {
1933           if (cstring_isDefined (s))
1934             {
1935               xllfatalerror (srcFile, srcLine,
1936                              message ("%q: Parse Error: %q.  "
1937                                       "Too many errors, giving up.",
1938                                       fileloc_unparse (g_currentloc), s));
1939             }
1940           else
1941             {
1942               xllfatalerror (srcFile, srcLine,
1943                              message ("%q: Parse Error.  Too many errors, giving up.",
1944                                       fileloc_unparse (g_currentloc)));
1945             }
1946         }
1947       else
1948         {
1949           if (cstring_isDefined (s))
1950             {
1951               llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1952                                            s));
1953               showSourceLoc (srcFile, srcLine);
1954             }
1955           else
1956             {
1957               llreportparseerror (message ("Parse Error. Attempting to continue."));
1958               showSourceLoc (srcFile, srcLine);
1959             }
1960         }
1961     }
1962   else
1963     {
1964       cstring msg;
1965
1966       if (cstring_isDefined (s))
1967         {
1968           msg = message ("Parse Error: %q.", s);
1969         }
1970       else
1971         {
1972           msg = message ("Parse Error.");
1973         }
1974
1975       xllfatalerror
1976         (srcFile, srcLine,
1977          message ("%q: %s (For help on parse errors, "
1978                   "see splint -help parseerrors.)",
1979                   fileloc_unparse (g_currentloc), msg));
1980     }
1981 }
1982
1983 bool xfsgenerror (char *srcFile, int srcLine,
1984                   flagSpec fs, /*@only@*/ cstring s, fileloc fl) 
1985 {
1986   if (flagSpec_isOn (fs, fl))
1987     {
1988       flagcode firston = flagSpec_getFirstOn (fs, fl);
1989
1990       if (llgenerroraux (firston, srcFile, srcLine, s, 
1991                          flagcodeHint (firston),
1992                          fl, TRUE, FALSE))
1993         {
1994           llsuppresshint ('-', firston);
1995           flagcode_recordError (firston);
1996           return TRUE;
1997         }
1998       else
1999         {
2000           flagcode_recordSuppressed (firston);
2001           return FALSE;
2002         }
2003     }
2004   else
2005     {
2006       flagcode_recordSuppressed (flagSpec_getDominant (fs));
2007       cstring_free (s);
2008       return FALSE;
2009     }
2010 }
2011
2012 bool doCheck (bool x, cstring pred, cstring file, int line)
2013 {
2014   if (!x) {
2015     llbug (message ("%q: Check Failed: %s",
2016                     fileloc_unparseRaw (file, line),
2017                     pred));
2018   }
2019
2020   return x;
2021 }
2022
2023 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
2024 {
2025   char *result;
2026
2027 #ifndef VMS
2028 #ifndef HAVE_STRERROR
2029   result = NULL;
2030 #else
2031   result = strerror (errnum);
2032 #endif
2033 #else   /* VMS */
2034   /* VAXCRTL's strerror() takes an optional second argument, which only
2035      matters when the first argument is EVMSERR.  However, it's simplest
2036      just to pass it unconditionally.  `vaxc$errno' is declared in
2037      <errno.h>, and maintained by the library in parallel with `errno'.
2038      We assume that caller's `errnum' either matches the last setting of
2039      `errno' by the library or else does not have the value `EVMSERR'.  */
2040
2041   result = strerror (errnum, vaxc$errno);
2042 #endif
2043
2044   if (result == NULL)
2045     {
2046       result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
2047     }
2048
2049   return cstring_fromChars (result);
2050 }
2051
2052 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
2053 {
2054 # if 0
2055 # ifdef HOMEVERSION
2056   llflush ();
2057   printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
2058                                       fileloc_unparse (g_currentloc),
2059                                       fileloc_unparseRaw (file, line),
2060                                       s, errno));
2061   printCodePoint ();
2062   llflush ();
2063 # endif
2064 # else
2065   cstring_free (s);
2066 # endif
2067 }
2068
2069 void llflush (void)
2070 {
2071   (void) fflush (g_warningstream);
2072   (void) fflush (g_messagestream);
2073 }
2074
2075 void displayScan (cstring msg)
2076 {
2077   if (s_scanOpen)
2078     {
2079       displayScanClose ();
2080     }
2081
2082   llassert (!s_scanOpen);
2083
2084   if (context_getFlag (FLG_SHOWSCAN))
2085     {
2086       showHerald ();
2087       fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
2088       (void) fflush (g_messagestream);
2089     }
2090
2091   cstring_free (msg);
2092 }
2093
2094 void displayScanOpen (cstring msg)
2095 {
2096   if (s_scanOpen)
2097     {
2098       displayScanClose ();
2099     }
2100
2101   llassert (!s_scanOpen);
2102   s_scanOpen = TRUE;
2103
2104   if (context_getFlag (FLG_SHOWSCAN))
2105     {
2106       fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
2107       (void) fflush (g_messagestream);
2108     }
2109
2110   cstring_free (msg);
2111 }
2112
2113 void displayScanContinue (/*@temp@*/ cstring msg)
2114 {
2115   if (context_getFlag (FLG_SHOWSCAN))
2116     {
2117       if (s_scanOpen) 
2118         {
2119           fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
2120           (void) fflush (g_messagestream);
2121         }
2122       else
2123         {
2124           /*
2125           ** Don't call bug recursively
2126           */
2127
2128           fprintf (stderr, "*** Bug: scan continue scan not open\n");
2129         }
2130     }
2131 }
2132
2133 void displayScanClose (void)
2134 {
2135   if (s_scanOpen)
2136     {
2137       if (context_getFlag (FLG_SHOWSCAN))
2138         {
2139           fprintf (g_messagestream, " >\n");
2140           (void) fflush (g_messagestream);
2141         }
2142     }
2143   else
2144     {
2145       /*
2146       ** Don't call bug recursively
2147       */
2148       
2149       fprintf (stderr, "*** Bug: scan close scan not open\n");
2150     }
2151   
2152   s_scanOpen = FALSE;
2153 }
2154
2155
This page took 0.190473 seconds and 3 git commands to generate.