From: Tony Hoyle
Subject: Converting C to Lisp
Date: 
Message-ID: <35f3f1e3.19949485@news.salford.ac.uk>
I've been given the task of converting a whole load of C header
files/function definitions to Allegro lisp (Win32).  Unfortunately my
knowledge of lisp is *zero* :-(

To get me started, how would I represent the following (hypothetical)
structure in lisp?

typedef struct
{
  unsigned aa;
  BOOL bb;
  char cc[11];
  OtherStruct *pOtherStruct;
} MyStruct;

Any info on type conversion would be helpful (short, int, dword,
etc.).  I'm really stuck over this one, as everything I try comes up
with meaningless error messages.....

Tony

--------------------------------------------------
Your mouse has moved. Windows NT must be restarted
for the change to take effect. Reboot now?  [ OK ]

···@netfusion.co.uk	http://sale.netfusion.co.uk
--------------------------------------------------

From: David B. Lamkins
Subject: Re: Converting C to Lisp
Date: 
Message-ID: <dlamkins-0709981203470001@192.168.0.1>
In article <·················@news.salford.ac.uk>, ···@netfusion.co.uk
(Tony Hoyle) wrote:

>I've been given the task of converting a whole load of C header
>files/function definitions to Allegro lisp (Win32).  Unfortunately my
>knowledge of lisp is *zero* :-(
>
>To get me started, how would I represent the following (hypothetical)
>structure in lisp?
>
>typedef struct
>{
>  unsigned aa;
>  BOOL bb;
>  char cc[11];
>  OtherStruct *pOtherStruct;
>} MyStruct;
>
>Any info on type conversion would be helpful (short, int, dword,
>etc.).  I'm really stuck over this one, as everything I try comes up
>with meaningless error messages.....


It would help us if you provided a little more context so we know _why_
you're converting C to Lisp.  The answers you'll get will be different,
for example, if you're converting C _code_ to Lisp (often a straighforward
translation is the worst approach to take -- more on this below) or if
you're writing FFI wrappers to allow the C code to be called from Lisp
(here, the specific techniques vary from vendor to vendor and from
platform to platform; in the case you cite, Franz has two completely
different implementations that support FFI to WIN32 -- I have no
experience with the newest version, but would not be surprised if the FFI
is different.)

If you're writing Lisp code to reimplement the C code, something as simple as 
  (defstruct my-struct
     aa bb cc other-struct)
could be equivalent.

OTOH, if you're writing FFI code and the struct is an interface to an
external C routine, then storage layout matters.  Here, there's no
substitute for digging out the Lisp vendor's documentation for the FFI and
the C compiler vendor's documentation on how they implement the scalar
data types and structure packing.

If you're translating C to Lisp (and I, for one, would _love_ to know why
:) you'll find that a straightforward translation will get you Lisp code
that works like C (except that it's somewhat harder to get the effects
like implicit modulus arithmetic on overflow, and you'd have to build your
own allocator to get explicit storage management.)  OTOH, if you
understand how the C code is supposed to work (and you understand Lisp),
then you can reimplement the C program in Lisp.  Expect your Lisp source
code to be anywhere from 1/5 to 1/10 the line count of the corresponding C
code.

Lack of Lisp knowledge is something that can be overcome fairly easily. 
There are some excellent books from which you could learn.  The ALU web
site <http://www.elwoodcorp.com/alu/> has a listing of books with
comments.  My own site has some capsule reviews at
<http://www.teleport.com/~dlamkins/computer-books.html>.  Links from these
sites should lead you to lots of other helpful Lisp information.

-- 
David B. Lamkins <http://www.teleport.com/~dlamkins/>
From: Steve Gonedes
Subject: Re: Converting C to Lisp
Date: 
Message-ID: <m27lzfu6o7.fsf@KludgeUnix.com>
···@netfusion.co.uk (Tony Hoyle) writes:

