[Openmcl-devel] Windows versions of CCL available for smoke-testing

Gary Byers gb at clozure.com
Fri Oct 10 20:25:18 PDT 2008

On Thu, 9 Oct 2008, Alexander Repenning wrote:

> Hi Gary,
> this is exciting news. In our case we really would like the Mac32/64 + 
> Win32/64 Lisps but our tire kicking activity would be to try to get OpenGL 
> and QuickTime to work on Windows. Sounds like the win32 version may be still 
> to shaky for this kind of stress test?

I don't know about stress/shakiness (there's one way to find out ...).
In order to create a window to draw in (whether via OpenGL or other
means), you have to be able to define (at least) a function that 
receives events ("messages").  For historical reasons (i.e, reasons
that haven't made sense since 1985 or so), most Win32 (and Win32-callable)
functions follow Pascal calling conventions (functions receive a fixed
number of arguments on the stack and the callee pops them off before
returning) rather than C calling conventions (the caller allocates and
eventually deallocates stack space for outgoing arguments, and the 
callee leaves the stack pointer pointing where it pointed on entry.)
I think that MCL used to have DEFPASCAL and DEF-C-CALLABLE (sp?) back
in the day, for this reason.  It stopped making sense when the 68K
stopped being interesting; this really just has to do with differences
between C and Pascal calling conventions as of the mid 1980s, but it
pervasively affects Win32.

CCL:DEFCALLBACK only really understands how to generate functions that
can be called from code following C conventions.  It needs to be
extended somehow - maybe

(defcallback foo :pascal (...)

or, half-seriously

(defpascall foo (..)

> Is there a plan to have SLIME work 
> with win32

Yes.  There are still socket-related bugs that keep it from getting
very far.

> and will there be a precompiled .exe version of ccl/win32?


was announced a few days ago (your message is responding to that announcement.)

> Is there already or will there be a mechanism similar to the trap

The following - in []s - isn't directly responsive.  When I was
younger and heard old people go off on weird tangents like this,
I promised myself that I'd never do it.  All I can say is that
anyone reading this will be old someday, too.

[For anyone reading this who may not be familiar with the term: 68K
instructions were sequences of one or more 16-bit words (where the
first word generally determined the class of instruction and any
subsequent words encoded operands.)  The high 4 bits of the first
word could sometimes fully determine the instruction - for some
reason, I still remember that #x7xxx was a "movq" instruction -
and sometimes it was necessary to decode other bits (#x4ed0 was
"jmp (a0)"; #x4e75 was "rts", and ... well, that's about all that
I remember.)

68K instructions whose high nibble was #xa (#xAxxx) were explicitly
undefined by Motorola, and (on early, memory-constrained Macs) Apple
used these undefined/illegal instructions as a means of accessing
OS and ToolBox (GUI) functionality.  (Your application was basically
its own code and a bunch of "A-traps" that manipulated files, windows,
events, etc.; shared libraries were just a gleam in someone's eye.)

MCL naturally shipped with what was at some point in time a fairly
complete set of "trap definitions".  This wss originally generated
by hand; later, a tool written by (IIRC) Joe Chung and Mike Travers
parsed Pascal header files into lisp-readable definitions.

The other 12 bits in an A-trap could have encoded 4K different system
services, but Apple used some of the bits in the opcode to encode
other functionality.  (Some bit - I don't remember which one -
controlled whether an I/O operation was to be perfomed synchronously
or asynchronously.)  The total number of unique services that could
be invoked via the A-trap mechanism was several hundred (and most of
those were defined in the original MacOS.)  Extending the mechanism
to add new functionality was a complicated process; since much of
the code that implemented these services was in ROM, patching around
bugs often involved incredible hair. ("Function FOO is generally OK,
except for the fact that it misbehaves when called from a certain
point in BAR.  So, let's redefine the A-trap used to invoke FOO and
have it look at the return address; if that address isn't in BAR,
jump back to the original code, otherwise ...")  This is known as
using "come from" statements, and they're generally considered harmful.

Apple realized what a mess this was, and started to work on replacing
it with shared library technology.  As I recall, what they'd tried to
do on the 68K wasn't very good; around this time, they switched to
the PPC and introduced fairly reasonable shared-library technology
(the "Code Fragment Manager").  The PPC never used illegal instructions
to access system services (at least not in a user-visible way.)

I think that MCL continued to (informally) refer to foreign function
calls as "traps".  I understand that when MCL users use the term
"trap" they're using the term in this informal sense, but please
understand that for some of us hearing the word "trap" in this
context invokes vivid and often unsettling flashbacks.]


> mechanism on Mac for OS X calls to parse header files to turn them
> automagically into defcallbacks (or whatever they will be called)?

Yes; the same mechanism is used on Windows as on other platforms.
(As mentioned above, callbacks - lisp functions that arrange to
be called from foreign code - sometimes have to follow Pascal
calling conventions on Win32, and some way of implementing such
callbacks has to be developed.)

Anyone looking at Windows C code might see that some functions
have a "cdecl" attribute - spelled in a variety of ways - and
others have some variant of "stdcall".  "stdcall" = "Pascal as
of the mid 1980s" and "cdecl" means "like most C compilers.
Windows headers often use other C macros to make the intent a
little more clear, like:

int WINAPI foo (...);


void CALLBACK bar (...);

and both WINAPI and CALLBACK ultimately mean "welcome to 1985,
clean up the stack on your way out."

Because of the way that CCL does foreign function calls, it doesn't
really care what the callee does with its arguments.  Windows code
that calls back into lisp -does- care about where the stack pointer
is on return, and things will misbehave if stack discipline isn't

Hope this clears things up without introducing more confusion.

> Alex

More information about the Openmcl-devel mailing list