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