blob: 2fd5929755d731a21551f301b5f313574f6c37d9 [file] [log] [blame]
/* COPYRIGHT (c) 1992-1994 BY
* MITECH CORPORATION, ACTON, MASSACHUSETTS.
* See the source file SLIB.C for more information.
(trace procedure1 procedure2 ...)
(untrace procedure1 procedure2 ...)
Currently only user-defined procedures can be traced.
Fancy printing features such as indentation based on
recursion level will also have to wait for a future version.
*/
#include <stdio.h>
#include <setjmp.h>
#include "siod.h"
#include "siodp.h"
static void init_trace_version(void)
{setvar(cintern("*trace-version*"),
cintern("$Id$"),
NIL);}
static long tc_closure_traced = 0;
static LISP sym_traced = NIL;
static LISP sym_quote = NIL;
static LISP sym_begin = NIL;
LISP ltrace_fcn_name(LISP body);
LISP ltrace_1(LISP fcn_name,LISP env);
LISP ltrace(LISP fcn_names,LISP env);
LISP luntrace_1(LISP fcn);
LISP luntrace(LISP fcns);
static void ct_gc_scan(LISP ptr);
static LISP ct_gc_mark(LISP ptr);
void ct_prin1(LISP ptr,struct gen_printio *f);
LISP ct_eval(LISP ct,LISP *px,LISP *penv);
LISP ltrace_fcn_name(LISP body)
{LISP tmp;
if NCONSP(body) return(NIL);
if NEQ(CAR(body),sym_begin) return(NIL);
tmp = CDR(body);
if NCONSP(tmp) return(NIL);
tmp = CAR(tmp);
if NCONSP(tmp) return(NIL);
if NEQ(CAR(tmp),sym_quote) return(NIL);
tmp = CDR(tmp);
if NCONSP(tmp) return(NIL);
return(CAR(tmp));}
LISP ltrace_1(LISP fcn_name,LISP env)
{LISP fcn,code;
fcn = leval(fcn_name,env);
if (TYPE(fcn) == tc_closure)
{code = fcn->storage_as.closure.code;
if NULLP(ltrace_fcn_name(cdr(code)))
setcdr(code,cons(sym_begin,
cons(cons(sym_quote,cons(fcn_name,NIL)),
cons(cdr(code),NIL))));
fcn->type = (short) tc_closure_traced;}
else if (TYPE(fcn) == tc_closure_traced)
;
else
err("not a closure, cannot trace",fcn);
return(NIL);}
LISP ltrace(LISP fcn_names,LISP env)
{LISP l;
for(l=fcn_names;NNULLP(l);l=cdr(l))
ltrace_1(car(l),env);
return(NIL);}
LISP luntrace_1(LISP fcn)
{if (TYPE(fcn) == tc_closure)
;
else if (TYPE(fcn) == tc_closure_traced)
fcn->type = tc_closure;
else
err("not a closure, cannot untrace",fcn);
return(NIL);}
LISP luntrace(LISP fcns)
{LISP l;
for(l=fcns;NNULLP(l);l=cdr(l))
luntrace_1(car(l));
return(NIL);}
static void ct_gc_scan(LISP ptr)
{CAR(ptr) = gc_relocate(CAR(ptr));
CDR(ptr) = gc_relocate(CDR(ptr));}
static LISP ct_gc_mark(LISP ptr)
{gc_mark(ptr->storage_as.closure.code);
return(ptr->storage_as.closure.env);}
void ct_prin1(LISP ptr,struct gen_printio *f)
{gput_st(f,"#<CLOSURE(TRACED) ");
lprin1g(car(ptr->storage_as.closure.code),f);
gput_st(f," ");
lprin1g(cdr(ptr->storage_as.closure.code),f);
gput_st(f,">");}
LISP ct_eval(LISP ct,LISP *px,LISP *penv)
{LISP fcn_name,args,env,result,l;
fcn_name = ltrace_fcn_name(cdr(ct->storage_as.closure.code));
args = leval_args(CDR(*px),*penv);
fput_st(stdout,"->");
lprin1f(fcn_name,stdout);
for(l=args;NNULLP(l);l=cdr(l))
{fput_st(stdout," ");
lprin1f(car(l),stdout);}
fput_st(stdout,"\n");
env = extend_env(args,
car(ct->storage_as.closure.code),
ct->storage_as.closure.env);
result = leval(cdr(ct->storage_as.closure.code),env);
fput_st(stdout,"<-");
lprin1f(fcn_name,stdout);
fput_st(stdout," ");
lprin1f(result,stdout);
fput_st(stdout,"\n");
*px = result;
return(NIL);}
void __stdcall init_trace(void)
{long j;
tc_closure_traced = allocate_user_tc();
set_gc_hooks(tc_closure_traced,
NULL,
ct_gc_mark,
ct_gc_scan,
NULL,
&j);
gc_protect_sym(&sym_traced,"*traced*");
setvar(sym_traced,NIL,NIL);
gc_protect_sym(&sym_begin,"begin");
gc_protect_sym(&sym_quote,"quote");
set_print_hooks(tc_closure_traced,ct_prin1);
set_eval_hooks(tc_closure_traced,ct_eval);
init_fsubr("trace",ltrace);
init_lsubr("untrace",luntrace);
init_trace_version();}