From: Benjamin Kowarsch
Subject: How to call OS traps from Lisp on Macintosh ?
Date: 
Message-ID: <nospam-orawnzva-0908990628280001@ppp014-max03.twics.com>
I have looked at a whole variety of Lisp implementations and
implementations of dialects after readers of this NG had suggested to do
so. I have checked them all out and there is lots of interesting tools,
yes, but the outcome is that I will have to call OS traps directly from
Lisp no matter what implementation I am going to use, for whatever reason.

So, please don't tell me how powerful the Lisp is you are using and that I
should be using it too because it will instantly solve any problems.

All I need to know is how do I call OS traps from Lisp on the Macintosh.


This is example code in Oberon:

(* Window Manager *)

PROCEDURE- InitWindows* 0A9H, 012H;

PROCEDURE- NewWindow*(wStorage: ME.Ptr; boundsRect: IM.Rect; title:
ME.Str255; visible: BOOLEAN; theProc: INTEGER; behind: WindowPtr;
goAwayFlag: BOOLEAN; refCon: LONGINT): WindowPtr 0A9H, 013H;

The "-" after the keyword "PROCEDURE" and the asterisk after identifiers
are export markers, rest is pretty much pascal except that procedures can
also be functions (use the same keyword) and return a result. The hex
codes in place of the body of the procedures/functions specify the related
OS trap.

As people have pointed out to me that Lisp is good for system programming,
I presume it is possible to code this in Lisp without too much trouble.
However, I haven't found anything in the Common Lisp Guide that would have
rang a bell as to using this or that to implement the traps (other than
inline assembler code).

Any help would be very much appreciated.

Benjamin

-- 
As an anti-spam measure I have scrambled my email address here.
Remove "nospam-" and ROT13 to obtain my email address in clear text.

From: Keke Abe
Subject: Re: How to call OS traps from Lisp on Macintosh ?
Date: 
Message-ID: <keke-0908991448460001@tc-1-117.osaka.gol.ne.jp>
In article <································@ppp014-max03.twics.com>, ···············@xntv.pbz (Benjamin Kowarsch) wrote:

> However, I haven't found anything in the Common Lisp Guide that would have
> rang a bell as to using this or that to implement the traps (other than
> inline assembler code).

there's a MacTech article re: implementing MacOS traps in Lisp.

  <http://www.mactech.com/articles/mactech/Vol.07/07.03/LispSounds/>

It's dated (circa 1991) but you'll get the picture.
also another MacTech article by the same author:

  <http://www.mactech.com/articles/mactech/Vol.09/09.01/MCL/>


regards,
abe

-- 
you make up your own reality. --TM
From: Rainer Joswig
Subject: Re: How to call OS traps from Lisp on Macintosh ?
Date: 
Message-ID: <joswig-0908990759570001@194.163.195.67>
In article <································@ppp014-max03.twics.com>, ···············@xntv.pbz (Benjamin Kowarsch) wrote:


> I have looked at a whole variety of Lisp implementations and
> implementations of dialects after readers of this NG had suggested to do
> so. I have checked them all out and there is lots of interesting tools,
> yes, but the outcome is that I will have to call OS traps directly from
> Lisp no matter what implementation I am going to use, for whatever reason.
> 
> So, please don't tell me how powerful the Lisp is you are using and that I
> should be using it too because it will instantly solve any problems.
> 
> All I need to know is how do I call OS traps from Lisp on the Macintosh.

MCL:

> This is example code in Oberon:
> 
> (* Window Manager *)
> 
> PROCEDURE- InitWindows* 0A9H, 012H;

Just write #_initwindows , and press m-.   -> then you get following source:

