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