first cut at detecting error source
This commit is contained in:
parent
b3a262910f
commit
cd7d654cca
83
C/errors.c
83
C/errors.c
@ -291,7 +291,7 @@ static char tmpbuf[YAP_BUF_SIZE];
|
||||
#include "YapErrors.h"
|
||||
|
||||
/**
|
||||
* @brief Yap_Error__
|
||||
* @brief Yap_Errorp
|
||||
* This function handles errors in the C code. Check errors.yap for the
|
||||
*corresponding Prolog code.
|
||||
*
|
||||
@ -313,7 +313,9 @@ static char tmpbuf[YAP_BUF_SIZE];
|
||||
* The list includes the following options:
|
||||
* + c=c(file, line, function): where the bug was detected;
|
||||
*
|
||||
* + p=p(mod, name, arity, file, line): the prolog procedure that caused the bug,
|
||||
* + e=p(mod, name, arity, cl, file, lin): where the code was entered;
|
||||
*
|
||||
* + p=p(mod, name, arity, cl, file, line): the prolog procedure that caused the bug,
|
||||
*and optionally,
|
||||
*
|
||||
* + g=g(Goal): the goal that created this mess
|
||||
@ -327,7 +329,7 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno,
|
||||
CELL nt[3];
|
||||
Functor fun;
|
||||
bool serious;
|
||||
Term tf, error_t;
|
||||
Term tf, error_t, comment, culprit;
|
||||
|
||||
/* disallow recursive error handling */
|
||||
if (LOCAL_PrologMode & InErrorMode) {
|
||||
@ -362,39 +364,7 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno,
|
||||
tmpbuf);
|
||||
Yap_exit(1);
|
||||
}
|
||||
/* must do this here */
|
||||
if (type == (SYSTEM_ERROR_FATAL || type == SYSTEM_ERROR_INTERNAL
|
||||
#if USE_SYSTEM_MALLOC
|
||||
|| !Yap_heap_regs
|
||||
#else
|
||||
|| !Yap_HeapBase
|
||||
#endif
|
||||
)) {
|
||||
{
|
||||
va_start(ap, where);
|
||||
char *format = NULL;
|
||||
format = va_arg(ap, char *);
|
||||
/* now build the error string */
|
||||
if (format) {
|
||||
#if HAVE_VSNPRINTF
|
||||
(void)vsnprintf(tmpbuf, YAP_BUF_SIZE, format, ap);
|
||||
#else
|
||||
(void)vsprintf(tmpbuf, format, ap);
|
||||
#endif
|
||||
} else {
|
||||
tmpbuf[0] = '\0';
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
if (LOCAL_PrologMode == UserCCallMode) {
|
||||
fprintf(stderr, "%%\n%%\n");
|
||||
fprintf(stderr, "%% YAP OOOPS in USER C-CODE: %s.\n", tmpbuf);
|
||||
fprintf(stderr, "%%\n%%\n");
|
||||
} else {
|
||||
fprintf(stderr, "%%\n%%\n");
|
||||
fprintf(stderr, "%% YAP OOOPS: %s.\n", tmpbuf);
|
||||
fprintf(stderr, "%%\n%%\n");
|
||||
}
|
||||
if (LOCAL_PrologMode == BootMode) {
|
||||
Yap_detect_bug_location(P, FIND_PRED_FROM_ANYWHERE, (char *)HR, 256);
|
||||
fprintf(stderr, "%%\n%% PC: %s\n", (char *)HR);
|
||||
Yap_detect_bug_location(CP, FIND_PRED_FROM_ANYWHERE, (char *)HR, 256);
|
||||
@ -440,8 +410,11 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno,
|
||||
#else
|
||||
(void)vsprintf(tmpbuf, format, ap);
|
||||
#endif
|
||||
} else
|
||||
comment = MkAtomTerm(Yap_LookupAtom(tmpbuf));
|
||||
} else {
|
||||
tmpbuf[0] = '\0';
|
||||
comment = TermNil;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
if (LOCAL_PrologMode & BootMode) {
|
||||
@ -521,28 +494,36 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno,
|
||||
MAX_ERROR_MSG_SIZE);
|
||||
LOCAL_ErrorMessage = LOCAL_ErrorSay;
|
||||
}
|
||||
if (LOCAL_ErrorSay && LOCAL_ErrorSay[0])
|
||||
comment = MkAtomTerm(Yap_LookupAtom( LOCAL_ErrorSay ) );
|
||||
else
|
||||
comment = TermNil;
|
||||
}
|
||||
switch (type) {
|
||||
case RESOURCE_ERROR_HEAP:
|
||||
case RESOURCE_ERROR_STACK:
|
||||
case RESOURCE_ERROR_TRAIL:
|
||||
nt[1] = MkAtomTerm(Yap_LookupAtom(tmpbuf));
|
||||
break;
|
||||
comment = MkAtomTerm(Yap_LookupAtom(tmpbuf));
|
||||
default:
|
||||
{
|
||||
Term stack_dump;
|
||||
|
||||
if ((stack_dump = Yap_all_calls()) == 0L) {
|
||||
stack_dump = TermNil;
|
||||
LOCAL_Error_Size = 0L;
|
||||
}
|
||||
nt[1] = MkPairTerm(MkAtomTerm(Yap_LookupAtom(tmpbuf)),
|
||||
MkPairTerm(stack_dump, TermNil));
|
||||
if (type == SYNTAX_ERROR) {
|
||||
nt[1] = MkPairTerm(where, nt[1]);
|
||||
}
|
||||
nt[1] = TermNil;
|
||||
if (comment != TermNil)
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("i")),comment), nt[1]);
|
||||
if (file && function) {
|
||||
Term ts[3], t3;
|
||||
ts[0] = MkAtomTerm(Yap_LookupAtom(file));
|
||||
ts[1] = MkIntegerTerm(lineno);
|
||||
ts[2] = MkAtomTerm(Yap_LookupAtom(function));
|
||||
t3 = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom("c"),3),3,ts);
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("c")),t3), nt[1]);
|
||||
}
|
||||
if ((culprit=Yap_pc_location( P, B, ENV)) != TermNil ) {
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("p")),culprit), nt[1]);
|
||||
}
|
||||
if ((culprit=Yap_env_location( CP, B, ENV, 0)) != TermNil ) {
|
||||
nt[1] = MkPairTerm(MkPairTerm(MkAtomTerm(Yap_LookupAtom("e")),culprit), nt[1]);
|
||||
}
|
||||
}
|
||||
Yap_DebugPlWrite(nt[1]);
|
||||
/* disable active signals at this point */
|
||||
LOCAL_Signals = 0;
|
||||
CalculateStackGap(PASS_REGS1);
|
||||
|
@ -217,19 +217,13 @@ to allow user-control.
|
||||
|
||||
|
||||
|
||||
'$do_error'(Type,Message) :-
|
||||
'$do_error'(Type,Goal) :-
|
||||
format('~w~n', [Type]),
|
||||
% stop_low_level_trace,
|
||||
current_stack(local_sp(Location,
|
||||
P,CP,PP,Envs,CPs)),
|
||||
% '$stack_dump',
|
||||
'$compose_context'(Message, Location, CMessage),
|
||||
throw(error(Type,[context(CMessage)
|
||||
,local_sp(Location,P,CP,PP,Envs,CPs)])).
|
||||
|
||||
'$compose_context'(context(Culprit), Caller, context(Culprit, Caller) ) :-
|
||||
!.
|
||||
'$compose_context'(Culprit, _Caller, context(Culprit) ).
|
||||
ancestor_location(Call, Caller),
|
||||
throw(error(Type, [
|
||||
[g|g(Goal)],
|
||||
[p|Call],
|
||||
[e|Caller]])).
|
||||
|
||||
|
||||
'$do_pi_error'(type_error(callable,Name/0),Message) :- !,
|
||||
|
179
pl/messages.yap
179
pl/messages.yap
@ -44,7 +44,11 @@ generic informational messages
|
||||
help messages (not currently implemented in YAP)
|
||||
+ `query`
|
||||
query used in query processing (not currently implemented in YAP)
|
||||
+ `silent`
|
||||
+ `silent`,M,Na,Ar,File, FilePos]],
|
||||
[nl, nl].
|
||||
caller( error(_,Term), _) -->
|
||||
{ lists:memberchk([g|g(Call)], Term) },
|
||||
['~*|called from
|
||||
messages that do not produce output but that can be intercepted by hooks.
|
||||
|
||||
|
||||
@ -192,130 +196,107 @@ compose_message(version(Version), _Leve) -->
|
||||
[ '~a' - [Version] ].
|
||||
compose_message(myddas_version(Version), _Leve) -->
|
||||
[ 'MYDDAS version ~a' - [Version] ].
|
||||
compose_message(yes, _Leve) --> !,
|
||||
compose_message(yes, _Level) --> !,
|
||||
[ 'yes'- [] ].
|
||||
|
||||
compose_message(Term, Level) -->
|
||||
{ Level == error -> true ; Level == warning },
|
||||
file_location(Term, Cause),
|
||||
main_message(Term, Cause),
|
||||
stack_dump( Term ),
|
||||
extra_info( Term ),
|
||||
{ Level == error -> true ; Level == warning },
|
||||
location(Term, Level),
|
||||
[nl],
|
||||
!.
|
||||
main_message( Term, Level ),
|
||||
c_goal( Term, Level ),
|
||||
caller( Term, Level ),
|
||||
extra_info( Term, Level ),
|
||||
!,
|
||||
[nl].
|
||||
compose_message(A-L, _Level) -->
|
||||
{ format(user_error,A,L) }.
|
||||
{ format(user_error,A,L) }.
|
||||
|
||||
|
||||
file_location(error(_,syntax_error(_,between(_,LN,_),FileName,_) ), _ ) -->
|
||||
location( error(_,Term), Level ) -->
|
||||
{ lists:memberchk([p|p(M,Na,Ar,File,FilePos)], Term ) },
|
||||
[ '~a:~d:0 ~a in ~a:~q/~d:'-[File, FilePos,Level,M,Na,Ar] ],
|
||||
[nl].
|
||||
location(error(_,syntax_error(_,between(_,LN,_),FileName,_) ), _ ) -->
|
||||
[ '~a:~d:0: ' - [FileName,LN] ] .
|
||||
file_location(warning(_,syntax_error(_,between(_,LN,_),FileName,_) ), _ ) -->
|
||||
location(warning(_,syntax_error(_,between(_,LN,_),FileName,_) ), _ ) -->
|
||||
[ '~a:~d:0: ' - [FileName,LN] ] .
|
||||
file_location(style_check(_,LN,FileName,_ ), _ ) -->
|
||||
% { stream_position_data( line_count, LN) },
|
||||
location(style_check(_,LN,FileName,_ ), _ ) -->
|
||||
% { stream_position_data( line_count, LN) },
|
||||
!,
|
||||
[ '~a:~d:0: ' - [FileName,LN] ] .
|
||||
file_location(error(_,L), Goal )-->
|
||||
{
|
||||
lists:memberchk(context(G),L),
|
||||
clause_to_indicator(G, Goal)
|
||||
->
|
||||
true
|
||||
;
|
||||
lists:memberchk(context(G,_P), L),
|
||||
clause_to_indicator(G, Goal)
|
||||
->
|
||||
true
|
||||
;
|
||||
true
|
||||
},
|
||||
{
|
||||
lists:memberchk(local_sp(LN:FileName:Mod:Ind,_P,_CP,_PP,_,_),L)
|
||||
->
|
||||
( var(Goal) -> Goal = Mod:Ind ; true )
|
||||
;
|
||||
lists:memberchk(local_sp(LN:FileName:[],_P,_CP,_PP,_,_),L)
|
||||
->
|
||||
true
|
||||
;
|
||||
prolog_load_context(file, FileName),
|
||||
stream_property( Stream, alias(loop_stream) ),
|
||||
stream_property( Stream, line_count( LN ) )
|
||||
->
|
||||
true
|
||||
;
|
||||
user_input = S,
|
||||
stream_property( S, line_count( LN ) ),
|
||||
stream_property( S, file_name( FileName ) )
|
||||
},
|
||||
{
|
||||
nonvar(Goal)
|
||||
->
|
||||
true
|
||||
;
|
||||
Ind = 'system:0'
|
||||
},
|
||||
[ '~d:0: ' - [FileName,LN] ].
|
||||
%file_location(Info,query) -->
|
||||
% { format( user_error, 'information available is: ~n~q.~n~n ' , [Info])} .
|
||||
|
||||
|
||||
|
||||
/*print_message(error, error(Msg,[Info|local_sp(P,CP,Envs,CPs)])) :- !,
|
||||
recorda(sp_info,local_sp(Msg, P,CP,PP,Envs,CPs),R),
|
||||
print_message(error, error(Msg, Info)),
|
||||
erase(R).
|
||||
*/
|
||||
|
||||
%message(loaded(Past,AbsoluteFileName,user,Msec,Bytes), Prefix, Suffix) :- !,
|
||||
main_message( error(syntax_error,syntax_error(Msg,between(L0,LM,LF),_Stream,Term)), _ ) -->
|
||||
!,
|
||||
['syntax error: ~s' - [Msg]],
|
||||
['~*|!!! syntax error: ~s' - [10,Msg]],
|
||||
[nl],
|
||||
% [prefix(' ')],
|
||||
( syntax_error_term( between(L0,LM,LF), Term )
|
||||
-> []
|
||||
->
|
||||
[]
|
||||
;
|
||||
['failed_processing ~w' - [Term],
|
||||
nl]
|
||||
['failed_processing ~w' - [Term]],
|
||||
[nl]
|
||||
).
|
||||
main_message(style_check(singleton(SVs),_S,_W,P), I) -->
|
||||
main_message(style_check(singleton(SVs),_S,_W,P), _) -->
|
||||
{ clause_to_indicator(P, I) },
|
||||
[ 'singleton variable~*c ~s in ~q.' - [ NVs, 0's, SVsL, I] ], % '
|
||||
[ '~*|!!! singleton variable~*c ~s in ~q.' - [ 10, NVs, 0's, SVsL, I] ],
|
||||
{ svs(SVs,SVsL,[]),
|
||||
( SVs = [_] -> NVs = 0 ; NVs = 1 )
|
||||
}.
|
||||
main_message(style_check(multiple(N,A,Mod,I0),_L,File,_),_I) -->
|
||||
[ '~a redefines ~q from ~a.' - [File, Mod:N/A, I0] ].
|
||||
main_message(style_check(multiple(N,A,Mod,I0),_L,File,_),_) -->
|
||||
[ '~*|!!! ~a redefines ~q from ~a.' - [8,File, Mod:N/A, I0] ].
|
||||
main_message(style_check(discontiguous(N,A,Mod),_P,_T,_M), _) -->
|
||||
[ 'discontiguous definition for ~p.' - [Mod:N/A] ].
|
||||
[ '~*|!!! !!! discontiguous definition for ~p.' - [8,Mod:N/A] ].
|
||||
main_message(error(Msg,Info), _) --> {var(Info)}, !,
|
||||
[ nl, '~internal YAP problem, incomplete message ~w~n.' - [Msg], nl ].
|
||||
main_message(error(consistency_error(Who), [Where|_]), _Source) -->
|
||||
[ 'argument ~a not consistent with ~q.'-[Who,Where] ].
|
||||
[ nl, '~*|!!! found internal YAP problem, incomplete message ~w~n.' - [8,Msg], nl ].
|
||||
main_message(error(consistency_error(Who)), _Source) -->
|
||||
[ '~*|!!! has argument ~a not consistent with type.'-[8,Who] ].
|
||||
main_message(error(domain_error(Who , Type), _Where), _Source) -->
|
||||
[ 'value ~a should be in ~q,' - [Who,Type], nl ].
|
||||
[ '~*|!!! ~q does not belong to domain ~a,' - [8,Who,Type], nl ].
|
||||
main_message(error(evaluation_error(What), _Where), _Source) -->
|
||||
[ ' ~a during evaluation of arithmetic expressions,' - [What], nl ].
|
||||
main_message(error(existence_error(Who , Type), _Where), _Source) -->
|
||||
[ '~a ~q could not be found,' - [Who, Type], nl ].
|
||||
[ '~*|!!! caused ~a during evaluation of arithmetic expressions,' - [8,What], nl ].
|
||||
main_message(error(existence_error(Type , Who), _Where), _Source) -->
|
||||
[ '~*|!!! ~q ~a could not be found,' - [8,Type, Who], nl ].
|
||||
main_message(error(permission_error(Op, Type, Id), _Where), _Source) -->
|
||||
[ ' ~q not allowed in ~a ~q,' - [Id, Type, Op], nl ].
|
||||
main_message(error(instantiation_error), _Source) -->
|
||||
[ 'unbound variable' - [], nl ].
|
||||
[ '~*|!!! ~q is not allowed in ~a ~q,' - [8, Op, Type,Id], nl ].
|
||||
main_message(error(instantiation_error, _Where), _Source) -->
|
||||
[ '~*|!!! unbound variable' - [8], nl ].
|
||||
main_message(error(representation_error), _Source) -->
|
||||
[ 'unbound variable' - [], nl ].
|
||||
[ '~*|!!! unbound variable' - [8], nl ].
|
||||
main_message(error(type_error(Type,Who), _What), _Source) -->
|
||||
[ ' ~q should be of type ~a' - [Who,Type], nl ].
|
||||
[ '~*|!!! ~q should be of type ~a' - [8,Who,Type], nl ].
|
||||
main_message(error(uninstantiation_error(T),_), _Source) -->
|
||||
[ 'found ~q, expected unbound variable ' - [T], nl ].
|
||||
[ '~*|!!! found ~q, expected unbound variable ' - [8,T], nl ].
|
||||
|
||||
caller( error(_,Term), _) -->
|
||||
{ lists:memberchk([p|p(M,Na,Ar,File,FilePos)], Term ) },
|
||||
{ lists:memberchk([g|g(Call)], Term) },
|
||||
!,
|
||||
['~*|goal was ~q' - [10,Call]],
|
||||
[nl],
|
||||
['~*|exception raised from ~a:~q/~d, ~a:~d:0. '-[10,M,Na,Ar,File, FilePos]],
|
||||
[nl].
|
||||
caller( error(_,Term), _) -->
|
||||
{ lists:memberchk([e|p(M,Na,Ar,File,FilePos)], Term ) },
|
||||
!,
|
||||
['~*|exception raised from ~a:~q/~d, ~a:~d:0. '-[10,M,Na,Ar,File, FilePos]],
|
||||
[nl].
|
||||
caller( error(_,Term), _) -->
|
||||
{ lists:memberchk([g|g(Call)], Term) },
|
||||
!,
|
||||
['~*|goal ~q '-[10,Call]],
|
||||
[nl].
|
||||
caller( _, _) -->
|
||||
[].
|
||||
|
||||
c_goal( error(_,Term), Level ) -->
|
||||
{ lists:memberchk([c|c(File, Line, Func)], Term ) },
|
||||
!,
|
||||
['~*|~a raised at C-function ~a() in ~a/~d:0. '-[10, Level, Func, File, Line]],
|
||||
[nl].
|
||||
c_goal( _, _Level ) --> [].
|
||||
|
||||
stack_dump(_) --> !.
|
||||
stack_dump(error(_,_)) -->
|
||||
{ fail },
|
||||
{ recorded(sp_info,local_sp(_Msg,_P,CP,_PP,Envs,CPs),_) },
|
||||
{ Envs = [_|_] ; CPs = [_|_] }, !,
|
||||
[nl],
|
||||
'$hacks':display_stack_info(CPs, Envs, 20, CP).
|
||||
|
||||
prolog_message(X) -->
|
||||
system_message(X).
|
||||
@ -386,8 +367,7 @@ system_message(error(permission_error(access,static_procedure,P), Where)) -->
|
||||
system_message(error(permission_error(alias,new,P), Where)) -->
|
||||
[ 'PERMISSION ERROR- ~w: cannot create alias ~w' - [Where,P] ].
|
||||
system_message(error(permission_error(create,Name,P), Where)) -->
|
||||
{ object_name(Name, ObjName) },
|
||||
[ 'PERMISSION ERROR- ~w: cannot create ~a ~w' - [Where,ObjName,P] ].
|
||||
[ 'PERMISSION ERROR- ~w: cannot create ~a ~w' - [Where,Name,P] ].
|
||||
system_message(error(permission_error(import,M1:I,redefined,SecondMod), Where)) -->
|
||||
[ 'PERMISSION ERROR- loading ~w: modules ~w and ~w both define ~w' - [Where,M1,SecondMod,I] ].
|
||||
system_message(error(permission_error(input,binary_stream,Stream), Where)) -->
|
||||
@ -536,7 +516,11 @@ domain_error(write_option, Opt) --> !,
|
||||
domain_error(Domain, Opt) -->
|
||||
[ '~w not a valid element for ~w' - [Opt,Domain] ].
|
||||
|
||||
extra_info( _ ) --> [].
|
||||
extra_info( error(_,Extra), _ ) -->
|
||||
{lists:memberchk([i|Msg], Extra)}, !,
|
||||
[' Comments: ~s~nx.' - [Msg] ].
|
||||
extra_info( _, _ ) -->
|
||||
[].
|
||||
|
||||
object_name(array, array).
|
||||
object_name(atom, atom).
|
||||
@ -553,6 +537,7 @@ object_name(float, float).
|
||||
object_name(in_byte, byte).
|
||||
object_name(in_character, character).
|
||||
object_name(integer, integer).
|
||||
|
||||
object_name(key, 'database key').
|
||||
object_name(leash_mode, 'leash mode').
|
||||
object_name(library, library).
|
||||
|
Reference in New Issue
Block a user