< 
< I've been given the task of converting a whole load of C header
< files/function definitions to Allegro lisp (Win32).  Unfortunately my
< knowledge of lisp is *zero* :-(
< 
< To get me started, how would I represent the following (hypothetical)
< structure in lisp?
< 
< typedef struct
< {
<   unsigned aa;
<   BOOL bb;
<   char cc[11];
<   OtherStruct *pOtherStruct;
< } MyStruct;
< 
< Any info on type conversion would be helpful (short, int, dword,
< etc.).  I'm really stuck over this one, as everything I try comes up
< with meaningless error messages.....

You can download an auto-conversion kit from ftp.franz.com (forget the
exact directory, sorry). I'm sure their web page has it shown
someplace. 

Structs in lisp look like the following example. Also `defstruct' will
create some functions, one is used to create a new instance of your
struct. You will probably be better off downloading the Common-Lisp
HyperSpec (no url, sorry; a search engine will certainly find it) and
reading up on it. Here are some examples.

(defstruct this
  (aa 0)
  (bb nil)
  (cc (make-string 10 :initial-element #\Space))
  (otherstruct nil))

(make-this :aa 1 :bb t :cc "steve" :otherstruct (make-this))
(make-this :aa 1 :bb t :cc "steve" :otherstruct 1/2)

(let ((other (make-this :aa 1 :bb t :cc "steve")))
   (make-this :aa 2 :bb t :otherstruct other))

In lisp the size of strings are already known, so there is no need to
insert a zero at the end of the string (hence the 10 for make-string).
Also, pointers are `automatic', that is, everything in lisp is a
`pointer'.

Two more things about structs that you may find interesting.
Say you have

typedef struct {
  int count;
  char *name;
} thing [100];.

What you do _not_ want to do in Lisp is

(defstruct thing
  count name)

(defvar *things*
  (make-array 100
    :initial-element (make-thing))),

as you would then have 100 `pointers' all `pointing' to the initial
call to `make-thing'. Also, you can use a multi-dimensional-array
instead of a structure. This is especially nice when all the members
of your struct will be of a similiar type (say unsigned shorts).

As far as conversions of memory-requirements...

In common-lisp you can create abbreviations for data types (you can
create new data-types as well). I think it maybe worthwile to use
type-declarations for some of the _operations_ you will be performing
on the structs just to catch potential errors. Lisp will _not_
`overflow' values, you will instead get a storage-condition (i.e., no
more memory is available). Luckily, lisp will signal an error if a
value does not satisfy a user-defined type declaration (Actually, I
believe it is not a requirement for a common-lisp to signal a type
condition for user-defined type-specifiers; although I do not know of
a lisp implementation that does not adhere to this).

Here are some type-specifiers that you could define; notice that these
will vary from machine to machine. This is to be expected when
converting from a low level language like C. [K&R The C programming
language, page 1]