(deftrap "_InitWindows" ()
   nil
   (:stack-trap #xA912))


Most of the traps are already converted to Lisp and indexed, you just use them
and MCL loads them on demand.

> 
> PROCEDURE- NewWindow*(wStorage: ME.Ptr; boundsRect: IM.Rect; title:
> ME.Str255; visible: BOOLEAN; theProc: INTEGER; behind: WindowPtr;
> goAwayFlag: BOOLEAN; refCon: LONGINT): WindowPtr 0A9H, 013H;
> 

(deftrap "_NewWindow" ((wStorage :pointer) (boundsRect (:pointer :rect)) (title (:string 255)) (visible :boolean) (theProc :signed-integer) (behind (:pointer :windowrecord)) (goAwayFlag :boolean) (refCon :signed-long))
   (:stack (:pointer :windowrecord))
   (:stack-trap #xA913))


You'd use this stuff like this:

(defun %new-window (type position size close-box-p visible-p color-p)
  ;Leaves the procid in RefCon.
  (unless (fixnump type)
    (setq type (or (cdr (assoc type *window-type-procid-alist*))
                   (report-bad-arg type *window-type-foos*))))
  (setq position (center-window size position))
  (rlet ((wrect :rect :topleft position :bottomright (add-points-16 position size))
         (tp (:string 2)))
    (%put-word tp #x0120)
    (let ((res (if (and color-p *color-available*)
                 (#_NewCWindow 
                  (%null-ptr)
                  wrect                            ; bounds
                  tp                               ; blank title
                  visible-p                        ; visible
                  type                             ; procid
                  (%int-to-ptr -1)                 ; behind
                  close-box-p                      ; goAwayFlag
                  type                             ; refCon
                  )
                 (#_NewWindow
                  (%null-ptr) 
                  wrect                            ; bounds
                  tp                               ; blank title
                  visible-p                        ; visible
                  type                             ; procid
                  (%int-to-ptr -1)                 ; behind
                  close-box-p                      ; goAwayFlag
                  type                             ; refCon
                  ))))
      (if (%null-ptr-p res)
        (%err-disp #$MemFullErr)
        res))))


Actually you'd normally just do (make-instance 'window) and it works.
From: John Wiseman
Subject: Re: How to call OS traps from Lisp on Macintosh ?
Date: 
Message-ID: <arxpv0xdj02.fsf@gargoyle.cs.uchicago.edu>
···············@xntv.pbz (Benjamin Kowarsch) writes:

> All I need to know is how do I call OS traps from Lisp on the
> Macintosh.
> 
> 
> This is example code in Oberon:
> 
> (* Window Manager *)
> 
> PROCEDURE- InitWindows* 0A9H, 012H;
> 
> PROCEDURE- NewWindow*(wStorage: ME.Ptr; boundsRect: IM.Rect; title:
> ME.Str255; visible: BOOLEAN; theProc: INTEGER; behind: WindowPtr;
> goAwayFlag: BOOLEAN; refCon: LONGINT): WindowPtr 0A9H, 013H;

There are three chapters in the Macintosh Common Lisp Reference having
to do with MCL's foreign function interface and low-level OS
interface.


I.  The Basics are Basic

It's generally easy.  Often all you have to do to call an OS trap is
write something something like

  (#_NewWindow arg1 arg2...)

Many trap arguments will automatically be converted from Lisp types
(symbols, T/NIL, double floats) to low-level types (OSTypes, Booleans,
single floats).  Arguments that can be, i.e., non-pointers, are
type-checked (contrary to that ancient MacTech article).

Nearly every trap you would use has already been defined and indexed
by Digitool.  The definition is automatically loaded when you use the
hash-underscore (#_) syntax.


II. The Commonplace is Convenient

There are facilities for working with low-level data types, including
strings and structs.  For example,

  (rlet ((angle :integer)
         (r :rect :topleft ·@(100 50) :bottomright #(120 70)))
    (with-pstrs ((label "Hello"))
      (#_DrawString label))
    (setf (rref r :rect :top) 49)
    (#_PtToAngle r ·@(150 20) angle)
    (%get-word angle))

The rlet form temporarily allocates storage on the stack for an
integer and a Rect struct, initializes the fields of the Rect as
specified, and binds angle and r to pointers to the allocated storage.

Thw with-pstrs macro allocates storage for a Pascal string, converts
the Lisp string to a Pascal string, and binds label to a pointer to
the string.

rref is used to refer to fields of structs.  It understands a special
syntax that makes it easy to refer to nested fields.


III. Beauty Marks and Warts

It's pretty easy to have MCL call functions you've written in C and
have C code call Lisp functions.

It's easy to use MCL's termination facility to do garbage collection
on low-level storage, if you desire.

It can be hard to interface to large libraries for which there are no
Digitool-supplied trap definitions.  It's easy enough to write your
own trap definitions by hand, and if you have a Pascal interface file
for the library there is a tool that can be coaxed into spitting out
the Lisp trap definitions, but there's nothing that will take a C
header file and generate the definitions MCL needs.  Since Digitool
provides something like 10,000 trap definitions this isn't *usually* a
problem.


John Wiseman