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