(deftype unsigned-integer ()
  (list 'integer 0 4294967295))

(deftype boolean ()
  (list 'or t nil))

You can use the backtick (`) reader-macro instead of list and quote
(') if it suits you better.

(deftype cardinal-direction ()
 `(member north south east west))

(deftype signed-character ()
  `(integer -128 127))

Here is an example of the `<<' and `>>' operators in C converted to
lisp with addition checking to ensure that the resulting value
satisfies the `signed-character' declaration.

(defun signed-character-shift (byte shift)
  (the signed-character (ash byte shift)))

You may want to use the following

(defun signed-character-shift (byte shift)
  (declare (optimize safety))
  (the signed-character (ash byte shift))),

which will optimize for safety (I doubt that this is necessary
though). This should signal a type condition if the value exceeds the
range of a signed-character.

(signed-character-shift 34 4)

=> Type-condition: `544' is not a signed-character.

Common-lisp does not understand the concept of `return an incorrect
answer', which is not the case for the C programming language. For me,
this is the greatest source of difficulty in conversions as I _never_
expect a program to explicitly overflow just because it may have been
unspecified behavior in K&R. I do realize that some overflows are not
relevant to writing C programs. [K&R The C programming language, page
x]. Unfortunately, these assumptions of safety are often wrong and I
feel that it is a nice thing to know about when reading a C program
(thus I write a terribly long message in hopes that you do not waste
as much time as I did the other day).

As far as type conversions go, in Common-lisp you must perform the
overflow manually. Here are some of my overflow functions. I only
wrote these for characters (signed and unsigned).

Again, the overflow maximums and minimums will vary from machine to
machine, which is why I declared them as constants (I don't believe
that C programs can be portable, therefor I believe that a direct
conversion will, for the most part, not lend itself to portability).


(defconstant schar-min  -128)
(defconstant schar-max   127)
(defconstant uchar-max   255)
(defconstant uint-max    4294967295)
(defconstant schar-mask (logxor uint-max schar-max))


(deftype signed-character ()
  (list 'integer schar-min schar-max))

(deftype unsigned-character ()
  (list 'integer 0 uchar-max))


(defun overflow-signed-character (byte)
  (the signed-character 
    (cond ((>= schar-max byte schar-min)
           byte)
          ((plusp byte)
           (- (logandc2 byte schar-mask) (1+ schar-max)))
          ((minusp byte)
           (+ schar-max 1 (logior byte schar-mask))))))

(defun overflow-unsigned-character (byte)
  (the unsigned-character 
    (cond ((>= uchar-max byte 0)
           byte)
          ((plusp byte)
           (logandc2 byte schar-mask))
          ((minusp byte)
           (overflow-unsigned-character (+ (1+ uchar-max) byte))))))


The hyperspec has examples of all the bitshifting functions, such as
lognot, logorc2, logandc2, etc.

I cannot get shorts to overflow using GCC, so I cannot help with
these. The overflow routines for integers and double-words would be
very similiar, just change the constants. Hope this helps...
From: Tony Hoyle
Subject: Re: Converting C to Lisp
Date: 
Message-ID: <35f5268f.99094620@news.salford.ac.uk>
On 7 Sep 1998 23:23:34 GMT, Steve Gonedes <········@worldnet.att.net>
wrote:

>You can download an auto-conversion kit from ftp.franz.com (forget the
>exact directory, sorry). I'm sure their web page has it shown
>someplace. 

I had a look for it but the one on that site is only a beta and
requires a later version of allegro.

I don't have to actually code much lisp, just enough so I can go back
to the customer and tell them it can be done.  I have managed to
define the structures now (with defcstruct) but can't call the
function.  If I can do that I can give them the source and wash my
hands of the thing (hopefully...)

So far I have this:

... cut, but basically lots of defcstruct's

(defcstruct SiteLookupInfoStruct
  (
   (lpCountryLookupStruct (CountryLookupStruct *))
   (NumCountryLookup uint)
   (lpProvA (IdNameCtryStruct *))
   (NumProvA uint)
   (lpProvB (IdNameCtryStruct *))
   (NumProvB uint)
   )
  )

(defparameter netvespa-api-site "site.dll")

(defun-dll WAPLoadSiteLookupInfo ((lpSiteLookupInfo
SiteLookupInfoStruct *))
   :return-type bool
   :library-name netvespa-api-site
   :entry-name ·······················@4")

OK that defines the function, so how do I call it?  I have tried the
following:

(defvar slistruct (ccallocate SiteLookupInfoStruct))
(WAPLoadSiteLookupInfo slistruct)

Unfortunately the C code is always called with a NULL pointer.  I
suspect the allocation isn't working - unfortunately I have no access
to the printed manuals (they are kept at the customers' site about 300
miles away) and there is no online documentation for ccallocate - I
had to guess.

>Lack of Lisp knowledge is something that can be overcome fairly easily. 
>There are some excellent books from which you could learn.  The ALU web
>site <http://www.elwoodcorp.com/alu/> has a listing of books with
>comments.  My own site has some capsule reviews at
><http://www.teleport.com/~dlamkins/computer-books.html>.  Links from these
>sites should lead you to lots of other helpful Lisp information.

I'm trying to avoid having to actually learn lisp :-)  This is just
because an awkward (but large) customer refuses to use C.

Tony


--------------------------------------------------
Your mouse has moved. Windows NT must be restarted
for the change to take effect. Reboot now?  [ OK ]

···@netfusion.co.uk	http://sale.netfusion.co.uk
--------------------------------------------------