1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/* 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 <stdlib.h>
#include <setjmp.h>
#include "siod.h"
#include "siodp.h"
static void
init_trace_version (void)
{
setvar (cintern ("*trace-version*"),
cintern ("$Id: trace.c,v 1.4 2003/12/04 13:21:25 mitch Exp $"),
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 = tc_closure_traced;
}
else if (TYPE (fcn) == tc_closure_traced)
;
else
my_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
my_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
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 ();
}
|