]> andersk Git - splint.git/blob - src/llerror.c
Fixed bug in usymtab clearing derived sRefs when exiting scope.
[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   /*
1408   ** This is confusing, and hardly ever useful.
1409
1410   if (errno != 0)
1411     {
1412       perror ("Possible system error diagnostic: ");
1413     }
1414
1415   **
1416   */
1417
1418   printBugReport ();
1419   llflush ();
1420
1421   numbugs++;
1422
1423   if (numbugs > context_getBugsLimit () && fileloc_withinLines (lastbug, g_currentloc, 2))
1424     {
1425       llfatalerror
1426         (message ("%q: Cannot recover from last bug. "
1427                   "(If you really want Splint to try to continue, use -bugslimit <n>.)",
1428                   fileloc_unparse (g_currentloc)));
1429     }
1430   
1431   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1432   fileloc_free (lastbug);
1433   lastbug = fileloc_copy (g_currentloc);
1434   closeMessage ();
1435   inbug = FALSE;
1436 }
1437
1438 # ifndef NOLCL
1439 void
1440 lclbug (/*@only@*/ cstring s)
1441 {
1442   prepareMessage ();
1443   printError (g_errorstream, message ("*** Internal Bug: %q", s));
1444   printCodePoint ();
1445   printBugReport ();
1446   fprintf (g_errorstream, "       (attempting to continue, results may be incorrect)\n");
1447   closeMessage ();
1448 }
1449 # endif
1450
1451 void
1452 llfatalerror (cstring s)
1453 {
1454   prepareMessage ();
1455   printError (g_errorstream, s);
1456   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1457   llexit (LLFAILURE);
1458 }
1459
1460 void
1461 llfatalerrorLoc (/*@only@*/ cstring s)
1462 {
1463   prepareMessage ();
1464   (void) fflush (g_warningstream);
1465   printError (g_errorstream, message ("%q: %q", fileloc_unparse (g_currentloc), s));
1466   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue."));
1467   (void) fflush (g_warningstream);
1468   llexit (LLFAILURE);
1469 }
1470
1471 # ifndef NOLCL
1472 bool
1473 lclHadError (void)
1474 {
1475   return (lclerrors > 0);
1476 }
1477
1478 bool
1479 lclHadNewError (void)
1480 {
1481   static int lastcall = 0;
1482
1483   if (lclerrors > lastcall)
1484     {
1485       lastcall = lclerrors;
1486       return TRUE;
1487     }
1488   else
1489     {
1490       return FALSE;
1491     }
1492 }
1493
1494 int
1495 lclNumberErrors (void)
1496 {
1497   return (lclerrors);
1498 }
1499
1500 void
1501 xlclerror (char *srcFile, int srcLine, ltoken t, /*@only@*/ cstring msg)
1502 {
1503   lclerrors++;
1504
1505   if (ltoken_getCode (t) != NOTTOKEN)
1506     {
1507       cstring loc = ltoken_unparseLoc (t);
1508       lastfileloclen = cstring_length (loc);
1509
1510       printError (g_warningstream, message ("%q: %q", loc, msg));
1511       showSourceLoc (srcFile, srcLine);
1512     }
1513   else
1514     {
1515       printError (g_warningstream, msg);
1516       showSourceLoc (srcFile, srcLine);
1517     }
1518 }
1519
1520 void
1521 lclplainerror (/*@only@*/ cstring msg)
1522 {
1523   lclerrors++;
1524   printError (g_warningstream, msg);
1525 }
1526
1527 void
1528 lclfatalerror (ltoken t, /*@only@*/ cstring msg)
1529 {
1530   if (ltoken_getCode (t) != NOTTOKEN)
1531     {
1532       cstring loc = ltoken_unparseLoc (t);
1533       lastfileloclen = cstring_length (loc);
1534       printError (g_errorstream, message ("%q: %q", loc, msg));
1535     }
1536   else
1537     {
1538       printError (g_errorstream, msg);
1539     }
1540
1541   printError (g_errorstream, cstring_makeLiteral ("*** Cannot continue"));
1542   llexit (LLFAILURE);
1543 }
1544
1545 void
1546 lclplainfatalerror (/*@only@*/ cstring msg)
1547 {
1548   (void) fflush (g_warningstream);
1549   printError (g_errorstream, message ("*** Cannot continue: %q", msg));
1550   llexit (LLFAILURE);
1551 }
1552
1553 void
1554 lclRedeclarationError (ltoken id)
1555 {
1556   cstring s = ltoken_getRawString (id);
1557
1558
1559   if (usymtab_existsEither (s))
1560     {
1561       uentry le = usymtab_lookupEither (s);
1562
1563       lclerror (id, message ("Respecification of %s", s));
1564       llgenindentmsg (message ("Previous specification of %q",
1565                                uentry_getName (le)),
1566                 uentry_whereSpecified (le));
1567     }
1568   else
1569     {
1570       lclerror (id, message ("Identifier redeclared: %s", s));
1571     }
1572 }
1573 # endif
1574
1575 void genppllerror (flagcode code, /*@only@*/ cstring s)
1576 {
1577   if (context_inSuppressZone (g_currentloc))
1578     {
1579       cstring_free (s);
1580     }
1581   else
1582     {
1583       if (context_getFlag (code))
1584         {
1585           if (!context_isInCommandLine ())
1586             {
1587               displayScanClose ();
1588             }
1589
1590           llerror (code, s);
1591
1592           if (code != FLG_PREPROC)
1593             {
1594               llsuppresshint ('-', code);
1595             }
1596
1597           if (!context_isInCommandLine ())
1598             {
1599               displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1600             }
1601         }
1602       else
1603         {
1604           cstring_free (s);
1605         }
1606     }
1607 }
1608
1609 void genppllerrorhint (flagcode code, /*@only@*/ cstring s,
1610                        /*@only@*/ cstring hint)
1611 {
1612   if (context_inSuppressZone (g_currentloc))
1613     {
1614       cstring_free (s);
1615       cstring_free (hint);
1616     }
1617   else
1618     {
1619       if (context_getFlag (code))
1620         {
1621           prepareMessage ();
1622           context_clearPreprocessing ();
1623           llerror (code, s);
1624           llgenhint (hint);
1625           context_setPreprocessing ();
1626           closeMessage ();
1627         }
1628       else
1629         {
1630           cstring_free (s);
1631           cstring_free (hint);
1632         }
1633     }
1634 }
1635
1636 void ppllerror (/*@only@*/ cstring s)
1637 {
1638   genppllerror (FLG_PREPROC, s);
1639 }
1640
1641 void pplldiagmsg (cstring s)
1642 {
1643   if (!context_isInCommandLine ())
1644     {
1645       displayScanClose ();
1646       lldiagmsg (s);
1647       displayScanOpen (cstring_makeLiteral ("< more preprocessing ."));
1648     }
1649   else
1650     {
1651       lldiagmsg (s);
1652     }
1653 }
1654
1655 void loadllmsg (cstring s)
1656 {
1657   displayScanClose ();
1658   lldiagmsg (s);
1659   displayScanOpen (cstring_makeLiteral ("< ."));
1660 }
1661
1662 static void llreportparseerror (/*@only@*/ cstring s)
1663 {
1664   if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
1665     {
1666       cstring_free (s);
1667     }
1668   else
1669     {
1670       llerror (FLG_SYNTAX, s);
1671
1672       fileloc_free (lastparseerror);
1673       lastparseerror = fileloc_copy (g_currentloc);
1674     }
1675 }
1676
1677 bool xcppoptgenerror (char *srcFile, int srcLine,
1678                       flagcode o,
1679                       /*@only@*/ cstring s,
1680                       cppReader *pfile)
1681 {
1682   bool res = FALSE;
1683   fileloc loc = cppReader_getLoc (pfile);
1684
1685   if (context_flagOn (o, loc))
1686     {
1687       if (xlloptgenerror (srcFile, srcLine, o, s, loc))
1688         {
1689           cppReader_printContainingFiles (pfile);
1690           res = TRUE;
1691         }
1692     }
1693   else
1694     {
1695       cstring_free (s);
1696     }
1697
1698   fileloc_free (loc);
1699
1700   return res;
1701 }
1702
1703 bool xlloptgenerror (char *srcFile, int srcLine, 
1704                      flagcode o, /*@only@*/ cstring s, fileloc loc)
1705 {
1706   DPRINTF (("xllopt: %s", s));
1707
1708   if (llrealerror (srcFile, srcLine, s, loc))
1709     {
1710       DPRINTF (("Here we are!"));
1711       llsuppresshint ('-', o);
1712       closeMessage ();
1713       flagcode_recordError (o);
1714       return TRUE;
1715     }
1716   else
1717     {
1718       DPRINTF (("Suppressed!"));
1719       flagcode_recordSuppressed (o);
1720       return FALSE;
1721     }
1722 }
1723
1724 bool xoptgenerror2 (char *srcFile, int srcLine,
1725                     flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1726 {
1727   if (context_suppressFlagMsg (f1, loc))
1728     {
1729       flagcode_recordSuppressed (f1);
1730       cstring_free (s);
1731     }
1732   else
1733     {
1734       if (context_suppressFlagMsg (f2, loc))
1735         {
1736           flagcode_recordSuppressed (f2);
1737           cstring_free (s);
1738         }
1739       else
1740         {
1741           if (llrealerror (srcFile, srcLine, s, loc))
1742             {
1743               llsuppresshint2 ('-', f1, f2);
1744               flagcode_recordError (f2);
1745               closeMessage ();
1746               return TRUE;
1747             }
1748           else
1749             {
1750               flagcode_recordSuppressed (f2);
1751             }
1752         }
1753     }
1754
1755   return FALSE;
1756 }
1757
1758 bool xoptgenerror2n (char *srcFile, int srcLine,
1759                      flagcode f1, flagcode f2, /*@only@*/ cstring s, fileloc loc)
1760 {
1761
1762   if (context_suppressFlagMsg (f1, loc))
1763     {
1764       flagcode_recordSuppressed (f1);
1765       cstring_free (s);
1766     }
1767   else
1768     {
1769       if (context_suppressNotFlagMsg (f2, loc))
1770         {
1771           flagcode_recordSuppressed (f2);
1772           cstring_free (s);
1773         }
1774       else
1775         {
1776           if (llrealerror (srcFile, srcLine, s, loc))
1777             {
1778               llsuppresshint ('+', f2);
1779               flagcode_recordError (f2);
1780               closeMessage ();
1781               return TRUE;
1782             }
1783
1784           flagcode_recordSuppressed (f2);
1785         }
1786     }
1787   return FALSE;
1788 }
1789
1790 bool xllnoptgenerror (char *srcFile, int srcLine,
1791                       flagcode o, /*@only@*/ cstring s, fileloc loc)
1792 {
1793   if (llrealerror (srcFile, srcLine, s, loc))
1794     {
1795       llsuppresshint ('+', o);
1796       flagcode_recordError (o);
1797       closeMessage ();
1798       return TRUE;
1799     }
1800
1801   flagcode_recordSuppressed (o);
1802   return FALSE;
1803 }
1804
1805 void llparseerror (cstring s)
1806 {
1807   if (context_getFlag (FLG_TRYTORECOVER))
1808     {
1809       parseerrorcount++;
1810
1811       if (parseerrorcount > GIVEUPPARSE)
1812         {
1813           if (cstring_isDefined (s))
1814             {
1815               llfatalerror (message ("%q: Parse Error: %q.  "
1816                                      "Too many errors, giving up.",
1817                                      fileloc_unparse (g_currentloc), s));
1818             }
1819           else
1820             {
1821               llfatalerror (message ("%q: Parse Error.  Too many errors, giving up.",
1822                                      fileloc_unparse (g_currentloc)));
1823             }
1824         }
1825       else
1826         {
1827           if (cstring_isDefined (s))
1828             {
1829               llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
1830                                            s));
1831             }
1832           else
1833             {
1834               llreportparseerror (message ("Parse Error. Attempting to continue."));
1835             }
1836         }
1837     }
1838   else
1839     {
1840       cstring msg;
1841
1842       if (cstring_isDefined (s))
1843         {
1844           msg = message ("Parse Error: %q.", s);
1845         }
1846       else
1847         {
1848           msg = message ("Parse Error.");
1849         }
1850
1851       llfatalerror
1852         (message ("%q: %s (For help on parse errors, "
1853                   "see splint -help parseerrors.)",
1854                   fileloc_unparse (g_currentloc), msg));
1855     }
1856 }
1857
1858 bool xfsgenerror (char *srcFile, int srcLine,
1859                    flagSpec fs, /*@only@*/ cstring s, fileloc fl) 
1860 {
1861   if (flagSpec_isOn (fs, fl))
1862     {
1863       if (llgenerroraux (srcFile, srcLine, s, fl, TRUE, FALSE))
1864         {
1865           llsuppresshint ('-', flagSpec_getFirstOn (fs, fl));
1866           flagcode_recordError (flagSpec_getFirstOn (fs, fl));
1867           return TRUE;
1868         }
1869       else
1870         {
1871           flagcode_recordSuppressed (flagSpec_getFirstOn (fs, fl));
1872           return FALSE;
1873         }
1874     }
1875   else
1876     {
1877       flagcode_recordSuppressed (flagSpec_getDominant (fs));
1878       cstring_free (s);
1879       return FALSE;
1880     }
1881 }
1882
1883 bool doCheck (bool x, cstring pred, cstring file, int line)
1884 {
1885   if (!x) {
1886     llbug (message ("%q: Check Failed: %s",
1887                     fileloc_unparseRaw (file, line),
1888                     pred));
1889   }
1890
1891   return x;
1892 }
1893
1894 /*@observer@*/ cstring lldecodeerror (/*@unused@*/ int errnum)
1895 {
1896   char *result;
1897
1898 #ifndef VMS
1899 #ifndef HAVE_STRERROR
1900   result = NULL;
1901 #else
1902   result = strerror (errnum);
1903 #endif
1904 #else   /* VMS */
1905   /* VAXCRTL's strerror() takes an optional second argument, which only
1906      matters when the first argument is EVMSERR.  However, it's simplest
1907      just to pass it unconditionally.  `vaxc$errno' is declared in
1908      <errno.h>, and maintained by the library in parallel with `errno'.
1909      We assume that caller's `errnum' either matches the last setting of
1910      `errno' by the library or else does not have the value `EVMSERR'.  */
1911
1912   result = strerror (errnum, vaxc$errno);
1913 #endif
1914
1915   if (result == NULL)
1916     {
1917       result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
1918     }
1919
1920   return cstring_fromChars (result);
1921 }
1922
1923 void llquietbugaux (cstring s, /*@unused@*/ cstring file, /*@unused@*/ int line)
1924 {
1925 # if 0
1926 # ifdef HOMEVERSION
1927   llflush ();
1928   printError (g_errorstream, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
1929                                       fileloc_unparse (g_currentloc),
1930                                       fileloc_unparseRaw (file, line),
1931                                       s, errno));
1932   printCodePoint ();
1933   llflush ();
1934 # endif
1935 # else
1936   cstring_free (s);
1937 # endif
1938 }
1939
1940 void llflush (void)
1941 {
1942   (void) fflush (g_warningstream);
1943   (void) fflush (g_messagestream);
1944 }
1945
1946 static bool s_scanOpen = FALSE;
1947
1948 void displayScan (cstring msg)
1949 {
1950   llassert (!s_scanOpen);
1951
1952   if (context_getFlag (FLG_SHOWSCAN))
1953     {
1954       fprintf (g_messagestream, "< %s >\n", cstring_toCharsSafe (msg));
1955       (void) fflush (g_messagestream);
1956     }
1957
1958   cstring_free (msg);
1959 }
1960
1961 void displayScanOpen (cstring msg)
1962 {
1963   llassert (!s_scanOpen);
1964   s_scanOpen = TRUE;
1965
1966   if (context_getFlag (FLG_SHOWSCAN))
1967     {
1968       fprintf (g_messagestream, "< %s", cstring_toCharsSafe (msg));
1969       (void) fflush (g_messagestream);
1970     }
1971
1972   cstring_free (msg);
1973 }
1974
1975 void displayScanContinue (/*@temp@*/ cstring msg)
1976 {
1977   if (context_getFlag (FLG_SHOWSCAN))
1978     {
1979       if (s_scanOpen) 
1980         {
1981           fprintf (g_messagestream, "%s", cstring_toCharsSafe (msg));
1982           (void) fflush (g_messagestream);
1983         }
1984       else
1985         {
1986           /*
1987           ** Don't call bug recursively
1988           */
1989
1990           fprintf (stderr, "*** Bug: scan continue scan not open\n");
1991         }
1992     }
1993 }
1994
1995 void displayScanClose (void)
1996 {
1997   if (s_scanOpen)
1998     {
1999       if (context_getFlag (FLG_SHOWSCAN))
2000         {
2001           fprintf (g_messagestream, " >\n");
2002           (void) fflush (g_messagestream);
2003         }
2004     }
2005   else
2006     {
2007       /*
2008       ** Don't call bug recursively
2009       */
2010       
2011       fprintf (stderr, "*** Bug: scan close scan not open\n");
2012     }
2013   
2014   s_scanOpen = FALSE;
2015 }
2016
2017
This page took 0.235241 seconds and 5 git commands to generate.