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