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