LaTeXML
view release on metacpan or search on metacpan
lib/LaTeXML/Common/Error.pm view on Meta::CPAN
sub Fatal {
my ($category, $object, $where, $message, @details) = @_;
# Check if this is a known unsafe fatal and flag it if so (so that we reinitialize in daemon contexts)
if ((($category eq 'internal') && ($object eq '<recursion>')) ||
($category eq 'too_many_errors') ||
($object eq 'deep_recursion') || ($object eq 'die')) {
$LaTeXML::UNSAFE_FATAL = 1; }
# We'll assume that if the DIE handler is bound (presumably to this function)
# we're in the outermost call to Fatal; we'll clear the handler so that we don't nest calls.
die $DIE_MESSAGE if $LaTeXML::IGNORE_ERRORS # Short circuit, w/no formatting, if in probing eval
|| (($SIG{__DIE__} eq 'DEFAULT') && $^S); # Also missing class when parsing bindings(?!?!)
my $inhandler = !$SIG{__DIE__};
my $ineval = 0; # whether we're in an eval should no longer matter!
# This seemingly should be "local", but that doesn't seem to help with timeout/alarm/term?
# It should be safe so long as the caller has bound it and rebinds it if necessary.
local $SIG{__DIE__} = 'DEFAULT'; # Avoid recursion while preparing the message.
my $state = $STATE;
if (!$inhandler) {
local $LaTeXML::BAILOUT = $LaTeXML::BAILOUT;
if (checkRecursiveError()) {
$LaTeXML::BAILOUT = 1;
push(@details, "Recursive Error!"); }
$state->noteStatus('fatal') if $state && !$ineval;
my $detail_level = (($VERBOSITY <= 1) && ($category =~ /^(?:timeout|too_many_errors)$/)) ? 0 : 2;
$message
= generateMessage(colorizeString("Fatal:" . $category . ":" . ToString($object), 'fatal'),
$where, $message, $detail_level, @details);
# If we're about to (really) DIE, we'll bypass the usual status message, so add it here.
# This really should be handled by the top-level program,
# after doing all processing within an eval
# BIZARRE: Note that die adds the "at <file> <line>" stuff IFF the message doesn't end w/ CR!
#### $message .= $state->getStatusMessage . "\n" if $state && !$ineval;
}
else { # If we ARE in a recursive call, the actual message is $details[0]
$message = $details[0] if $details[0]; }
# inhibit message to STDERR, since die will handle that
_printlines($message);
hardYankProcessing();
# Now that we have yanked the processing state, ignore any following errors
$LaTeXML::IGNORE_ERRORS = 1;
# If inside an eval, this won't actually die, but WILL set $@ for caller's use.
die $DIE_MESSAGE; }
sub hardYankProcessing {
my $state = $STATE;
# Nothing we can do if we are called without a global $STATE bound
return unless $state;
# Ensure we have nothing else to do in the main processing.
# NOTE: this recovery procedure must always be run after all logging messages are generated,
# as resetting the various stacks loses information (e.g. location is lost).
my $stomach = $$state{stomach};
my $gullet = $$stomach{gullet};
$$stomach{token_stack} = [];
# If we were in an infinite loop, disable any potential busy token.
my $relax_def = $$state{meaning}{"\\relax"}[0];
$state->assignMeaning($LaTeXML::CURRENT_TOKEN, $relax_def, 'global') if $LaTeXML::CURRENT_TOKEN;
for my $token (@{ $$gullet{pushback} }) {
$state->assignMeaning($token, $relax_def, 'global'); }
# Rescue data structures that may be serializable/resumable
if (@LaTeXML::LIST) {
$$stomach{rescued_boxes} = [@LaTeXML::LIST];
@LaTeXML::LIST = ();
}
if ($LaTeXML::DOCUMENT) {
$$state{rescued_document} = $LaTeXML::DOCUMENT; }
# avoid looping at \end{document}, Fatal brings us back to the doc level
$state->assignValue('current_environment', undef, 'global');
# then reset the gullet
$$gullet{pushback} = [];
$$gullet{mouthstack} = [];
$$gullet{pending_comments} = [];
$$gullet{mouth} = LaTeXML::Core::Mouth->new();
return; }
sub checkRecursiveError {
my @caller;
for (my $frame = 2 ; @caller = caller($frame) ; $frame++) {
if ($caller[3] =~ /^LaTeXML::(Global::ToString|Global::Stringify)$/) {
# print STDERR "RECURSED ON $caller[3]\n";
return 1; } }
return; }
# Should be fatal if strict is set, else warn.
sub Error {
my ($category, $object, $where, $message, @details) = @_;
return if $LaTeXML::IGNORE_ERRORS;
my $state = $STATE;
$state && $state->noteStatus('error');
if ($state && $state->lookupValue('STRICT')) {
Fatal($category, $object, $where, $message, @details); }
else {
my $formatted = generateMessage("Error:" . $category . ":" . ToString($object),
$where, $message, 1, @details);
_printline($formatted); }
# Note that "100" is hardwired into TeX, The Program!!!
my $maxerrors = ($state ? $state->lookupValue('MAX_ERRORS') : 100);
if ($state && (defined $maxerrors) && (($state->getStatus('error') || 0) > $maxerrors)) {
Fatal('too_many_errors', $maxerrors, $where, "Too many errors (> $maxerrors)!"); }
return; }
# Warning message; results may be OK, but somewhat unlikely
sub Warn {
my ($category, $object, $where, $message, @details) = @_;
return if $LaTeXML::IGNORE_ERRORS;
my $state = $STATE;
$state && $state->noteStatus('warning');
my $formatted = generateMessage("Warning:" . $category . ":" . ToString($object),
$where, $message, 0, @details);
_printline($formatted);
return; }
# Informational message; results likely unaffected
# but the message may give clues about subsequent warnings or errors
sub Info {
( run in 0.724 second using v1.01-cache-2.11-cpan-39bf76dae61 )