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