Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

trace-all

3 views
Skip to first unread message

Frode Vatvedt Fjeld

unread,
Dec 6, 2001, 10:21:48 AM12/6/01
to
Myriam Abramson <mabr...@osf1.gmu.edu> writes:

> Could somebody show me how to do a (trace-all) function or macro?
> The code below does not work I guess because trace is a macro and
> quotes its argument.

Perhaps this, untested:

(defun trace-all (function-names)
(dolist (function-name function-names)
(eval `(trace ,function-name))))

I think I would however expect a function named trace-all to trace
_all_ functions, something like

(defun trace-all ()
(do-all-symbols (symbol)
(when (fboundp symbol)
(eval `(trace ,symbol)))))

--
Frode Vatvedt Fjeld

Jochen Schmidt

unread,
Dec 6, 2001, 11:34:30 AM12/6/01
to
Myriam Abramson wrote:

>
> Hi!


>
> Could somebody show me how to do a (trace-all) function or macro?
> The code below does not work I guess because trace is a macro and
> quotes its argument.
>

> (defun trace-all (fns)
> (dolist (fn fns)
> (trace fn)))
>
> Error: `FN' is not fbound
> [condition type: UNDEFINED-FUNCTION]
>
> TIA
>
> myriam

Trace already can get multiple functions

; Trace functions a, b and c
(trace a b c)

But if you want to trace all functions in a given list you could simply do:

(defun trace-all (fns)
(eval `(trace ,@fns)))


ciao,
Jochen

Pierre R. Mai

unread,
Dec 6, 2001, 10:45:41 AM12/6/01
to
Myriam Abramson <mabr...@osf1.gmu.edu> writes:

> Could somebody show me how to do a (trace-all) function or macro?
> The code below does not work I guess because trace is a macro and
> quotes its argument.

Maybe a better way would be to say that it doesn't evaluate its
argument.

> (defun trace-all (fns)
> (dolist (fn fns)
> (trace fn)))

If you really insist on trace-all being a function, then one way
to apply trace would be to use eval:

