## error.pkg
# Compiled by:
#
src/lib/c-kit/src/parser/c-parser.sublib### "Finally I'm becoming stupider no more."
###
### -- Paul Erdos
stipulate
package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package f = sfprintf; # sfprintf is from
src/lib/src/sfprintf.pkg package pp = old_prettyprinter; # old_prettyprinter is from
src/lib/prettyprint/big/src/old-prettyprinter.pkg package sm = line_number_db; # line_number_db is from
src/lib/c-kit/src/parser/stuff/line-number-db.pkgherein
package error
: (weak) Error # Error is from
src/lib/c-kit/src/parser/stuff/error.api {
Error_State
=
ES
{ out_strm: fil::Output_Stream,
num_errors: Ref( Int ),
num_warnings: Ref( Int ),
warnings_enabled: Ref( Bool ),
errors_enabled: Ref( Bool ),
errors_limit: Int,
warnings_limit: Int
};
# Global error and warning count limits:
#
errors_limit = REF 10; # flag for suppressing error messages
warnings_limit = REF 10; # flag for suppressing warning messages
# make an error state. src is the source file name, dst is the
# output state to report errors on, lnum and lpos are references
# used to keep track of the current line number and starting
# character positions of the scanned lines.
#
fun make_error_state (dst: fil::Output_Stream)
=
ES { out_strm => dst,
num_errors => REF 0,
num_warnings => REF 0,
warnings_enabled => REF TRUE,
errors_enabled => REF TRUE,
errors_limit => *errors_limit,
warnings_limit => *warnings_limit
};
fun inc (i: Ref( Int )) = { i := *i + 1; ();};
fun dec (i: Ref( Int )) = { i := *i - 1; ();};
# Curried version of fil::write:
#
fun outputc outstrm strng
=
fil::write (outstrm, strng);
# For reporting internal bugs:
#
fun bug (ES { out_strm, ... } ) (msg: String) : Void
=
fil::write (out_strm, ("Compiler bug: " + msg + "\n"));
# Print a warning/error message with location info:
#
fun say_error (es as ES { out_strm, ... }, loc, kind, msg)
=
f::fnprintf' (outputc out_strm) "%s: %s%s\n" [
f::STRING (sm::loc_to_string loc), f::STRING kind, f::STRING msg
];
# Print a formatted warning/error message with location info:
#
fun fmt_error (es as ES { out_strm, ... }, loc, kind, fmt, items)
=
f::fnprintf' (outputc out_strm) ("%s: %s" + fmt + "\n")
((f::STRING (sm::loc_to_string loc)) ! (f::STRING kind) ! items);
# Print warning messages to the error stream:
#
fun warning (es as ES { num_warnings, warnings_limit, warnings_enabled, ... }, loc, msg)
=
if *warnings_enabled
say_error (es, loc, "warning: ", msg);
inc num_warnings;
if (*num_warnings > warnings_limit)
warnings_enabled := FALSE;
say_error (es, loc, "warning: ", "additional warnings suppressed");
fi;
fi;
fun warningf (es as ES { num_warnings, warnings_limit, warnings_enabled, ... },
loc, fmt, items)
=
if (*warnings_enabled)
fmt_error (es, loc, "warning: ", fmt, items);
inc num_warnings;
if (*num_warnings > warnings_limit)
warnings_enabled := FALSE;
say_error (es, loc, "warning: ", "additional warnings suppressed");
fi;
fi;
fun no_more_warnings (es as ES { warnings_enabled, ... } )
=
{ warnings_enabled := FALSE;
say_error (es, sm::UNKNOWN, "warning: ", "additional warnings suppressed.");
};
# hints - heuristic help for error messages;
# Note: must be called before error call is generated.
last_hint = REF (NULL: Null_Or( String ));
fun hint s = (last_hint := THE s);
# Print error messages to the error stream:
#
fun error (es as ES { num_errors, errors_limit, errors_enabled, ... }, loc, msg)
=
if (*errors_enabled)
case *last_hint
THE s => { say_error (es, loc, "error: ", msg + "\n" + s);
last_hint := NULL;};
NULL => say_error (es, loc, "error: ", msg);
esac;
inc num_errors;
if (*num_errors > errors_limit)
errors_enabled := FALSE;
say_error (es, loc, "warning: ", "additional errors suppressed.");
fi;
fi;
fun errorf (es as ES { num_errors, errors_limit, errors_enabled, ... }, loc, fmt, items)
=
if *errors_enabled
fmt_error (es, loc, "error: ", fmt, items);
inc num_errors;
if (*num_errors > errors_limit)
errors_enabled := FALSE;
say_error (es, loc, "warning: ", "additional errors suppressed.");
fi;
fi;
fun no_more_errors (es as ES { errors_enabled, ... } )
=
{ errors_enabled := FALSE;
say_error (es, sm::UNKNOWN, "warning: ", "additional errors suppressed.");
};
# Pretty-print an error message on the error stream:
#
fun prettyprint_error (es as ES { out_strm, num_errors, ... }, loc, prettyprint)
=
{ prettyprint_stream
=
pp::make_ppstream
{
consumer => outputc out_strm,
flush => \\ () = fil::flush out_strm,
close => \\ () = ()
};
inc num_errors;
pp::begin_block prettyprint_stream pp::INCONSISTENT 0;
pp::add_string prettyprint_stream
(f::sprintf' "Error %s: " [f::STRING (sm::loc_to_string loc)]);
prettyprint prettyprint_stream;
pp::add_newline prettyprint_stream;
pp::end_block prettyprint_stream;
pp::flush_ppstream prettyprint_stream;
};
fun err_stream (ES { out_strm, ... } )
=
out_strm;
# Return count of errors reported on the state (since last reset):
#
fun error_count (ES { num_errors, ... } )
=
*num_errors;
# Return count of warnings reported on the state (since last reset):
#
fun warning_count (ES { num_warnings, ... } )
=
*num_warnings;
# Clear the error and warning counts, so that errorCount and
# warningCount will return 0:
#
fun reset (ES { num_errors, num_warnings, ... } )
=
{ num_errors := 0;
num_warnings := 0;
};
}; # error
end;