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