(defun trace-all (fns)
(dolist (fn fns)

(eval `(trace ,fn))))

Or you could find out what function call trace expands to in your
implementation, and funcall that, but that will not result in portable
code.

That said, trace is already specified to take more than one function
name:

(defun trace-all (fns)
(eval `(trace ,@fns)))

So the only point in your trace-all function seems to be the ability
to invoke it on arguments that are computed at run-time. Is that
correct?

Regs, Pierre.

--
Pierre R. Mai <pm...@acm.org> http://www.pmsf.de/pmai/
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents. -- Nathaniel Borenstein

Coby Beck

unread,
Dec 6, 2001, 4:42:02 PM12/6/01
to

"Frode Vatvedt Fjeld" <fro...@acm.org> wrote in message
news:2hbshci...@dslab7.cs.uit.no...

> Myriam Abramson <mabr...@osf1.gmu.edu> writes:
>
> > Could somebody show me how to do a (trace-all) function or macro?
> > The code below does not work I guess because trace is a macro and
> > quotes its argument.
> [snip]

> I think I would however expect a function named trace-all to trace
> _all_ functions, something like
>
> (defun trace-all ()
> (do-all-symbols (symbol)
> (when (fboundp symbol)
> (eval `(trace ,symbol)))))
>
> --
> Frode Vatvedt Fjeld
>

Which looks like a remarkably bad idea! : )

I think I once did a (trace unread-char) without thinking and...well it was a
problem...
--
Coby
(remove #\space "coby . beck @ opentechgroup . com")


Erik Naggum

unread,
Dec 6, 2001, 5:35:47 PM12/6/01
to
* "Coby Beck" <cb...@mercury.bc.ca>

| I think I once did a (trace unread-char) without thinking and...well it
| was a problem...

It would have been so much nicer if the Common Lisp system had not kept
tracing functions called by the top-level loop itself, but had confined
its tracing to the functions called by direct user request. The user is
unlikely to want to debug the top-level loop, anyway.

///
--
The past is not more important than the future, despite what your culture
has taught you. Your future observations, conclusions, and beliefs are
more important to you than those in your past ever will be. The world is
changing so fast the balance between the past and the future has shifted.

Scott McKay

unread,
Dec 6, 2001, 7:09:47 PM12/6/01
to

"Erik Naggum" <er...@naggum.net> wrote in message
news:32166669...@naggum.net...

> * "Coby Beck" <cb...@mercury.bc.ca>
> | I think I once did a (trace unread-char) without thinking and...well it
> | was a problem...
>
> It would have been so much nicer if the Common Lisp system had not kept
> tracing functions called by the top-level loop itself, but had confined
> its tracing to the functions called by direct user request. The user is
> unlikely to want to debug the top-level loop, anyway.

As it happens, trying to get this to work right was one of the
very first things I tried to do when I was hired in the early days
of Symbolics.

We never did manage to get 'trace' to work completely safely.


Barry Margolin

unread,
Dec 6, 2001, 7:49:48 PM12/6/01
to
In article <32166669...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:
>* "Coby Beck" <cb...@mercury.bc.ca>
>| I think I once did a (trace unread-char) without thinking and...well it
>| was a problem...
>
> It would have been so much nicer if the Common Lisp system had not kept
> tracing functions called by the top-level loop itself, but had confined
> its tracing to the functions called by direct user request. The user is
> unlikely to want to debug the top-level loop, anyway.

Since it's unspecified what functions the top-level loop (or most built-in
functions) calls, I think it would be conforming for an implementation to
disable tracing while inside any of these things. I.e. since the
implementation could call SYSTEM::READ-CHAR and SYSTEM::UNREAD-CHAR instead
of COMMON-LISP:READ-CHAR and COMMON-LISP:UNREAD-CHAR inside the READ
function, there's no reason for the user to expect that tracing these
functions would result in any output from the top-level loop. Even if the
implementation doesn't actually use separate functions for this, it could
act as if it does since the user can't tell the difference.

I think I once crashed a Lisp Machine by tracing the wrong function. :)

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Ole Rohne

unread,
Dec 7, 2001, 5:28:28 AM12/7/01
to
"Coby Beck" <cb...@mercury.bc.ca> writes:

> Which looks like a remarkably bad idea! : )

Unless it accepts a package argument - CMUCL provides something along
those lines for profiling. (trace-all :package "COMMON-LISP") would
still be a remarkable bad idea.

Ole

Duane Rettig

unread,
Dec 6, 2001, 7:58:12 PM12/6/01
to
"Scott McKay" <s...@mediaone.net> writes:

In ruminating over this common malady for Lisp programmers, and
especially for Lisp implementors, I just thought of a great analogy
(yeah, I know, it'll probably look really stupid tomorrow :-) :

Doing self-debugging, especially tracing, on any introspective system
is like tweezing thorns or slivers out of one's own skin.

If you have a thorn or sliver in one of your hands, it is easy to
get it out with a pair of tweezers in the other hand.

If the sliver is in your shoulder, it is a little harder, and you
may need a mirror.

If the sliver is on your neck, you may need two mirrors and a lot
of practice.

Debugging any function that works on *standard-input* is like
trying to get a sliver out from on top of your eyelid (think
about it).

Other languages like C or C++ are philosophically opposed to
tweezing their own slivers; they have someone else (e.g. gdb or dbx)
do the job. How do gdb and dbx do the job? They ask each other,
or have a clone of themselves do it.

[The real answer to tracing unread-char is to only close one
eyelid at a time - redirect *trace-output* to some other stream
that is not *terminal-io*]

--
Duane Rettig Franz Inc. http://www.franz.com/ (www)
1995 University Ave Suite 275 Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)

Barry Margolin

unread,
Dec 7, 2001, 1:47:45 PM12/7/01
to
In article <4vgfjj...@beta.franz.com>,

Duane Rettig <du...@franz.com> wrote:
>Other languages like C or C++ are philosophically opposed to
>tweezing their own slivers; they have someone else (e.g. gdb or dbx)
>do the job. How do gdb and dbx do the job? They ask each other,
>or have a clone of themselves do it.

It's not so much the language as the OS and development environment. I
used to use Multics, which was a PL/I machine, and PL/I is much more like C
than it is like Lisp. However, the operating environment was similar to
Lisp Machines, in that a login session is a single-process address space,
and command invocation was implemented by dynamic linking and calling them
as subroutines, rather than creating an independent process for each
command. The debugger was introspective, much like it is in Lisp
implementations; this meant that if you corrupted some critical parts of
process memory (like the ones that the dynamic linker itself depends on)
you might not be able to run the debugger.

For Lisp Machines, the solution when you need to have "someone else do the
job", the answer is to use the FEP's DDT-style debugger. I once managed to
use it to resurrect a machine after accidentally changing the value of NIL
or T (SETQ had checks to make sure you didn't modify them, but SET didn't
-- Symbolics fixed it in the following release by moving their value cells
to read-only pages).

Duane Rettig

unread,
Dec 7, 2001, 2:19:20 PM12/7/01
to
Barry Margolin <bar...@genuity.net> writes:

> In article <4vgfjj...@beta.franz.com>,
> Duane Rettig <du...@franz.com> wrote:
> >Other languages like C or C++ are philosophically opposed to
> >tweezing their own slivers; they have someone else (e.g. gdb or dbx)
> >do the job. How do gdb and dbx do the job? They ask each other,
> >or have a clone of themselves do it.
>
> It's not so much the language as the OS and development environment. I
> used to use Multics, which was a PL/I machine, and PL/I is much more like C
> than it is like Lisp. However, the operating environment was similar to
> Lisp Machines, in that a login session is a single-process address space,
> and command invocation was implemented by dynamic linking and calling them
> as subroutines, rather than creating an independent process for each
> command. The debugger was introspective, much like it is in Lisp
> implementations; this meant that if you corrupted some critical parts of
> process memory (like the ones that the dynamic linker itself depends on)
> you might not be able to run the debugger.

Hmm. I can see your point, but I still contend that my point is a
language issue, not an OS/environment one. That PL/I system you worked
on had to have implemented an _extension_ of PL/I - it's been a _long_
time since I worked on PL/I, and you can correct me if I'm wrong, but I
don't remember any such self-inspecting capabilities when I worked on
PL/I on the IBM 360).

Compare/contrast that with Common Lisp, which indeed does define all
of the language elements needed to do such self-inspection (e.g. trace,
step, inspect, and it even gives examples for and interactions with
the read-eval-print loop). In a sense, the CL spec defines enough of
the environment _as_ _a_ _language_ to mandate such self-debuggability
without extension.

Barry Margolin

unread,
Dec 7, 2001, 3:13:53 PM12/7/01
to
In article <44rn2k...@beta.franz.com>,

Duane Rettig <du...@franz.com> wrote:
>Barry Margolin <bar...@genuity.net> writes:
>
>> In article <4vgfjj...@beta.franz.com>,
>> Duane Rettig <du...@franz.com> wrote:
>> >Other languages like C or C++ are philosophically opposed to
>> >tweezing their own slivers; they have someone else (e.g. gdb or dbx)
>> >do the job. How do gdb and dbx do the job? They ask each other,
>> >or have a clone of themselves do it.
>>
>> It's not so much the language as the OS and development environment. I
>> used to use Multics, which was a PL/I machine, and PL/I is much more like C
>> than it is like Lisp. However, the operating environment was similar to
>> Lisp Machines, in that a login session is a single-process address space,
>> and command invocation was implemented by dynamic linking and calling them
>> as subroutines, rather than creating an independent process for each
>> command. The debugger was introspective, much like it is in Lisp
>> implementations; this meant that if you corrupted some critical parts of
>> process memory (like the ones that the dynamic linker itself depends on)
>> you might not be able to run the debugger.
>
>Hmm. I can see your point, but I still contend that my point is a
>language issue, not an OS/environment one. That PL/I system you worked
>on had to have implemented an _extension_ of PL/I - it's been a _long_
>time since I worked on PL/I, and you can correct me if I'm wrong, but I
>don't remember any such self-inspecting capabilities when I worked on
>PL/I on the IBM 360).

I'm not sure what you mean by this. There was a command "debug" to get
into the debugger, analogous to Unix "dbx". The implementation of this
just uses PL/I pointer variables to access the parts of memory that are
being used by the program being debugged.

>Compare/contrast that with Common Lisp, which indeed does define all
>of the language elements needed to do such self-inspection (e.g. trace,
>step, inspect, and it even gives examples for and interactions with
>the read-eval-print loop). In a sense, the CL spec defines enough of
>the environment _as_ _a_ _language_ to mandate such self-debuggability
>without extension.

It defines the high-level interfaces, but doesn't define the primitives
needed to implement any of these things. I haven't thought it all through,
but I think a possible implementation technique would be for them to spawn
another process that uses the same mechanisms as gdb/dbx to watch what's
happening in the process being monitored (e.g. the Unix ptrace system
call). If it were done this way, you wouldn't have any problem if you
traced a low-level, internal function.

Duane Rettig

unread,
Dec 7, 2001, 5:04:44 PM12/7/01
to
Barry Margolin <bar...@genuity.net> writes:

dbx (and, I presume, "debug"), are not commands defined by their
implementational languages, but perhaps implemented in them.
CL's trace macro, however, is part of the language, where, though
not highly specified, is in fact specified as a part of the langauge.
A conforming PL/I implementation would get by without offering a
"debug" program, and a conforming C implementation would get by
without providing a "dbx" program, but a CL implementation that
has no "trace" macro defined (in any way) is simply not conforming.
That is what I mean by my statement that it is in fact a language
issue, and not necessarily an os/evironment issue. It's because CL
actually ties down some environment issues as a part of its language
definition.

I don't want to get any more pedantic - it's really a fine point,
in my opinion, and not worth wasting too much time on.

> >Compare/contrast that with Common Lisp, which indeed does define all
> >of the language elements needed to do such self-inspection (e.g. trace,
> >step, inspect, and it even gives examples for and interactions with
> >the read-eval-print loop). In a sense, the CL spec defines enough of
> >the environment _as_ _a_ _language_ to mandate such self-debuggability
> >without extension.
>
> It defines the high-level interfaces, but doesn't define the primitives
> needed to implement any of these things. I haven't thought it all through,
> but I think a possible implementation technique would be for them to spawn
> another process that uses the same mechanisms as gdb/dbx to watch what's
> happening in the process being monitored (e.g. the Unix ptrace system
> call). If it were done this way, you wouldn't have any problem if you
> traced a low-level, internal function.

Yes, this is certainly a possible way to implement these features.
However, since you are then calling on an operating system to
handle some of the implementation, it becomes harder to make the
interface portable. It's hard enough dealing with all those different
hardware architectures as it is...

Barry Margolin

unread,
Dec 7, 2001, 6:19:39 PM12/7/01
to
In article <4zo4ui...@beta.franz.com>,

Duane Rettig <du...@franz.com> wrote:
>That is what I mean by my statement that it is in fact a language
>issue, and not necessarily an os/evironment issue. It's because CL
>actually ties down some environment issues as a part of its language
>definition.

Yes, it's a silly thing to debate, but I'm having fun...

There's a C compiler for Symbolics Lisp Machines. You can trace C
functions because this functionality is provided by the operating
environment, even though the C language doesn't specify anything like this
being available.

Suppose the C language required a debug_me() function. On a Lisp Machine
this would presumably invoke the introspective debugger provided by the
operating environment. On a Unix system I would expect it to fork a new
process and run dbx there.

Common Lisp requires an ED function to invoke an editor. While some CL
implementations have an embedded editor, I think quite a few simply
implement this as an interface to an external editor; the only
introspection involved might be writing the source code of the function to
a temporary file.

0 new messages