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