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