00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 # include "lclintMacros.nf"
00031 # include <string.h>
00032 # include <errno.h>
00033 # include "llbasic.h"
00034 # include "llmain.h"
00035 # include "version.h"
00036
00037 static void printIndentMessage (FILE *p_stream, cstring p_sc, int p_indent)
00038 ;
00039
00040 # ifndef NOLCL
00041 static int lclerrors = 0;
00042 # endif
00043
00044 static int lastfileloclen = 10;
00045 static cstring lastmsg = cstring_undefined;
00046 static int mcount = 0;
00047 static cstring saveOneMessage = cstring_undefined;
00048 static fileloc lastparseerror = fileloc_undefined;
00049 static fileloc lastbug = fileloc_undefined;
00050 static bool llgenerrorreal ( cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
00051 ;
00052 static bool llgenerroraux ( cstring p_s, fileloc p_fl, bool p_iserror, bool p_indent)
00053 ;
00054 static void printError (FILE *p_stream, cstring p_sc)
00055
00056 ;
00057 static void printMessage (FILE *p_stream, cstring p_s)
00058 ;
00059
00060 static char *
00061 maxcp ( char *a, char *b)
00062 {
00063 if (a > b) return a;
00064 else return b;
00065 }
00066
00067 static void
00068 printBugReport (void)
00069 {
00070 fprintf (stderr, " *** Please report bug to %s ***\n",
00071 LCLINT_MAINTAINER);
00072 llflush ();
00073
00074 }
00075
00076 static bool s_needsPrepare = TRUE;
00077
00078 void prepareMessage (void)
00079 {
00080 if (context_isPreprocessing ()
00081 && s_needsPrepare
00082 && context_getDebug (FLG_SHOWSCAN))
00083 {
00084 llflush ();
00085 fprintf (stderr, " >\n");
00086 s_needsPrepare = FALSE;
00087 }
00088
00089 llflush ();
00090 }
00091
00092 void closeMessage (void)
00093 {
00094 if (context_isPreprocessing ()
00095 && context_getDebug (FLG_SHOWSCAN))
00096 {
00097 llflush ();
00098 fprintf (stderr, "< more preprocessing .");
00099
00100 llassert (!s_needsPrepare);
00101 s_needsPrepare = TRUE;
00102 }
00103 else
00104 {
00105 llflush ();
00106 }
00107 }
00108
00109 void
00110 llmsg ( cstring s)
00111 {
00112 context_setNeednl ();
00113 prepareMessage ();
00114 printMessage (g_msgstream, s);
00115 closeMessage ();
00116 }
00117
00118 void
00119 lldiagmsg ( cstring s)
00120 {
00121 context_setNeednl ();
00122 prepareMessage ();
00123 printMessage (stderr, s);
00124 closeMessage ();
00125 }
00126
00127 void
00128 llmsgplain ( cstring s)
00129 {
00130 context_setNeednl ();
00131 prepareMessage ();
00132 printMessage (g_msgstream, s);
00133 closeMessage ();
00134 }
00135
00136 void flagWarning (cstring s)
00137 {
00138 if (context_getFlag (FLG_WARNFLAGS))
00139 {
00140 showHerald ();
00141
00142 if (fileloc_isBuiltin (g_currentloc))
00143 {
00144 llmsg (message ("Warning: %s", s));
00145 }
00146 else
00147 {
00148 llgenmsg (message ("Warning: %s", s), g_currentloc);
00149 }
00150 }
00151 }
00152
00153 static void
00154 llgenhint ( cstring s)
00155 {
00156 context_setNeednl ();
00157 printIndentMessage (g_msgstream, s, 2);
00158 }
00159
00160 void
00161 llhint (cstring s)
00162 {
00163 if (context_getFlag (FLG_HINTS) &&
00164 !(context_inSuppressRegion () || context_inSuppressZone (g_currentloc)))
00165 {
00166 llgenhint (s);
00167 }
00168 else
00169 {
00170 cstring_free (s);
00171 }
00172 }
00173
00174 static void
00175 llshowhint (flagcode f)
00176 {
00177 if (context_getFlag (FLG_HINTS))
00178 {
00179 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
00180 {
00181 cstring desc = flagcodeHint (f);
00182
00183 if (cstring_isDefined (desc))
00184 {
00185 llgenhint (cstring_copy (desc));
00186 }
00187 }
00188 }
00189 }
00190
00191
00192 static void
00193 llsuppresshint (char c, flagcode f)
00194 {
00195
00196 if (context_getFlag (FLG_HINTS))
00197 {
00198 if ((flagcode_numReported (f) == 0) || context_getFlag (FLG_FORCEHINTS))
00199 {
00200 cstring desc = flagcodeHint (f);
00201 context_setNeednl ();
00202 lastfileloclen = 8;
00203
00204 if (flagcode_isNamePrefixFlag (f))
00205 {
00206 f = FLG_NAMECHECKS;
00207 }
00208
00209 if (cstring_isDefined (desc))
00210 {
00211 llgenhint (message ("%s (%h%s will suppress message)", desc, c,
00212 flagcode_name (f)));
00213 }
00214 else
00215 {
00216 llgenhint (message ("(%h%s will suppress message)", c,
00217 flagcode_name (f)));
00218 }
00219 }
00220 }
00221 }
00222
00223 static void
00224 llnosuppresshint (flagcode f)
00225 {
00226
00227 if (context_getFlag (FLG_FORCEHINTS))
00228 {
00229 cstring desc = flagcodeHint (f);
00230 context_setNeednl ();
00231 lastfileloclen = 8;
00232
00233 if (cstring_isDefined (desc))
00234 {
00235 printError (g_msgstream, message (" %s", desc));
00236 }
00237 }
00238 }
00239
00240
00241 # define MAXSEARCH 20
00242
00243
00244 # define MINLINE 35
00245
00246 typedef char *nd_charp;
00247
00248 static void
00249 mstring_split ( char **sp,
00250 nd_charp *tp,
00251 int maxline, int *indentchars)
00252 {
00253 char *nl;
00254 char *t;
00255 char *s = *sp;
00256
00257 *tp = NULL;
00258
00259 if (maxline < MINLINELEN)
00260 {
00261 maxline = MINLINELEN;
00262 }
00263
00264 if (*indentchars > 0)
00265 {
00266 s = *sp = mstring_concatFree1 (mstring_spaces (*indentchars), s);
00267 }
00268
00269 nl = strchr (s, '\n');
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 if ((nl != NULL) && ((nl - s) < maxline))
00288 {
00289 *nl = '\0';
00290 t = nl + 1;
00291
00292 if (*t == '\0')
00293 {
00294 return;
00295 }
00296
00297 if (*t >= '\1' && *t <= '\7')
00298 {
00299 *indentchars += (int) (*t - '\1') + 1;
00300 t++;
00301 }
00302
00303 *tp = t;
00304 return;
00305 }
00306 else if (size_toInt (strlen (s)) < maxline)
00307 {
00308 return;
00309 }
00310 else
00311 {
00312 int i = 0;
00313 char savechar;
00314 char *lcolon, *lsemi, *splitat;
00315
00316 splitat = NULL;
00317
00318 t = s + maxline - 1;
00319 savechar = *t;
00320
00321 *t = '\0';
00322 lcolon = strrchr (s, ':');
00323 lsemi = strrchr (s, ';');
00324 *t = savechar;
00325
00326 splitat = maxcp (lcolon, lsemi);
00327
00328 if (splitat != NULL && ((int)(splitat - s) > MINLINE)
00329 && *(splitat + 1) == ' ' && *(splitat + 2) != '}')
00330 {
00331 *(splitat + 1) = '\0';
00332 t = splitat + 2;
00333 *tp = t;
00334 return;
00335 }
00336
00337 while (*t != ' ' && *t != '\t' && i < MAXSEARCH)
00338 {
00339 t--;
00340 i++;
00341 }
00342
00343 if (*t != ' ' && *t != '\t')
00344 {
00345 t = mstring_copy (s + maxline);
00346 *(s + maxline) = '\0';
00347
00348 if (*t == '\0')
00349 {
00350 sfree (t);
00351 return;
00352 }
00353
00354 mstring_markFree (t);
00355 *tp = t;
00356 return;
00357 }
00358 else
00359 {
00360 *t = '\0';
00361 t++;
00362
00363 if (*t == '\0') return;
00364
00365
00366
00367
00368
00369 *tp = t;
00370 return;
00371 }
00372 }
00373 }
00374
00375 static
00376 void limitmessage ( cstring s, fileloc loc)
00377 {
00378 if (mcount > context_getLimit () + 1)
00379 {
00380 cstring_free (s);
00381 }
00382 else
00383 {
00384 cstring flstring = fileloc_unparse (loc);
00385
00386 lastfileloclen = cstring_length (flstring);
00387 cstring_free (saveOneMessage);
00388 saveOneMessage = message ("%q: %q", flstring, s);
00389 }
00390 }
00391
00392 static int parseerrorcount = 0;
00393
00394 void cleanupMessages ()
00395 {
00396 parseerrorcount = 0;
00397
00398 if (context_unlimitedMessages ())
00399 {
00400 ;
00401 }
00402 else
00403 {
00404 int unprinted = mcount - context_getLimit ();
00405
00406 if (unprinted > 0)
00407 {
00408 if (unprinted == 1 && cstring_isDefined (saveOneMessage))
00409 {
00410 prepareMessage ();
00411 printError (g_msgstream, saveOneMessage);
00412 closeMessage ();
00413 saveOneMessage = cstring_undefined;
00414 }
00415 else
00416 {
00417 if (cstring_isDefined (saveOneMessage))
00418 {
00419
00420 saveOneMessage = cstring_undefined;
00421 }
00422
00423 fprintf (g_msgstream, "%s: (%d more similar errors unprinted)\n",
00424 cstring_toCharsSafe (fileloc_filename (g_currentloc)),
00425 mcount - context_getLimit ());
00426 }
00427 }
00428 }
00429
00430 mcount = 0;
00431 }
00432
00433 void
00434 llgenmsg ( cstring s, fileloc fl)
00435 {
00436 cstring flstring = fileloc_unparse (fl);
00437 lastfileloclen = cstring_length (flstring);
00438
00439 prepareMessage ();
00440 (void) printError (g_msgstream, message ("%q: %q", flstring, s));
00441 closeMessage ();
00442 }
00443
00444 void
00445 llgenindentmsg ( cstring s, fileloc fl)
00446 {
00447 cstring flstring = fileloc_unparse (fl);
00448
00449 prepareMessage ();
00450 (void) printIndentMessage (g_msgstream, message ("%q: %q", flstring, s), 3);
00451 closeMessage ();
00452 }
00453
00454 void
00455 llgenindentmsgnoloc ( cstring s)
00456 {
00457 prepareMessage ();
00458 (void) printIndentMessage (g_msgstream, s, 3);
00459 closeMessage ();
00460 }
00461
00462 static bool
00463 llgentypeerroraux (flagcode ocode, ctype t1, exprNode e1, ctype t2, exprNode e2,
00464 cstring s, fileloc fl)
00465 {
00466 cstring hint = cstring_undefined;
00467 flagcode code = ocode;
00468 flagcode hcode = INVALID_FLAG;
00469 ctype ut1 = t1;
00470 ctype ut2 = t2;
00471
00472 DPRINTF (("Type error: %s / %s : %s / %s",
00473 exprNode_unparse (e1), exprNode_unparse (e2),
00474 ctype_unparse (t1), ctype_unparse (t2)));
00475
00476 DPRINTF (("Bool: %s / %s",
00477 bool_unparse (ctype_isBool (t1)),
00478 bool_unparse (ctype_isBool (t2))));
00479
00480
00481
00482
00483
00484 while (ctype_isPointer (ut1) && ctype_isPointer (ut2)) {
00485 ut1 = ctype_baseArrayPtr (ut1);
00486 ut2 = ctype_baseArrayPtr (ut2);
00487 }
00488
00489 if ((ctype_isFloat (ut1) && ctype_isDouble (ut2))
00490 || (ctype_isFloat (ut1) && ctype_isDouble (ut2)))
00491 {
00492 hcode = FLG_FLOATDOUBLE;
00493 }
00494 else if ((exprNode_isCharLit (e1) && ctype_isInt (ut2))
00495 || (exprNode_isCharLit (e2) && ctype_isInt (ut1)))
00496 {
00497 hcode = FLG_CHARINTLITERAL;
00498 }
00499 else if ((exprNode_isNumLit (e1) && ctype_isReal (ut2))
00500 || (exprNode_isNumLit (e2) && ctype_isReal (ut1)))
00501 {
00502 hcode = FLG_NUMLITERAL;
00503 }
00504 else if ((ctype_isManifestBool (ut1) && ctype_isInt (ut2))
00505 || (ctype_isInt (ut1) && ctype_isManifestBool (ut2)))
00506
00507 {
00508 hcode = FLG_BOOLINT;
00509 }
00510 else if (((ctype_isChar (ut1) && !ctype_isInt (ut1)) && ctype_isInt (ut2))
00511 || ((ctype_isInt (ut1) && (ctype_isChar (ut2) && !ctype_isInt (ut2)))))
00512 {
00513 hcode = FLG_CHARINT;
00514 }
00515 else if ((ctype_isInt (ut1) && ctype_isInt (ut2))
00516 || (ctype_isChar (ut1) && ctype_isChar (ut2))
00517 || (ctype_isDouble (ut1) && ctype_isDouble (ut2)))
00518 {
00519 if (!bool_equal (ctype_isSigned (ut1), ctype_isSigned (ut2)))
00520 {
00521 hcode = FLG_IGNORESIGNS;
00522 }
00523 else
00524 {
00525 hcode = FLG_IGNOREQUALS;
00526 }
00527 }
00528 else if (ctype_isArbitraryIntegral (ctype_realType (ut1)))
00529 {
00530 if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
00531 {
00532 hcode = FLG_MATCHANYINTEGRAL;
00533 }
00534 else if (ctype_match (ut2, ctype_ulint))
00535 {
00536 hcode = FLG_LONGUNSIGNEDINTEGRAL;
00537 }
00538 else if (ctype_match (ut2, ctype_lint))
00539 {
00540 hcode = FLG_LONGINTEGRAL;
00541 }
00542 else if (ctype_isInt (ut2))
00543 {
00544 hcode = FLG_MATCHANYINTEGRAL;
00545 }
00546 else
00547 {
00548 ;
00549 }
00550 }
00551 else if (ctype_isArbitraryIntegral (ctype_realType (ut2)))
00552 {
00553 ctype tr = ctype_realType (ut1);
00554
00555 if (ctype_isArbitraryIntegral (tr))
00556 {
00557 hcode = FLG_MATCHANYINTEGRAL;
00558 }
00559 else if (ctype_match (ut1, ctype_ulint))
00560 {
00561 if (ctype_isUnsignedIntegral (tr))
00562 {
00563 hcode = FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL;
00564 }
00565 else if (ctype_isSignedIntegral (tr))
00566 {
00567 ;
00568 }
00569 else
00570 {
00571 hcode = FLG_LONGUNSIGNEDINTEGRAL;
00572 }
00573 }
00574 else if (ctype_match (ut1, ctype_lint))
00575 {
00576 if (ctype_isSignedIntegral (tr))
00577 {
00578 hcode = FLG_LONGSIGNEDINTEGRAL;
00579 }
00580 else if (ctype_isSignedIntegral (tr))
00581 {
00582 ;
00583 }
00584 else
00585 {
00586 hcode = FLG_LONGINTEGRAL;
00587 }
00588 }
00589 else if (ctype_isInt (ut1))
00590 {
00591 hcode = FLG_MATCHANYINTEGRAL;
00592 }
00593 else
00594 {
00595 ;
00596 }
00597 }
00598 else if (ctype_isAbstract (ut1) && !ctype_isAbstract (ut2))
00599 {
00600 uentry ue1 = usymtab_getTypeEntry (ctype_typeId (ut1));
00601 ctype ct = uentry_getType (ue1);
00602
00603 if (ctype_match (ct, ut2))
00604 {
00605 code = FLG_ABSTRACT;
00606 hint = message ("Underlying types match, but %s is an "
00607 "abstract type that is not accessible here.",
00608 ctype_unparse (t1));
00609 }
00610 }
00611 else if (ctype_isAbstract (ut2) && !ctype_isAbstract (ut1))
00612 {
00613 uentry ue = usymtab_getTypeEntry (ctype_typeId (ut2));
00614 ctype ct = uentry_getType (ue);
00615
00616 if (ctype_match (ct, ut1))
00617 {
00618 code = FLG_ABSTRACT;
00619 hint = message ("Underlying types match, but %s is an "
00620 "abstract type that is not accessible here.",
00621 ctype_unparse (t2));
00622 }
00623 }
00624 else if ((ctype_isEnum (ut1) && ctype_isArbitraryIntegral (ut2))
00625 || (ctype_isEnum (ut2) && ctype_isArbitraryIntegral (ut1)))
00626 {
00627 code = FLG_ENUMINT;
00628 }
00629 else if ((ctype_isEnum (ut1) && ctype_isArbitraryIntegral (ut2))
00630 || (ctype_isEnum (ut2) && ctype_isArbitraryIntegral (ut1)))
00631 {
00632 code = FLG_ENUMINT;
00633 }
00634 else if ((ctype_isSignedChar (ut1) && ctype_isUnsignedChar (ut2))
00635 || (ctype_isUnsignedChar (ut1) && ctype_isSignedChar (ut2)))
00636 {
00637 code = FLG_CHARUNSIGNEDCHAR;
00638 }
00639 else if (ctype_isNumeric (ut1) && ctype_isNumeric (ut2))
00640 {
00641 code = FLG_RELAXTYPES;
00642 }
00643 else
00644 {
00645 DPRINTF (("No special type rule: %s / %s", ctype_unparse (ut1),
00646 ctype_unparse (ut2)));
00647 }
00648
00649 if (cstring_isDefined (hint))
00650 {
00651 if (!context_suppressFlagMsg (ocode, fl))
00652 {
00653 return llgenhinterror (code, s, hint, fl);
00654 }
00655 else
00656 {
00657 cstring_free (s);
00658 cstring_free (hint);
00659 return FALSE;
00660 }
00661 }
00662 else
00663 {
00664 if (llgenerroraux (s, fl, TRUE, FALSE))
00665 {
00666 if (hcode != INVALID_FLAG && hcode != ocode)
00667 {
00668 code = hcode;
00669 llshowhint (code);
00670
00671 }
00672 else
00673 {
00674 llsuppresshint ('-', code);
00675 }
00676
00677 flagcode_recordError (code);
00678 return TRUE;
00679 }
00680
00681 return FALSE;
00682 }
00683 }
00684
00685 bool
00686 llgentypeerror (ctype t1, exprNode e1, ctype t2, exprNode e2,
00687 cstring s, fileloc fl)
00688 {
00689 return llgentypeerroraux (FLG_TYPE, t1, e1, t2, e2, s, fl);
00690 }
00691
00692 bool
00693 llgenformattypeerror (ctype t1, exprNode e1, ctype t2, exprNode e2,
00694 cstring s, fileloc fl)
00695 {
00696 return llgentypeerroraux (FLG_FORMATTYPE, t1, e1, t2, e2, s, fl);
00697 }
00698
00699 bool
00700 llgenerror (flagcode o, cstring s, fileloc fl)
00701 {
00702 if (llgenerroraux (s, fl, TRUE, FALSE))
00703 {
00704 llnosuppresshint (o);
00705 flagcode_recordError (o);
00706 closeMessage ();
00707 return TRUE;
00708 }
00709 else
00710 {
00711 flagcode_recordSuppressed (o);
00712 return FALSE;
00713 }
00714 }
00715
00716 bool
00717 llgenhinterror (flagcode o, cstring s, cstring hint,
00718 fileloc fl)
00719 {
00720 if (!context_suppressFlagMsg (o, fl))
00721 {
00722 if (llgenerroraux (s, fl, TRUE, FALSE))
00723 {
00724 flagcode_recordError (o);
00725
00726 if (context_getFlag (FLG_HINTS))
00727 {
00728 llgenhint (hint);
00729 }
00730 else
00731 {
00732 cstring_free (hint);
00733 }
00734
00735 closeMessage ();
00736 return TRUE;
00737 }
00738
00739 cstring_free (hint);
00740 }
00741 else
00742 {
00743 cstring_free (hint);
00744 cstring_free (s);
00745 }
00746
00747 flagcode_recordSuppressed (o);
00748 return FALSE;
00749 }
00750
00751 static bool
00752 llrealerror ( cstring s, fileloc fl)
00753 {
00754 return (llgenerrorreal (s, fl, TRUE, FALSE));
00755 }
00756
00757 static bool
00758 llgenerroraux ( cstring s, fileloc fl, bool iserror, bool indent)
00759 {
00760
00761 if (context_inSuppressZone (fl))
00762 {
00763 cstring_free (s);
00764 return FALSE;
00765 }
00766 else
00767 {
00768 ;
00769 }
00770
00771 return (llgenerrorreal (s, fl, iserror, indent));
00772 }
00773
00774 void
00775 llforceerror (flagcode code, cstring s, fileloc fl)
00776 {
00777 flagcode_recordError (code);
00778 (void) llgenerrorreal (s, fl, TRUE, FALSE);
00779 closeMessage ();
00780 }
00781
00782 static bool
00783 llgenerrorreal ( cstring s, fileloc fl, bool iserror, bool indent)
00784 {
00785 cstring flstring;
00786
00787
00788
00789 if (!messageLog_add (context_messageLog (), fl, s))
00790 {
00791 cstring_free (s);
00792 return FALSE;
00793 }
00794
00795 if (iserror) context_hasError ();
00796
00797 if (context_unlimitedMessages ())
00798 {
00799 ;
00800 }
00801 else
00802 {
00803
00804
00805
00806
00807
00808
00809 char *sc = cstring_toCharsSafe (s);
00810 char *tmpmsg = strchr (sc, ':');
00811
00812 if (tmpmsg == NULL)
00813 {
00814 tmpmsg = sc;
00815 }
00816 else
00817 {
00818 char *savechar = tmpmsg;
00819 *tmpmsg = '\0';
00820 tmpmsg = sc;
00821 *savechar = ':';
00822 }
00823
00824 if (cstring_equal (lastmsg, cstring_fromChars (tmpmsg)))
00825 {
00826 mcount++;
00827 if (mcount == (context_getLimit () + 1))
00828 {
00829 limitmessage (s, fl);
00830 return FALSE;
00831 }
00832
00833 if (mcount > (context_getLimit ()))
00834 {
00835 cstring_free (s);
00836 return FALSE;
00837 }
00838 }
00839 else
00840 {
00841 cleanupMessages ();
00842 mcount = 0;
00843 cstring_free (lastmsg);
00844 lastmsg = cstring_fromCharsNew (tmpmsg);
00845 }
00846 }
00847
00848 if (context_hasAliasAnnote ())
00849 {
00850 char *sc = cstring_toCharsSafe (s);
00851 char *fcolon = strchr (sc, ':');
00852 cstring a = context_getAliasAnnote ();
00853
00854
00855 if (fcolon == NULL)
00856 {
00857 s = message ("%q (%q)", s, a);
00858 }
00859 else
00860 {
00861 cstring afterColon;
00862
00863 *fcolon = '\0';
00864 afterColon = cstring_fromCharsNew (fcolon + 1);
00865
00866 s = message ("%q (%q):%q", s, a, afterColon);
00867 }
00868 }
00869
00870 if (context_hasMessageAnnote ())
00871 {
00872 char *fcolon = strchr (cstring_toCharsSafe (s), ':');
00873
00874
00875 if (fcolon == NULL)
00876 {
00877
00878 s = message ("%q (%q)", s, context_getMessageAnnote ());
00879
00880 }
00881 else
00882 {
00883 cstring afterColon;
00884
00885 *fcolon = '\0';
00886 afterColon = cstring_fromCharsNew (fcolon + 1);
00887
00888
00889 s = message ("%q (%q):%q", s,
00890 context_getMessageAnnote (), afterColon);
00891
00892 }
00893 }
00894
00895 context_setNeednl ();
00896 prepareMessage ();
00897
00898 if (context_showFunction ())
00899 {
00900 cstring fname = fileloc_unparseFilename (g_currentloc);
00901
00902 if (context_inIterDef ())
00903 {
00904 fprintf (g_msgstream, "%s: (in iter %s)\n",
00905 cstring_toCharsSafe (fname),
00906 cstring_toCharsSafe (context_inFunctionName ()));
00907 }
00908 else if (context_inIterEnd ())
00909 {
00910 fprintf (g_msgstream, "%s: (in iter finalizer %s)\n",
00911 cstring_toCharsSafe (fname),
00912 cstring_toCharsSafe (context_inFunctionName ()));
00913 }
00914 else if (context_inMacro ())
00915 {
00916 fprintf (g_msgstream, "%s: (in macro %s)\n", cstring_toCharsSafe (fname),
00917 cstring_toCharsSafe (context_inFunctionName ()));
00918 }
00919 else
00920 {
00921 fprintf (g_msgstream, "%s: (in function %s)\n",
00922 cstring_toCharsSafe (fname),
00923 cstring_toCharsSafe (context_inFunctionName ()));
00924 }
00925
00926 cstring_free (fname);
00927 context_setShownFunction ();
00928 }
00929
00930 flstring = fileloc_unparse (fl);
00931
00932 lastfileloclen = cstring_length (flstring);
00933
00934 if (indent)
00935 {
00936 printError (g_msgstream, message (" %q: %q", flstring, s));
00937 }
00938 else
00939 {
00940 printError (g_msgstream, message ("%q: %q", flstring, s));
00941 }
00942
00943 return TRUE;
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 static
00957 void printMessage (FILE *stream, cstring s)
00958 {
00959 printIndentMessage (stream, s, 0);
00960 }
00961
00962 static
00963 void printIndentMessage (FILE *stream, cstring sc, int indent)
00964 {
00965 int maxlen = context_getLineLen ();
00966 char *s = cstring_toCharsSafe (sc);
00967
00968
00969 do
00970 {
00971 char *t = NULL;
00972 char *st = s;
00973
00974 mstring_split (&st, &t, maxlen, &indent);
00975 fprintf (stream, "%s\n", st);
00976 llassert (t != s);
00977 s = t;
00978 } while (s != NULL) ;
00979
00980 cstring_free (sc);
00981 }
00982
00983 static
00984 void printError (FILE *stream, cstring sc)
00985 {
00986 int maxlen = context_getLineLen ();
00987 int nspaces = lastfileloclen + 5;
00988 int nextlen = maxlen - nspaces;
00989 int len = cstring_length (sc);
00990 int indent = 0;
00991 char *s = cstring_toCharsSafe (sc);
00992 char *os = s;
00993 char *t = NULL;
00994
00995 if (len < (maxlen + nextlen) && (strchr (s, '\n') == NULL))
00996 {
00997 mstring_split (&s, &t, maxlen, &indent);
00998
00999 fprintf (stream, "%s\n", s);
01000
01001 if (t != NULL)
01002 {
01003 len = mstring_length (t);
01004
01005 if (len < (maxlen - 3) && (strchr (t, '\n') == NULL)
01006 && len > (nextlen - 1))
01007 {
01008 fprintf (stream, " %s\n", t);
01009 }
01010 else
01011 {
01012 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
01013 int i;
01014
01015 for (i = 0; i < nspaces; i++)
01016 {
01017 spaces[i] = ' ';
01018 }
01019
01020 spaces[nspaces] = '\0';
01021
01022 while (t != NULL)
01023 {
01024 char *st = t;
01025 mstring_split (&st, &t, nextlen, &indent);
01026 fprintf (stream, "%s%s\n", spaces, st);
01027 }
01028
01029 sfree (spaces);
01030 }
01031 }
01032 }
01033 else
01034 {
01035 if (len < (maxlen + maxlen - 1) && (strchr (s, '\n') != NULL))
01036 {
01037 nspaces = ((maxlen + maxlen - 1) - len) / 2;
01038
01039 if (nspaces < 1) nspaces = 1;
01040
01041 nextlen = maxlen - nspaces;
01042
01043 mstring_split (&s, &t, maxlen, &indent);
01044
01045 fprintf (stream, "%s\n", s);
01046
01047 if (t != NULL)
01048 {
01049 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
01050 int i;
01051
01052 for (i = 0; i < nspaces; i++)
01053 {
01054 spaces[i] = ' ';
01055 }
01056
01057 spaces[nspaces] = '\0';
01058
01059 while (t != NULL)
01060 {
01061 char *st = t;
01062
01063 mstring_split (&st, &t, nextlen, &indent);
01064 fprintf (stream, "%s%s\n", spaces, st);
01065 }
01066
01067 sfree (spaces);
01068 }
01069 }
01070 else
01071 {
01072 nspaces = 4;
01073 nextlen = maxlen - nspaces;
01074
01075 mstring_split (&s, &t, maxlen, &indent);
01076
01077 fprintf (stream, "%s\n", s);
01078
01079 if (t != NULL)
01080 {
01081 char *spaces = (char *) dmalloc ((nspaces + 1) * sizeof (*spaces));
01082 int i;
01083
01084 for (i = 0; i < nspaces; i++)
01085 {
01086 spaces[i] = ' ';
01087 }
01088
01089 spaces[nspaces] = '\0';
01090
01091 while (t != NULL)
01092 {
01093 char *st = t;
01094 mstring_split (&st, &t, nextlen, &indent);
01095 fprintf (stream, "%s%s\n", spaces, st);
01096 }
01097
01098 sfree (spaces);
01099 }
01100 }
01101 }
01102
01103 sfree (os);
01104 }
01105
01106 void
01107 llfatalbug ( cstring s)
01108 {
01109 prepareMessage ();
01110 printError (stderr, message ("%q: *** Fatal bug: %q",
01111 fileloc_unparse (g_currentloc), s));
01112 printCodePoint ();
01113 printBugReport ();
01114 llexit (LLFAILURE);
01115 }
01116
01117 # ifndef NOLCL
01118 void
01119 lclfatalbug (char *msg)
01120 {
01121 prepareMessage ();
01122 printError (stderr,
01123 message ("*** Fatal Bug: %s", cstring_fromChars (msg)));
01124 printCodePoint ();
01125 printBugReport ();
01126 llexit (LLFAILURE);
01127 }
01128 # endif
01129
01130 void
01131 checkParseError (void)
01132 {
01133 if (fileloc_withinLines (lastparseerror, g_currentloc, 10))
01134 {
01135 llfatalerror (message ("%q: Cannot recover from parse error.",
01136 fileloc_unparse (g_currentloc)));
01137 }
01138 }
01139
01140 void llbugaux (cstring file, int line, cstring s)
01141 {
01142
01143 static int numbugs = 0;
01144 static bool inbug = FALSE;
01145
01146 if (inbug)
01147 {
01148 cstring temps = fileloc_unparseRaw (file, line);
01149
01150 fprintf (stderr, "%s: Recursive bug detected: %s\n",
01151 cstring_toCharsSafe (temps),
01152 cstring_toCharsSafe (s));
01153 cstring_free (temps);
01154
01155 llexit (LLFAILURE);
01156 }
01157
01158 inbug = TRUE;
01159
01160 prepareMessage ();
01161
01162 if (fileloc_isRealLib (g_currentloc))
01163 {
01164 llfatalerror (message ("%q: Library file appears to be corrupted. Error: %q:%s",
01165 fileloc_unparse (g_currentloc),
01166 fileloc_unparseRaw (file, line), s));
01167 }
01168
01169 if (fileloc_withinLines (lastparseerror, g_currentloc, 7))
01170 {
01171 llfatalerror (message ("%q: Cannot recover from parse error.",
01172 fileloc_unparse (g_currentloc)));
01173 }
01174
01175 (void) fflush (g_msgstream);
01176 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
01177 fileloc_unparse (g_currentloc),
01178 fileloc_unparseRaw (file, line),
01179 s, errno));
01180 printCodePoint ();
01181
01182 (void) fflush (stderr);
01183 perror ("Possible system error diagnostic: ");
01184 (void) fflush (stderr);
01185
01186 printBugReport ();
01187
01188 numbugs++;
01189
01190 if (numbugs > 5 && fileloc_withinLines (lastbug, g_currentloc, 2))
01191 {
01192 llfatalerror (message ("%q: Cannot recover from last bug.",
01193 fileloc_unparse (g_currentloc)));
01194 }
01195
01196 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
01197 fileloc_free (lastbug);
01198 lastbug = fileloc_copy (g_currentloc);
01199 closeMessage ();
01200
01201 (void) fflush (stderr);
01202 inbug = FALSE;
01203 }
01204
01205 # ifndef NOLCL
01206 void
01207 lclbug ( cstring s)
01208 {
01209 prepareMessage ();
01210 printError (stderr, message ("*** Internal Bug: %q", s));
01211 printCodePoint ();
01212 printBugReport ();
01213 fprintf (stderr, " (attempting to continue, results may be incorrect)\n");
01214 closeMessage ();
01215 }
01216 # endif
01217
01218 void
01219 llfatalerror (cstring s)
01220 {
01221 prepareMessage ();
01222 printError (stderr, s);
01223 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
01224 llexit (LLFAILURE);
01225 }
01226
01227 void
01228 llfatalerrorLoc ( cstring s)
01229 {
01230 prepareMessage ();
01231 (void) fflush (g_msgstream);
01232 printError (stderr, message ("%q: %q", fileloc_unparse (g_currentloc), s));
01233 printError (stderr, cstring_makeLiteral ("*** Cannot continue."));
01234 llexit (LLFAILURE);
01235 }
01236
01237
01238
01239
01240
01241 void
01242 llgloberror ( cstring s)
01243 {
01244 if (context_inSuppressRegion ())
01245 {
01246 cstring_free (s);
01247 }
01248 else
01249 {
01250 context_setNeednl ();
01251 prepareMessage ();
01252 context_hasError ();
01253 flagcode_recordError (FLG_SPECIAL);
01254 printError (g_msgstream, s);
01255 closeMessage ();
01256 }
01257 }
01258
01259 # ifndef NOLCL
01260 bool
01261 lclHadError (void)
01262 {
01263 return (lclerrors > 0);
01264 }
01265
01266 bool
01267 lclHadNewError (void)
01268 {
01269 static int lastcall = 0;
01270
01271 if (lclerrors > lastcall)
01272 {
01273 lastcall = lclerrors;
01274 return TRUE;
01275 }
01276 else
01277 {
01278 return FALSE;
01279 }
01280 }
01281
01282 int
01283 lclNumberErrors (void)
01284 {
01285 return (lclerrors);
01286 }
01287
01288 void
01289 lclerror (ltoken t, cstring msg)
01290 {
01291 lclerrors++;
01292
01293 if (ltoken_getCode (t) != NOTTOKEN)
01294 {
01295 cstring loc = ltoken_unparseLoc (t);
01296
01297 lastfileloclen = cstring_length (loc);
01298
01299 printError (g_msgstream, message ("%q: %q", loc, msg));
01300 }
01301 else
01302 {
01303 printError (g_msgstream, msg);
01304 }
01305 }
01306
01307 void
01308 lclplainerror ( cstring msg)
01309 {
01310 lclerrors++;
01311
01312 printError (g_msgstream, msg);
01313 }
01314
01315 void
01316 lclfatalerror (ltoken t, cstring msg)
01317 {
01318 lclerror (t, msg);
01319 (void) fflush (g_msgstream);
01320 printError (stderr, cstring_makeLiteral ("*** Cannot continue"));
01321 llexit (LLFAILURE);
01322 }
01323
01324 void
01325 lclplainfatalerror ( cstring msg)
01326 {
01327 (void) fflush (g_msgstream);
01328 printError (stderr, message ("*** Cannot continue: %q", msg));
01329 llexit (LLFAILURE);
01330 }
01331
01332 void
01333 lclRedeclarationError (ltoken id)
01334 {
01335 cstring s = ltoken_getRawString (id);
01336
01337
01338 if (usymtab_existsEither (s))
01339 {
01340 uentry le = usymtab_lookupEither (s);
01341
01342 lclerror (id, message ("Respecification of %s", s));
01343 llgenindentmsg (message ("Previous specification of %q",
01344 uentry_getName (le)),
01345 uentry_whereSpecified (le));
01346 }
01347 else
01348 {
01349 lclerror (id, message ("Identifier redeclared: %s", s));
01350 }
01351 }
01352 # endif
01353
01354 void genppllerror (flagcode code, cstring s)
01355 {
01356 if (context_inSuppressZone (g_currentloc))
01357 {
01358 cstring_free (s);
01359 }
01360 else
01361 {
01362 if (context_getFlag (code))
01363 {
01364 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
01365 {
01366 fprintf (g_msgstream, " >\n");
01367 }
01368
01369 llerror (code, s);
01370
01371 if (code != FLG_PREPROC)
01372 {
01373 llsuppresshint ('-', code);
01374 }
01375
01376 if (context_getFlag (FLG_SHOWSCAN) && !context_isInCommandLine ())
01377 {
01378 fprintf (stderr, "< more preprocessing .");
01379 }
01380 }
01381 else
01382 {
01383 cstring_free (s);
01384 }
01385 }
01386 }
01387
01388 void genppllerrorhint (flagcode code, cstring s,
01389 cstring hint)
01390 {
01391 if (context_inSuppressZone (g_currentloc))
01392 {
01393 cstring_free (s);
01394 cstring_free (hint);
01395 }
01396 else
01397 {
01398 if (context_getFlag (code))
01399 {
01400 prepareMessage ();
01401 context_clearPreprocessing ();
01402 llerror (code, s);
01403 llgenhint (hint);
01404 context_setPreprocessing ();
01405 closeMessage ();
01406 }
01407 else
01408 {
01409 cstring_free (s);
01410 cstring_free (hint);
01411 }
01412 }
01413 }
01414
01415 void ppllerror ( cstring s)
01416 {
01417 genppllerror (FLG_PREPROC, s);
01418 }
01419
01420 void pplldiagmsg (cstring s)
01421 {
01422 if (context_getDebug (FLG_SHOWSCAN) && !context_isInCommandLine ())
01423 {
01424 fprintf (stderr, " >\n");
01425 lldiagmsg (s);
01426 fprintf (stderr, "< more preprocessing .");
01427 }
01428 else
01429 {
01430 lldiagmsg (s);
01431 }
01432 }
01433
01434 void loadllmsg (cstring s)
01435 {
01436 if (context_getDebug (FLG_SHOWSCAN))
01437 {
01438 fprintf (stderr, " >\n");
01439 lldiagmsg (s);
01440 fprintf (stderr, "< .");
01441 }
01442 else
01443 {
01444 lldiagmsg (s);
01445 }
01446 }
01447
01448 static void llreportparseerror ( cstring s)
01449 {
01450 if (fileloc_withinLines (lastparseerror, g_currentloc, 5))
01451 {
01452 cstring_free (s);
01453 }
01454 else
01455 {
01456 llerror (FLG_SYNTAX, s);
01457
01458 fileloc_free (lastparseerror);
01459 lastparseerror = fileloc_copy (g_currentloc);
01460 }
01461 }
01462
01463 bool lloptgenerror (flagcode o, cstring s, fileloc loc)
01464 {
01465 if (llrealerror (s, loc))
01466 {
01467 llsuppresshint ('-', o);
01468 closeMessage ();
01469 flagcode_recordError (o);
01470 return TRUE;
01471 }
01472
01473 flagcode_recordSuppressed (o);
01474 return FALSE;
01475 }
01476
01477 bool optgenerror2 (flagcode f1, flagcode f2, cstring s, fileloc loc)
01478 {
01479 if (context_suppressFlagMsg (f1, loc))
01480 {
01481 flagcode_recordSuppressed (f1);
01482 cstring_free (s);
01483 }
01484 else
01485 {
01486 if (context_suppressFlagMsg (f2, loc))
01487 {
01488 flagcode_recordSuppressed (f2);
01489 cstring_free (s);
01490 }
01491 else
01492 {
01493 if (llrealerror (s, loc))
01494 {
01495 llsuppresshint ('-', f2);
01496 flagcode_recordError (f2);
01497 closeMessage ();
01498 return TRUE;
01499 }
01500
01501 flagcode_recordSuppressed (f2);
01502 }
01503 }
01504 return FALSE;
01505 }
01506
01507 bool optgenerror2n (flagcode f1, flagcode f2, cstring s, fileloc loc)
01508 {
01509
01510 if (context_suppressFlagMsg (f1, loc))
01511 {
01512 flagcode_recordSuppressed (f1);
01513 cstring_free (s);
01514 }
01515 else
01516 {
01517 if (context_suppressNotFlagMsg (f2, loc))
01518 {
01519 flagcode_recordSuppressed (f2);
01520 cstring_free (s);
01521 }
01522 else
01523 {
01524 if (llrealerror (s, loc))
01525 {
01526 llsuppresshint ('+', f2);
01527 flagcode_recordError (f2);
01528 closeMessage ();
01529 return TRUE;
01530 }
01531
01532 flagcode_recordSuppressed (f2);
01533 }
01534 }
01535 return FALSE;
01536 }
01537
01538 bool llnoptgenerror (flagcode o, cstring s, fileloc loc)
01539 {
01540 if (llrealerror (s, loc))
01541 {
01542 llsuppresshint ('+', o);
01543 flagcode_recordError (o);
01544 closeMessage ();
01545 return TRUE;
01546 }
01547
01548 flagcode_recordSuppressed (o);
01549 return FALSE;
01550 }
01551
01552 void llparseerror (cstring s)
01553 {
01554 if (context_getFlag (FLG_TRYTORECOVER))
01555 {
01556 parseerrorcount++;
01557
01558 if (parseerrorcount > GIVEUPPARSE)
01559 {
01560 if (cstring_isDefined (s))
01561 {
01562 llfatalerror (message ("%q: Parse Error: %q. "
01563 "Too many errors, giving up.",
01564 fileloc_unparse (g_currentloc), s));
01565 }
01566 else
01567 {
01568 llfatalerror (message ("%q: Parse Error. Too many errors, giving up.",
01569 fileloc_unparse (g_currentloc)));
01570 }
01571 }
01572 else
01573 {
01574 if (cstring_isDefined (s))
01575 {
01576 llreportparseerror (message ("Parse Error: %q. Attempting to continue.",
01577 s));
01578 }
01579 else
01580 {
01581 llreportparseerror (message ("Parse Error. Attempting to continue."));
01582 }
01583 }
01584 }
01585 else
01586 {
01587 cstring msg;
01588
01589 if (cstring_isDefined (s))
01590 {
01591 msg = message ("Parse Error: %q.", s);
01592 }
01593 else
01594 {
01595 msg = message ("Parse Error.");
01596 }
01597
01598 llfatalerror
01599 (message ("%q: %s (For help on parse errors, "
01600 "see lclint -help parseerrors.)",
01601 fileloc_unparse (g_currentloc), msg));
01602 }
01603 }
01604
01605 bool doCheck (bool x, cstring pred, cstring file, int line)
01606 {
01607 if (!x) {
01608 llbug (message ("%q: Check Failed: %s",
01609 fileloc_unparseRaw (file, line),
01610 pred));
01611 }
01612
01613 return x;
01614 }
01615
01616 cstring lldecodeerror ( int errnum)
01617 {
01618 char *result;
01619
01620 #ifndef VMS
01621 #ifndef HAVE_STRERROR
01622 result = NULL;
01623 #else
01624 result = strerror (errnum);
01625 #endif
01626 #else
01627
01628
01629
01630
01631
01632
01633
01634 result = strerror (errnum, vaxc$errno);
01635 #endif
01636
01637 if (result == NULL)
01638 {
01639 result = cstring_toCharsSafe (message ("undocumented I/O error: %d", errnum));
01640 }
01641
01642 return cstring_fromChars (result);
01643 }
01644
01645 void llquietbugaux (cstring s, cstring file, int line)
01646 {
01647 # if 0
01648 # ifdef HOMEVERSION
01649 llflush ();
01650 printError (stderr, message ("%q: *** Internal Bug at %q: %q [errno: %d]",
01651 fileloc_unparse (g_currentloc),
01652 fileloc_unparseRaw (file, line),
01653 s, errno));
01654 printCodePoint ();
01655 llflush ();
01656 # endif
01657 # else
01658 cstring_free (s);
01659 # endif
01660 }
01661
01662 void llflush (void)
01663 {
01664 (void) fflush (g_msgstream);
01665 (void) fflush (stderr);
01666 }