/*-------------------------------------------------------------------------*/ /* Prolog to Wam Compiler INRIA Rocquencourt - ChLoE Project */ /* C Run-time Daniel Diaz - 1994 */ /* */ /* Prolog/Wam Debugger */ /* */ /* debugger.c */ /*-------------------------------------------------------------------------*/ #include #include #include #include "wam_engine.h" #define DEBUGGER #include "debugger.h" LibPrototype(extern long strtol()) /*---------------------------------*/ /* Constants */ /*---------------------------------*/ #define CALL 1 #define EXIT 2 #define FAIL 4 #define REDO 8 #define WAMI 16 #define MAX_SPY_TBL_SIZE 64 #define DEFAULT_DEBUG_STACK_SZ 10240 /* in WamWords */ #define DEBUG_STACK_ENV_VAR_NAME "DEBUGSZ" #define BANK_NAME_OFFSET_LENGTH 13 #define HEXADECIMAL_LENGTH 10 #define DECIMAL_LENGTH 10 #define VALUE_PART_LENGTH BANK_NAME_OFFSET_LENGTH #define ERR_ALLOC_DEBUG "Memory allocation fault (in debugger)" #define ERR_DEBUG_STACK_OVERFLOW "debug stack overflow" #define SEPARATOR_LIST " ,[]" #define ABORT X61626F7274 #define DBG_EXEC X6462675F65786563 /*---------------------------------*/ /* Type Definitions */ /*---------------------------------*/ typedef enum { DEBUGGED, EXTERNAL, DYNAMIC }PDbgTyp; typedef struct runinf *PRunInf; typedef struct runinf /* one env = info call of f/n */ { PRunInf last_env; /* previous env in the stack */ PRunInf caller_env; /* env caller of this one */ AtomInf *atom; /* functor atom (f) */ int arity; /* arity (n) */ PDbgTyp type; /* debugged(local)/external/dyn */ Bool aux_pred; /* is it an auxiliary predicate?*/ WamCont cp; /* copy of CP before the call */ WamWord *e; /* copy of E before the call */ WamWord *b; /* copy of B before the call */ int invoc_nb; /* invocation number */ int indice_nb; /* indice number */ WamWord word; /* term: or */ union /* or heap term (if dynamic) */ { /* if !dynamic and arity > 0 */ WamWord f_n; /* word f/n */ Bool first_clause; /* first clause (try) if dyn */ }x; }RunInf; typedef Bool (*FctPtr)(); typedef struct { char *name; FctPtr fct; }InfCmd; /*---------------------------------*/ /* Global Variables */ /*---------------------------------*/ static AtomInf *atom_debug; static AtomInf *atom_nodebug; static AtomInf *atom_trace; static AtomInf *atom_call; static AtomInf *atom_exit; static AtomInf *atom_fail; static AtomInf *atom_redo; static AtomInf *debug_mode; static RunInf *debug_stack=NULL; static RunInf *end_debug_stack; static RunInf *top_stack; static RunInf *top_env; static int invoc_nb; static char *spy_tbl; static int skip_invoc_nb; static Bool leap_mode; static Bool exact_trace; static int wam_curr_inst; static int wam_next_inst; static int leash_option; static int depth; static Bool redo; static Bool catch_fail; static int nb_read_arg; static char read_arg[30][80]; static char *envir_name[]=ENVIR_NAMES; static char *choice_name[]=CHOICE_NAMES; static char *trail_tag_name[]=TRAIL_TAG_NAMES; static WamWord reg_copy[NB_OF_REGS]; /*---------------------------------*/ /* Function Prototypes */ /*---------------------------------*/ static RunInf *Find_Non_Determin_Env (RunInf *top,WamWord *b); static void Call_Port (AtomInf *atom,int arity,PDbgTyp type); static void Exit_Port (Bool from_dynamic); static void Fail_Port (void); static void Redo_Port (void); static void Read_Command (int port,Bool read_cmd,char *str_next_inst); static void Scan_Command (char *source_str); static FctPtr Find_Function (void); static Bool Creep (void); static Bool Skip (int port); static Bool Leap (void); static Bool Abort (void); static Bool Goals_GoalsB (void); static void One_Goal (int nb,RunInf *top_last_e, RunInf *top_caller_e,WamWord *b); static Bool Leash (void); static Bool NoDebug (void); static Bool Debugging (void); static Bool Spy_NoSpy_NoSpyAll (void); static Bool Exec_Prolog_Goal (void); static Bool Depth (void); static Bool Exact_NoExact (void); static Bool Write_Data_Modify (void); static Bool Where (void); static Bool Dereference (void); static Bool Environment (void); static Bool Backtrack (void); static WamWord *Read_Bank_Adr (Bool only_stack,int arg_nb, char **bank_name); static int Read_Integer (int arg_nb); static void Print_Bank_Name_Offset(char *prefix,char *bank_name,int offset); static void Print_Wam_Word (WamWord *word_adr); static void Modify_Wam_Word (WamWord *word_adr); static WamWord *Detect_Stack (WamWord *adr,char **stack_name); static Bool Instruction (void); static Bool Help (void); #define math_max(x,y) (((x)>(y)) ? (x) : (y)) #define Y_Storing_Invoc_Nb(e) (Y(e,3)) /* see call.pl */ /*-------------------------------------------------------------------------*/ /* INIT_DEBUGGER */ /* */ /*-------------------------------------------------------------------------*/ void Init_Debugger(void) { char *p; int x=DEFAULT_DEBUG_STACK_SZ; if (debug_stack==NULL) { p=(char *) Lib1(getenv,DEBUG_STACK_ENV_VAR_NAME); if (p && *p) { x=Lib1(atoi,p); x=KBytes_To_Wam_Words(x); } if ((debug_stack=(RunInf *) Lib1(malloc,x*sizeof(WamWord)))==NULL) Fatal_Error(ERR_ALLOC_DEBUG); end_debug_stack=(RunInf *) ((WamWord *) debug_stack+x); spy_tbl=Hash_Table(MAX_SPY_TBL_SIZE,sizeof(long),sizeof(long)); if (spy_tbl==NULL) Fatal_Error(ERR_ALLOC_DEBUG); atom_debug =Create_Atom("debug"); atom_nodebug=Create_Atom("nodebug"); atom_trace =Create_Atom("trace"); atom_call =Create_Atom("call"); atom_exit =Create_Atom("exit"); atom_fail =Create_Atom("fail"); atom_redo =Create_Atom("redo"); } top_stack=top_env=debug_stack; top_env->atom =Create_Atom("????????"); /* dummy env */ top_env->arity =0; top_env->type =EXTERNAL; top_env->cp =NULL; top_env->e =NULL; top_env->b =NULL; top_env->indice_nb=0; invoc_nb=1; debug_mode =atom_nodebug; leap_mode =FALSE; skip_invoc_nb=0; exact_trace =FALSE; wam_curr_inst=0; wam_next_inst=0; depth =10; leash_option =CALL|EXIT|FAIL|REDO; redo =FALSE; catch_fail =FALSE; } /*-------------------------------------------------------------------------*/ /* DEBUG_SET_MODE */ /* */ /*-------------------------------------------------------------------------*/ Bool Debug_Set_Mode(AtomInf *mode) { if (mode!=atom_debug && mode!=atom_trace && mode!=atom_nodebug) return FALSE; top_stack=top_env=debug_stack; leap_mode=(mode==atom_debug); /* always to reinitialize */ skip_invoc_nb=0; invoc_nb =1; wam_curr_inst=0; wam_next_inst=0; redo =FALSE; catch_fail =FALSE; if (mode!=debug_mode) { debug_mode=mode; Debug_Display_Mode(); } return TRUE; } /*-------------------------------------------------------------------------*/ /* DEBUG_GET_MODE */ /* */ /*-------------------------------------------------------------------------*/ AtomInf *Debug_Get_Mode(void) { return debug_mode; } /*-------------------------------------------------------------------------*/ /* DEBUG_CLAUSE */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Clause(void) { if (debug_mode==atom_nodebug) return; if (redo && exact_trace) Redo_Port(); } /*-------------------------------------------------------------------------*/ /* DEBUG_BODY */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Body(void) { if (debug_mode==atom_nodebug) return; catch_fail=TRUE; if (redo && !exact_trace) Redo_Port(); } /*-------------------------------------------------------------------------*/ /* DEBUG_CALL */ /* */ /* name==NULL if called predicate is dynamic (A(0) contains the pred) */ /* debug_level: -1 (don't know) 0/1/2 (no/only Prolog/Prolog + WAM insts)*/ /* (not used if called predicate is dynamic) */ /*-------------------------------------------------------------------------*/ void Debug_Call(char *name,int arity,int debug_level) { AtomInf *atom; PredInf *pred; if (debug_mode==atom_nodebug) return; if (name==NULL) { Call_Port(NULL,arity,DYNAMIC); return; } atom=Create_Atom(name); if (debug_level== -1) /* then the pred is static and public */ { pred=Lookup_Pred(atom,arity,0); debug_level=module_tbl[pred->owner_mod_nb].debug_level; } Call_Port(atom,arity,(debug_level) ? DEBUGGED : EXTERNAL); } /*-------------------------------------------------------------------------*/ /* DEBUG_PROCEED */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Proceed(Bool from_dynamic) { if (debug_mode==atom_nodebug) return; Exit_Port(from_dynamic); } /*-------------------------------------------------------------------------*/ /* DEBUG_FAIL */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Fail(void) { if (debug_mode==atom_nodebug) return; if (exact_trace || catch_fail || top_env->b>=B) Fail_Port(); } /*-------------------------------------------------------------------------*/ /* DEBUG_DYNAMIC_BODY */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Dynamic_Body(void) { int dyn_invoc_nb; RunInf *top_bkt; if (debug_mode==atom_nodebug) return; dyn_invoc_nb=Y_Storing_Invoc_Nb(E); if (top_env->invoc_nb==dyn_invoc_nb && top_env->x.first_clause) { /* first time */ top_env->x.first_clause=FALSE; return; } top_bkt=top_stack; while(top_bkt->invoc_nb!=dyn_invoc_nb) top_bkt=top_bkt->last_env; while(top_env>debug_stack && top_env>top_bkt) { Read_Command(FAIL,TRUE,NULL); top_env=top_env->caller_env; } top_env=top_bkt; invoc_nb=top_env->invoc_nb+1; Read_Command(REDO,TRUE,NULL); } /*-------------------------------------------------------------------------*/ /* DEBUG_HAS_FAILED_REDO */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Has_Failed_Redo(void) { /* used by call/1 */ RunInf *top_bkt; if (debug_mode==atom_nodebug) return; top_bkt=Find_Non_Determin_Env(top_stack,B+1); /* choice point deleted */ if (top_bkt==debug_stack) top_bkt=top_env; if (top_bkt==debug_stack) { Lib1(printf,"Not enough debug information at Fail Port\n"); return; } while(top_env>debug_stack && top_env>=top_bkt) { Read_Command(FAIL,TRUE,NULL); top_env=top_env->caller_env; } top_env=top_bkt; invoc_nb=top_env->invoc_nb+1; redo=FALSE; Read_Command(REDO,TRUE,NULL); } /* synchronize with non debugged pred (after call/return/fail) */ /*-------------------------------------------------------------------------*/ /* DEBUG_PRED */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Pred(char *name,int arity) { AtomInf *atom; if (debug_mode==atom_nodebug) return; if (top_env->type!=DEBUGGED) { atom=Create_Atom(name); Call_Port(atom,arity,DEBUGGED); } } /*-------------------------------------------------------------------------*/ /* DEBUG_SUB_PRED */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Sub_Pred(char *name,int arity) { RunInf *top; if (debug_mode==atom_nodebug) return; top=top_stack; while(top>debug_stack && (top->cp!=CP || top->e!=E)) top=top->last_env; if (top==debug_stack || toptype==DEBUGGED) return; if (top>top_env) { /* fail/redo in outside */ top_env=top; invoc_nb=top_env->invoc_nb+1; Read_Command(REDO,FALSE,NULL); } /* proceed from outside */ Exit_Port(FALSE); } /*-------------------------------------------------------------------------*/ /* DEBUG_RETRY */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Retry(void) { if (debug_mode==atom_nodebug) return; if (top_env->type!=DEBUGGED) /* fail from outside */ Fail_Port(); } /*-------------------------------------------------------------------------*/ /* DEBUG_WAM_INST */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Wam_Inst(char *str_next_inst) { if (++wam_curr_inst!=wam_next_inst) return; Read_Command(WAMI,TRUE,str_next_inst); } /*-------------------------------------------------------------------------*/ /* FIND_NON_DETERMIN_ENV */ /* */ /*-------------------------------------------------------------------------*/ static RunInf *Find_Non_Determin_Env(RunInf *top,WamWord *b) { while(top->b >= b) top=top->last_env; return top; } /*-------------------------------------------------------------------------*/ /* CALL_PORT */ /* */ /* if type==DYNAMIC A(0) contains the called predicate */ /*-------------------------------------------------------------------------*/ static void Call_Port(AtomInf *atom,int arity,PDbgTyp type) { RunInf *top,*cur_top; WamWord *adr; int indice_nb; char *p=NULL; int i; while(top_env>debug_stack && top_env->type==EXTERNAL) { /* the caller cannot be EXTERNAL */ Read_Command(EXIT,TRUE,NULL);/* so they have suceeded (dynamic calls) */ top_env=top_env->caller_env; } indice_nb=top_env->indice_nb+1; top_stack=Find_Non_Determin_Env(top_stack,B); cur_top=math_max(top_stack,top_env); top=(RunInf *) ((WamWord *) (cur_top+1)+cur_top->arity); if (top>=end_debug_stack) Fatal_Error(ERR_DEBUG_STACK_OVERFLOW); if (type==DYNAMIC) atom=Get_Functor_Arity(A(0),&arity,&adr); /* init atom */ else p=(char *) Lib2(strchr,atom->name,'$'); top->last_env =cur_top; top->caller_env=top_env; top->atom =atom; top->arity =arity; top->type =type; top->aux_pred =(p!=NULL && Lib3(strncmp,p,"$aux",4)==0 && type!=DYNAMIC); top->cp =CP; top->e =E; top->b =B; top->invoc_nb =invoc_nb++; top->indice_nb =indice_nb; if (type!=DYNAMIC) { if (top->arity>0) { top->x.f_n=Functor_Arity(top->atom,top->arity); top->word=Tag_Value(STC,&(top->x.f_n)); adr=(WamWord *) (top+1); for(i=0;iarity;i++) *adr++ = X(i); } else top->word=Tag_Value(CST,top->atom); } else { Y_Storing_Invoc_Nb(E)=top->invoc_nb; /* see call.{pl,usr} */ top->word=A(0); top->x.first_clause=TRUE; } top_stack=top_env=top; catch_fail=FALSE; redo=FALSE; Read_Command(CALL,TRUE,NULL); } /*-------------------------------------------------------------------------*/ /* EXIT_PORT */ /* */ /*-------------------------------------------------------------------------*/ static void Exit_Port(Bool from_dynamic) { Bool last; int dyn_invoc_nb; redo=FALSE; if (!from_dynamic) while(top_env>debug_stack && top_env->cp==CP && top_env->e==E) { Read_Command(EXIT,TRUE,NULL); top_env=top_env->caller_env; } else { dyn_invoc_nb=Y_Storing_Invoc_Nb(E); do { Read_Command(EXIT,TRUE,NULL); last=(top_env->invoc_nb==dyn_invoc_nb); top_env=top_env->caller_env; } while(!last); } } /*-------------------------------------------------------------------------*/ /* FAIL_PORT */ /* */ /*-------------------------------------------------------------------------*/ static void Fail_Port(void) { RunInf *top_bkt; top_bkt=Find_Non_Determin_Env(top_stack,B); if (top_bkt==debug_stack) top_bkt=top_env; if (top_bkt==debug_stack) { Lib1(printf,"Not enough debug information at Fail Port\n"); return; } redo=TRUE; while(top_env>debug_stack && top_env>=top_bkt) { Read_Command(FAIL,TRUE,NULL); top_env=top_env->caller_env; } top_env=top_bkt; invoc_nb=top_env->invoc_nb+1; } /*-------------------------------------------------------------------------*/ /* REDO_PORT */ /* */ /*-------------------------------------------------------------------------*/ static void Redo_Port(void) { redo=FALSE; Read_Command(REDO,TRUE,NULL); } /*-------------------------------------------------------------------------*/ /* READ_COMMAND */ /* */ /*-------------------------------------------------------------------------*/ static void Read_Command(int port,Bool read_cmd,char *str_next_inst) { FctPtr command; char c_spy; Bool disp_full_term; char *port_name; char str[80]; long key; if (debug_mode==atom_nodebug || wam_curr_instatom,top_env->arity); c_spy=(Hash_Fast_Find_Int(spy_tbl,key)) ? '+' : ' '; if (leap_mode && c_spy==' ') return; if (skip_invoc_nb>0) /* skip */ { if (top_env->invoc_nb!=skip_invoc_nb) return; if (port!=EXIT && (port!=FAIL || B>top_env->b)) return; } if (!exact_trace && top_env->aux_pred) return; if (read_cmd && port!=WAMI && !(leash_option & port) && !leap_mode && skip_invoc_nb==0) read_cmd=FALSE; leap_mode =FALSE; skip_invoc_nb=0; wam_next_inst=0; switch(port) { case CALL: port_name="Call"; disp_full_term=TRUE; break; case EXIT: port_name="Exit"; disp_full_term=TRUE; break; case FAIL: port_name="Fail"; /* disp_full_term=TRUE; */ disp_full_term=(top_env->type!=DYNAMIC); break; case REDO: port_name="Redo"; disp_full_term=(exact_trace && top_env->type!=EXTERNAL); break; } if (port!=WAMI) { Lib5(printf," %c %4d %4d %s: ",c_spy,top_env->invoc_nb, top_env->indice_nb,port_name); if (top_env->type==EXTERNAL) Lib1(printf,"(external) "); if (disp_full_term) Complex_Write_Term(stdout,depth,FALSE,TRUE,TRUE,top_env->word); else Lib3(printf,"%s/%d",top_env->atom->name,top_env->arity); } else Lib3(printf,"Wam Inst. (%5d) : %s",wam_curr_inst,str_next_inst); if (!read_cmd) { Lib1(printf,"\n"); return; } Lib1(printf," ? "); *str='\0'; Lib3(fgets,str,sizeof(str),stdin); str[strlen(str)-1]='\0'; if (*str=='\0') Lib2(strcpy,str,"creep"); Scan_Command(str); if ((command=Find_Function())==NULL || !(*command)(port)) Read_Command(port,TRUE,str_next_inst); } /*-------------------------------------------------------------------------*/ /* SCAN_COMMAND */ /* */ /*-------------------------------------------------------------------------*/ static void Scan_Command(char *source_str) { char str[80]; char *p,*q; Lib2(strcpy,str,source_str); nb_read_arg=0; p=(char *) Lib2(strtok,str,SEPARATOR_LIST); while(p) { q=p; p=(char *) Lib2(strtok,NULL,SEPARATOR_LIST); Lib2(strcpy,read_arg[nb_read_arg++],q); } } /*-------------------------------------------------------------------------*/ /* FIND_FUNCTION */ /* */ /*-------------------------------------------------------------------------*/ static FctPtr Find_Function(void) { int lg; int i; static InfCmd cmd[]= { { "creep", Creep }, { "skip", Skip }, { "leap", Leap }, { "abort", Abort }, { "goalsb", Goals_GoalsB }, { "gb", Goals_GoalsB }, { "leash", Leash }, { "nodebug", NoDebug }, { "notrace", NoDebug }, { "=", Debugging }, { "+", Spy_NoSpy_NoSpyAll }, { "-", Spy_NoSpy_NoSpyAll }, { "@", Exec_Prolog_Goal }, { "<", Depth }, { "exact", Exact_NoExact }, { "noexact", Exact_NoExact }, { "write", Write_Data_Modify }, { "data", Write_Data_Modify }, { "modify", Write_Data_Modify }, { "where", Where }, { "deref", Dereference }, { "envir", Environment }, { "backtrack", Backtrack }, { "instruction", Instruction }, { "help", Help } }; if (nb_read_arg==0) return NULL; lg=Lib1(strlen,read_arg[0]); for(i=0;iinvoc_nb : Lib1(atoi,read_arg[1]); if (invoc==top->invoc_nb && (port==EXIT || port==FAIL) && invoc==top->invoc_nb) { Lib1(printf,"Option not applicable at this port\n"); return FALSE; } if (invocinvoc_nb) { while(top>debug_stack && top->invoc_nb>invoc) top=top->caller_env; if (top->invoc_nb!=invoc) { Lib1(printf,"Incorrect invocation number (try goals)\n"); return FALSE; } Lib1(printf,"Skip backward\n"); } else if (invoc>top->invoc_nb) Lib1(printf,"Skip forward\n"); skip_invoc_nb=invoc; return TRUE; } /*-------------------------------------------------------------------------*/ /* LEAP */ /* */ /*-------------------------------------------------------------------------*/ static Bool Leap(void) { leap_mode=TRUE; return TRUE; } /*-------------------------------------------------------------------------*/ /* ABORT */ /* */ /*-------------------------------------------------------------------------*/ static Bool Abort(void) { Prototype(Prefix(Pred_Name(ABORT,0))) Execute_A_Continuation((CodePtr) Prefix(Pred_Name(ABORT,0))); } /*-------------------------------------------------------------------------*/ /* GOALS_GOALSB */ /* */ /*-------------------------------------------------------------------------*/ static Bool Goals_GoalsB(void) { int nb= -1; if (nb_read_arg>1) nb=Lib1(atoi,read_arg[1]); Lib1(printf,"Ancestors:\n"); if (Lib2(strchr,read_arg[0],'b')==NULL) One_Goal(nb,NULL,top_env,NULL); else One_Goal(nb,Find_Non_Determin_Env(top_stack,B),top_env,B); Lib1(printf,"\n"); return FALSE; } /*-------------------------------------------------------------------------*/ /* ONE_GOAL */ /* */ /*-------------------------------------------------------------------------*/ static void One_Goal(int nb,RunInf *top_bkt_e,RunInf *top_caller_e, WamWord *b) { RunInf *top; int nb_chc_pnt=0; Bool disp_env; top=math_max(top_bkt_e,top_caller_e); if (top==debug_stack || nb==0) return; while(b>top->b) { b=(WamWord *) BB(b); nb_chc_pnt++; } if (top==top_bkt_e) top_bkt_e=Find_Non_Determin_Env(top_bkt_e,b); if (top==top_caller_e) { disp_env=TRUE; top_caller_e=top->caller_env; } else disp_env=FALSE; One_Goal(--nb,top_bkt_e,top_caller_e,b); if (!exact_trace && top->aux_pred) return; if (nb_chc_pnt==0) Lib1(printf," "); else Lib2(printf,"%2d ",nb_chc_pnt); Lib3(printf,"%4d %4d ",top->invoc_nb,top->indice_nb); if (disp_env) Complex_Write_Term(stdout,depth,FALSE,TRUE,TRUE,top->word); else Lib3(printf," %s/%d",top->atom->name,top->arity); Lib1(printf,"\n"); } /*-------------------------------------------------------------------------*/ /* LEASH */ /* */ /*-------------------------------------------------------------------------*/ static Bool Leash(void) { int i; Debug_Add_Leash_Mode(NULL); for(i=1;iname,arity); pkey=(WamWord *) Hash_Lookup(spy_tbl,(char *) pkey,H_NEXT); } if (nb_spy==0) Lib1(printf,"There are no spypoints\n"); Lib1(printf,"\n"); } /*-------------------------------------------------------------------------*/ /* DEBUG_DISPLAY_MODE */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Display_Mode(void) { char *s; if (debug_mode==atom_debug) s="The debugger will first leap -- showing spypoints (debug)\n"; if (debug_mode==atom_trace) s="The debugger will first creep -- showing everything (trace)\n"; if (debug_mode==atom_nodebug) s="The debugger is switched off\n"; Lib1(printf,s); } /*-------------------------------------------------------------------------*/ /* DEBUG_DISPLAY_LEASHING */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Display_Leashing(void) { Bool first=TRUE; if (leash_option==0) Lib1(printf,"No leashing\n"); else { Lib1(printf,"Using leashing stopping at "); first=TRUE; if (leash_option & CALL) Lib2(printf,"%ccall",first ? '[' : ','), first=FALSE; if (leash_option & EXIT) Lib2(printf,"%cexit",first ? '[' : ','), first=FALSE; if (leash_option & FAIL) Lib2(printf,"%cfail",first ? '[' : ','), first=FALSE; if (leash_option & REDO) Lib2(printf,"%credo",first ? '[' : ','), first=FALSE; Lib1(printf,"] ports\n"); } } /*-------------------------------------------------------------------------*/ /* DEBUG_DISPLAY_EXACT */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Display_Exact(void) { if (exact_trace) Lib1(printf,"trace: exact (showing all visible failures)\n"); else Lib1(printf,"trace: noexact (not showing failures when unifying heads)\n"); } /*-------------------------------------------------------------------------*/ /* SPY_NOSPY_NOSPYALL */ /* */ /*-------------------------------------------------------------------------*/ static Bool Spy_NoSpy_NoSpyAll(void) { AtomInf *atom; int arity; char *p; int i; void (*f)(); if (nb_read_arg==2 && Lib2(strcmp,read_arg[1],"all")==0) Debug_Remove_Spy_Point(NULL,0); else { f=(*read_arg[0]=='+' ) ? Debug_Add_Spy_Point : Debug_Remove_Spy_Point; if (nb_read_arg==1) (*f)(top_env->atom,top_env->arity); else for(i=1;iname,arity); } /*-------------------------------------------------------------------------*/ /* DEBUG_REMOVE_SPY_POINT */ /* */ /*-------------------------------------------------------------------------*/ void Debug_Remove_Spy_Point(AtomInf *atom,int arity) { long key=Functor_Arity(atom,arity); char *s; if (atom==NULL) /* for builtin nospyall/0 in trace.pl */ { Hash_Delete_All(spy_tbl); Lib1(printf,"All spypoints removed\n"); return; } if (Hash_Lookup(spy_tbl,(char *) &key,H_DELETE)) s="Spypoint removed from %s/%d\n"; else s="There is no spypoint on %s/%d\n"; Lib3(printf,s,atom->name,arity); } /*-------------------------------------------------------------------------*/ /* EXEC_PROLOG_GOAL */ /* */ /*-------------------------------------------------------------------------*/ static Bool Exec_Prolog_Goal(void) { Prototype(Prefix(Pred_Name(DBG_EXEC,0))) AtomInf *save_debug_mode=debug_mode; WamWord *save_reg_bank=reg_bank; WamWord local_reg_bank[REG_BANK_SIZE]; Switch_Reg_Bank(local_reg_bank); debug_mode=atom_nodebug; Call_Prolog((CodePtr) Prefix(Pred_Name(DBG_EXEC,0))); debug_mode=save_debug_mode; Switch_Reg_Bank(save_reg_bank); return FALSE; } /*-------------------------------------------------------------------------*/ /* DEPTH */ /* */ /*-------------------------------------------------------------------------*/ static Bool Depth(void) { if (nb_read_arg==1) depth=10; else depth=Lib1(atoi,read_arg[1]); return FALSE; } /*-------------------------------------------------------------------------*/ /* EXACT_NOEXACT */ /* */ /*-------------------------------------------------------------------------*/ static Bool Exact_NoExact(void) { exact_trace= *read_arg[0]=='e'; Debug_Display_Exact(); return FALSE; } /*-------------------------------------------------------------------------*/ /* WRITE_DATA_MODIFY */ /* */ /*-------------------------------------------------------------------------*/ static Bool Write_Data_Modify(void) { WamWord *adr; char *bank_name; int offset; int nb; int i; if (adr=Read_Bank_Adr(FALSE,1,&bank_name)) { offset=(nb_read_arg<3) ? 0 : Read_Integer(2); nb =(nb_read_arg<4) ? 1 : Read_Integer(3); if (adr==reg_copy) { if (offset>=NB_OF_REGS) offset=0; if (nb_read_arg<4 && *read_arg[0]!='m') nb=NB_OF_REGS-offset; else if (nb>NB_OF_REGS-offset) nb=NB_OF_REGS-offset; } while(nb--) { Print_Bank_Name_Offset((adr==reg_copy) ? reg_tbl[offset] : "", bank_name,offset); Lib1(printf,":"); if (*read_arg[0]=='w') Complex_Write_Term(stdout,depth,FALSE,TRUE,TRUE,adr[offset]); else { Print_Wam_Word(adr+offset); if (*read_arg[0]=='m') Modify_Wam_Word(adr+offset); } Lib1(printf,"\n"); offset++; } } if (adr==reg_copy) /* saved by Read_Bank_Adr */ for(i=0;i \n"); Print_Bank_Name_Offset("",stack_name,d_adr-adr); Lib1(printf,":"); } Print_Wam_Word(d_adr); Lib1(printf,"\n"); } return FALSE; } /*-------------------------------------------------------------------------*/ /* ENVIRONMENT */ /* */ /*-------------------------------------------------------------------------*/ static Bool Environment(void) { WamWord *adr; int offset; char *stack_name; int i; if (nb_read_arg==1) { adr=Detect_Stack(E,&stack_name); offset=E-adr; adr=E; } else { if ((adr=Read_Bank_Adr(TRUE,1,&stack_name))==NULL) return FALSE; offset=(nb_read_arg<3) ? 0 : Read_Integer(2); adr+=offset; } for(i=ENVIR_STATIC_SIZE;i>0;i--) { Print_Bank_Name_Offset(envir_name[i-1],stack_name,offset-i); Lib1(printf,":"); Print_Wam_Word(adr-i); Lib1(printf,"\n"); } return FALSE; } /*-------------------------------------------------------------------------*/ /* BACKTRACK */ /* */ /*-------------------------------------------------------------------------*/ static Bool Backtrack(void) { WamWord *adr; int offset; char *stack_name; int i; if (nb_read_arg==1) { adr=Detect_Stack(B,&stack_name); offset=B-adr; adr=B; } else { if ((adr=Read_Bank_Adr(TRUE,1,&stack_name))==NULL) return FALSE; offset=(nb_read_arg<3) ? 0 : Read_Integer(2); adr+=offset; } for(i=CHOICE_STATIC_SIZE;i>0;i--) { Print_Bank_Name_Offset(choice_name[i-1],stack_name,offset-i); Lib1(printf,":"); Print_Wam_Word(adr-i); Lib1(printf,"\n"); } return FALSE; } /*-------------------------------------------------------------------------*/ /* READ_BANK_ADR */ /* */ /*-------------------------------------------------------------------------*/ static WamWord *Read_Bank_Adr(Bool only_stack,int arg_nb,char **bank_name) { int lg; int offset; int i; if (nb_read_argBANK_NAME_OFFSET_LENGTH) lg=BANK_NAME_OFFSET_LENGTH-1; Lib4(printf,"%*s%s",BANK_NAME_OFFSET_LENGTH-lg,"",str); } /*-------------------------------------------------------------------------*/ /* PRINT_WAM_WORD */ /* */ /*-------------------------------------------------------------------------*/ static void Print_Wam_Word(WamWord *word_adr) { WamWord word= *word_adr; WamWord tag; WamWord value; char *stack_name; WamWord *adr; AtomInf *functor; int arity; Lib5(printf,"%#*lx %*ld ",HEXADECIMAL_LENGTH,(long) word, DECIMAL_LENGTH, (long) word); if (adr=Detect_Stack((WamWord *) word,&stack_name)) Print_Bank_Name_Offset("",stack_name,(WamWord *) word-adr); else Lib3(printf,"%*s",BANK_NAME_OFFSET_LENGTH,"?[?]"); Lib1(printf," "); tag=Tag_Of(word); if (tagname); else Lib4(printf,"%s,%#*lx",tag_tbl[tag].name, VALUE_PART_LENGTH,(long) value); break; } } else tag= -1; if (tag== -1) Lib3(printf,"???,%*s",VALUE_PART_LENGTH,"?"); Lib1(printf," "); if (word_adr>=Trail_Stack && word_adr=0 && arity<=MAX_ARITY) Lib3(printf,"%12s/%-3d",functor->name,arity); } /*-------------------------------------------------------------------------*/ /* MODIFY_WAM_WORD */ /* */ /*-------------------------------------------------------------------------*/ static void Modify_Wam_Word(WamWord *word_adr) { WamWord word; char *bank_name; WamWord *adr; int offset; char str[80]; char *comma; char *slash; char *p; int i; for(;;) { Lib1(printf,"\nNew value: "); *str='\0'; Lib3(fgets,str,sizeof(str),stdin); str[strlen(str)-1]='\0'; if (*str=='\0') return; Scan_Command(str); if (comma=(char *) Lib2(strchr,str,',')) goto tag_value; if (slash=(char *) Lib2(strchr,read_arg[0],'/')) goto functor_arity; integer: if (nb_read_arg==1 && *read_arg[0]>='0' && *read_arg[0]<='9') { word=Lib3(strtol,read_arg[0],&p,0); if (*p=='\0') { *word_adr=word; return; } else goto err; } stack_adr: if (adr=Read_Bank_Adr(TRUE,0,&bank_name)) { offset=(nb_read_arg<2) ? 0 : Read_Integer(1); *word_adr=(WamWord) (adr+offset); return; } goto err; tag_value: comma++; for(i=0;iMAX_ARITY) goto err; word=Lib3(strtol,read_arg[0],&p,0); if (*p!='\0') word=(long) Create_Allocate_Atom(read_arg[0]); else if (!Hash_Is_An_Element(atom_tbl,(char *) word)) goto err; *word_adr=Functor_Arity(word,i); Lib3(printf,"--> %s/%d",((AtomInf *) word)->name,i); return; err: Lib1(printf,"Error..."); } } /*-------------------------------------------------------------------------*/ /* DETECT_STACK */ /* */ /*-------------------------------------------------------------------------*/ static WamWord *Detect_Stack(WamWord *adr,char **stack_name) { int i; for(i=0;i=stk_tbl[i].stack && adr skip and stop at return of the invocated pred") L("leap resume running (only stopping on spy-points)") L("abort abort the current execution") L("goals print ancestor goals") L("goalsb print ancestor goals and choice points") L("leash ... set the leashing mode to (call/exit/fail/redo)") L("nodebug switch the debugger off") L("notrace equivalent to nodebug") L("= output information concerning the debugger") L("+ ... place a spy-point on each (or current)") L("- ... remove spy-point on each (or current)") L("@ call arbitrary Prolog goal") L("< set the print depth limit to (or reset)") L("exact trace all failures (and auxiliary predicates)") L("noexact do not trace fail when unifying the head") L("") L("Wam level") L("") L("write adr write Prolog terms starting at ") L("data adr display words starting at ") L("modify adr display and modify words starting at ") L("where sadr display the exact address corresponding to ") L("deref adr display the dereferenced word started at ") L("envir display an environment located at (or current)") L("backtrack display a choice point located at (or current)") L("instruction execute one instruction or until instruction ") L("") L("An address (adr) has the following syntax: bank_name < [n] >") L(" bank_name is either reg/x/y/stack_name (see below)") L(" n is an optional offset specifier (Integer)") L("") L("A stack address (sadr) has the following syntax: stack_name < [n] >") Lib1(printf," stack_name is either"); for(i=0;i