properly print to end of doc when -o#- is requested (4.3BSD-tahoe/usr.bin/31)
[unix-history] / usr / src / old / lisp / PSD.doc / ch8.n
CommitLineData
f56971ac
NC
1.\" Copyright (c) 1980 Regents of the University of California.
2.\" All rights reserved. The Berkeley software License Agreement
3.\" specifies the terms and conditions for redistribution.
4.\"
7f944314 5.\" @(#)ch8.n 6.2 (Berkeley) %G%
f56971ac 6.\"
78dae1cf
NC
7." $Header: ch8.n,v 1.4 83/07/27 15:12:22 layer Exp $
8.Lc Functions,\ Fclosures,\ and\ Macros 8
7f944314 9.sh 2 valid\ function\ objects \n(ch 1
78dae1cf
NC
10.pp
11There are many different objects which can occupy the function field of
12a symbol object.
13Table 8.1, on the following page,
14shows all of the possibilities, how to recognize them,
15and where to look for documentation.
16.(z
17.sp 1v
18.TS
19box center ;
20c | c | c .
21informal name object type documentation
22=
23interpreted list with \fIcar\fP 8.2
24lambda function \fIeq\fP to lambda
25_
26interpreted list with \fIcar\fP 8.2
27nlambda function \fIeq\fP to nlambda
28_
29interpreted list with \fIcar\fP 8.2
30lexpr function \fIeq\fP to lexpr
31_
32interpreted list with \fIcar\fP 8.3
33macro \fIeq\fP to macro
34_
35fclosure vector with \fIvprop\fP 8.4
36 \fIeq\fP to fclosure
37_
38compiled binary with discipline 8.2
39lambda or lexpr \fIeq\fP to lambda
40function
41_
42compiled binary with discipline 8.2
43nlambda function \fIeq\fP to nlambda
44_
45compiled binary with discipline 8.3
46macro \fIeq\fP to macro
47_
48foreign binary with discipline 8.5
49subroutine of \*(lqsubroutine\*(rq\*[\(dg\*]
50_
51foreign binary with discipline 8.5
52function of \*(lqfunction\*(rq\*[\(dg\*]
53_
54foreign binary with discipline 8.5
55integer function of \*(lqinteger-function\*(rq\*[\(dg\*]
56_
57foreign binary with discipline 8.5
58real function of \*(lqreal-function\*(rq\*[\(dg\*]
59_
60foreign binary with discipline 8.5
61C function of \*(lqc-function\*(rq\*[\(dg\*]
62_
63foreign binary with discipline 8.5
64double function of \*(lqdouble-c-function\*(rq\*[\(dg\*]
65_
66foreign binary with discipline 8.5
67structure function of \*(lqvector-c-function\*(rq\*[\(dg\*]
68_
69array array object 9
70.TE
71.tl ''Table 8.1''
72.(f
73\*[\(dg\*]Only the first character of the string is significant (i.e \*(lqs\*(rq
74is ok for \*(lqsubroutine\*(rq)
75.)f
76.)z
77.br
78.sh 2 functions
79.pp
80The basic Lisp function is the lambda function.
81When a lambda function is called, the actual arguments are
82evaluated from left to right and are lambda-bound to the
83formal parameters of the lambda function.
84.pp
85An nlambda function is usually used for functions which are invoked
86by the user at top level.
87Some built-in functions which evaluate their arguments in special ways are
88also nlambdas (e.g \fIcond\fP, \fIdo\fP, \fIor\fP).
89When an nlambda function is called, the list of unevaluated arguments
90is lambda bound to the single formal parameter of the nlambda function.
91.pp
92Some programmers will use an nlambda function
93when they are not sure how many arguments
94will be passed.
95Then, the first thing the nlambda function does is map \fIeval\fP over
96the list of unevaluated arguments it has been passed.
97This is usually the wrong thing to do, as it will not work compiled if
98any of the arguments are local variables.
99The solution is to use a lexpr.
100When a lexpr function is called, the arguments
101are evaluated and a fixnum whose value is
102the number of arguments is lambda-bound to the single
103formal parameter of the lexpr function.
104The lexpr can then access the arguments using the \fIarg\fP function.
105.pp
106When a function is compiled,
107.i special
108declarations may be needed to
109preserve its behavior.
110An argument is not lambda-bound to the name of
111the corresponding formal parameter
112unless that formal parameter has been declared
113.i special
114(see \(sc12.3.2.2).
115.pp
116Lambda and lexpr functions both compile into a binary object with
117a discipline of lambda.
118However, a compiled lexpr still acts like an interpreted lexpr.
119.sh 2 macros
120.pp
121An important feature of Lisp
122is its ability to manipulate programs as data.
123As a result of this, most Lisp implementations
124have very powerful macro facilities.
125The Lisp language's macro facility
126can be used to incorporate popular features of the other
127languages into Lisp.
128For example, there are macro packages
129which allow one to create records (ala Pascal)
130and refer to elements of those records by the field names.
131The
132.i struct
133package imported from Maclisp does this.
134Another popular use for macros is to create more readable control
135structures which expand into
136.i cond ,
137.i or
138and
139.i and .
140One such example is the If macro.
141It allows you to write
142.sp 1v
143.nf
144.ft I
145(If (equal numb 0) then (print 'zero) (terpr)
146\ elseif (equal numb 1) then (print 'one) (terpr)
147\ else (print '|I give up|))
148.ft P
149.sp 1v
150which expands to
151.sp 1v
152.ft I
153(cond
154\ \ \ \ ((equal numb 0) (print 'zero) (terpr))
155\ \ \ \ ((equal numb 1) (print 'one) (terpr))
156\ \ \ \ (t (print '|I give up|)))
157.ft P
158.sp 1v
159.fi
160.sh 3 macro\ forms
161.pp
162A macro is a function which accepts a Lisp expression as input and returns
163another Lisp expression.
164The action the macro takes is called macro expansion.
165Here is a simple example:
166.sp 1v
167.nf
168\-> \fI(def first (macro (x) (cons 'car (cdr x))))\fP
169first
170\-> \fI(first '(a b c))\fP
171a
172\-> \fI(apply 'first '(first '(a b c)))\fP
173(car '(a b c))
174.fi
175.sp 1v
176The first input line defines a macro called
177.i first .
178Notice that the macro has one formal parameter, \fIx\fP.
179On the second input line, we ask the interpreter to evaluate
180\fI(first\ '(a\ b\ c))\fP.
181.i Eval
182sees that
183.i first
184has a function definition of type macro, so it evaluates
185.i first 's
186definition,
187passing to
188.i first ,
189as an argument, the form
190.i eval
191itself
192was trying to
193evaluate: \fI(first\ '(a\ b\ c))\fP.
194The
195.i first
196macro chops off the car of the argument with
197.i cdr ,
198cons' a
199.i car
200at the beginning of the list and returns \fI(car\ '(a\ b\ c))\fP,
201which
202.i eval
203evaluates.
204The value
205.i a
206is returned as the value of \fI(first\ '(a\ b\ c))\fP.
207Thus whenever
208.i eval
209tries to evaluate a list whose car has a macro definition
210it ends up doing (at least) two operations, the first of which
211is a call to the macro
212to let it macro expand the form, and the other is the evaluation of the
213result of the macro.
214The result of the macro may be yet another call to a macro, so
215.i eval
216may have to do even more evaluations until it can finally determine
217the value of an expression.
218One way to see how a macro will expand is to use
219.i apply
220as shown on the third input line above.
221.sh +0 defmacro
222.pp
223The macro
224.i defmacro
225makes it easier to define macros because it allows you to name the arguments
226to the macro call.
227For example, suppose we find ourselves often writing code like
228\fI(setq\ stack\ (cons\ newelt\ stack)\fP.
229We could define a macro named \fIpush\fP to do this for us.
230One way to define it is:
231.nf
232.sp 1v
233\-> \fI(de\kAf push
234\h'|\nAu'(macro (x) (list 'setq (caddr x) (list 'cons (cadr x) (caddr x)))))\fP
235push
236.fi
237.sp 1v
238then \fI(push\ newelt\ stack)\fP will expand to the form mentioned above.
239The same macro written using defmacro would be:
240.nf
241.sp 1v
242\->\fI\kA (defmacro push (value stack)
243 \h'|\nAu'(list 'setq ,stack (list 'cons ,value ,stack)))\fP
244push
245.fi
246.sp 1v
247Defmacro allows you to name the arguments of the macro call, and makes the
248macro definition look more like a function definition.
249.sh +0 the\ backquote\ character\ macro
250.pp
251The default syntax for
252.Fr
253has four characters with associated character macros.
254One is semicolon for comments.
255Two others are the backquote and comma which are
256used by the backquote character
257macro.
258The fourth is the sharp sign macro described in the next section.
259.pp
260The backquote macro is used to create lists where many of the elements are
261fixed (quoted).
262This makes it very useful for creating macro definitions.
263In the simplest case, a backquote acts just like a single quote:
264.sp 1v
265.nf
266\->\fI`(a b c d e)\fP
267(a b c d e)
268.fi
269.sp 1v
270If a comma precedes an element of a backquoted list then that element is
271evaluated and its value is put in the list.
272.sp 1v
273.nf
274\->\fI(setq d '(x y z))\fP
275(x y z)
276\->\fI`(a b c ,d e)\fP
277(a b c (x y z) e)
278.fi
279.sp 1v
280If a comma followed by an at sign precedes an element in a backquoted list,
281then that element is evaluated and spliced into the list with
282.i append .
283.nf
284.sp 1v
285\->\fI`(a b c ,@d e)\fP
286(a b c x y z e)
287.sp 1v
288.fi
289Once a list begins with a backquote, the commas may appear anywhere in the
290list as this example shows:
291.nf
292.sp 1v
293\->\fI`(a b (c d ,(cdr d)) (e f (g h ,@(cddr d) ,@d)))\fP
294(a b (c d (y z)) (e f (g h z x y z)))
295.sp 1v
296.fi
297It is also possible and sometimes even useful to use the
298backquote macro within itself.
299As a final demonstration of the backquote macro, we shall define the
300first and push macros using all the power at our disposal: defmacro
301and the backquote macro.
302.sp 1v
303.nf
304\->\fI(defmacro first (list) `(car ,list))\fP
305first
306\->\fI(defmacro push (value stack) `(setq ,stack (cons ,value ,stack)))\fP
307stack
308.fi
309.sh +0 sharp\ sign\ character\ macro
310.pp
311The sharp sign macro can perform a number of
312different functions at read time.
313The character directly following the sharp sign determines which function
314will be done, and following Lisp s-expressions may serve as arguments.
315.sh +1 conditional\ inclusion
316.lp
317If you plan to run one source file in more than one environment then
318you may want to some pieces of code to be included or not included
319depending on the environment.
320The C language uses \*(lq#ifdef\*(lq and \*(lq#ifndef\*(rq for this
321purpose, and Lisp uses \*(lq#+\*(rq and \*(lq#\-\*(rq.
322The environment that the sharp sign macro checks is the
323\fI(status\ features)\fP list which is initialized when the Lisp
324system is built and which may be altered by
325\fI(sstatus\ feature\ foo)\fP and \fI(sstatus\ nofeature\ bar)\fP
326The form of conditional inclusion is
327.br
328.tl ''\fI#+when what\fP''
329where
330.i when
331is either a symbol or an expression involving symbols and the functions
332.i and ,
333.i or ,
334and
335.i not .
336The meaning is that
337.i what
338will only be read in if
339.i when
340is true.
341A symbol in
342.i when
343is true only if it appears in the
344.i (status\ features)
345list.
346.Eb
347; suppose we want to write a program which references a file
348; and which can run at ucb, ucsd and cmu where the file naming conventions
349; are different.
350;
351\-> \fI(de\kAfun howold (name)
352 \h'|\nAu'\kC(terpr)
353 \h'|\nCu'\kB(load #\kA+(or ucb ucsd) "/usr/lib/lisp/ages.l"
354 \h'|\nAu'#+cmu "/usr/lisp/doc/ages.l")
355 \h'|\nBu'\kA(patom name)
356 \h'|\nBu'\kA(patom " is ")
357 \h'|\nAu'\kB(print (cdr (assoc name agefile)))
358 \h'|\nBu'\kA(patom "years old")
359 \h'|\nAu'(terpr))\fP
360.Ee
361The form
362.br
363.tl ''\fI#\-when what\fP''
364is equivalent to
365.br
366.tl ''\fI#+(not when) what\fP''
367.sh +0 fixnum\ character\ equivalents
368.lp
369When working with fixnum equivalents of characters, it is often hard to
370remember the number corresponding to a character.
371The form
372.br
373.tl ''\fI#/c\fP''
374is equivalent to the fixnum representation of character c.
375.Eb
376; a function which returns t if the user types y else it returns nil.
377;
378\-> \fI(de\kBfun yesorno nil
379 \h'|\nBu'(progn \kA(ans)
380 \h'|\nAu'\kB(setq ans (tyi))
381 \h'|\nBu'(cond \kA((equal ans #/y) t)
382 \h'|\nAu'(t nil))))\fP
383.Ee
384.sh +0 read\ time\ evaluation
385.lp
386Occasionally you want to express a constant as a Lisp expression, yet you
387don't want to pay the penalty of evaluating this expression each time it
388is referenced.
389The form
390.br
391.tl ''\fI#.expression\fP''
392evaluates the expression at read time and returns its value.
393.Eb
394; a function to test if any of bits 1 3 or 12 are set in a fixnum.
395;
396\-> \fI(de\kCfun testit (num)
397 \h'|\nCu'(cond \kA(\kB(zerop (boole 1 num #.(+ (lsh 1 1) (lsh 1 3) (lsh 1 12))))
398 \h'|\nBu'nil)
399 \h'|\nAu'(t t)))\fP
400.Ee
401.sh 2 fclosures
402.pp
403Fclosures are a type of functional object.
404The purpose is to remember the values of some variables
405between invocations of the functional object and to protect this
406data from being inadvertently overwritten by other Lisp functions.
407Fortran programs usually exhibit this behavior for their variables.
408(In fact, some versions of Fortran would require the
409variables to be in COMMON).
410Thus it is easy to write a linear congruent random number generator
411in Fortran, merely by keeping the seed as a variable in the function.
412It is much more risky to do so in Lisp, since any special variable you
413picked, might be used by some other function.
414Fclosures are an attempt to provide most of the same functionality as
415closures in Lisp Machine Lisp, to users of
416.Fr .
417Fclosures are related to closures in this way:
418.br
419(fclosure '(a b) 'foo) <==>
420.br
421 (let ((a a) (b b)) (closure '(a b) 'foo))
422.sh 3 an\ example
423.sp 1v
424.in 0
425.nf
426.sz -2
427.hl
428% \fBlisp\fP
429Franz Lisp, Opus 38.60
430\->\fB(defun code (me count)
431 (print (list 'in x))
432 (setq x (+ 1 x))
433 (cond ((greaterp count 1) (funcall me me (sub1 count))))
434 (print (list 'out x)))\fP
435code
436\->\fB(defun tester (object count)
437 (funcall object object count) (terpri))\fP
438tester
439\->\fB(setq x 0)\fP
4400
441\->\fB(setq z (fclosure '(x) 'code))\fP
442fclosure[8]
443\->\fB (tester z 3)\fP
444(in 0)(in 1)(in 2)(out 3)(out 3)(out 3)
445nil
446\->\fBx\fP
4470
448.hl
449.fi
450.sz +2
451.sp 3v
452.pp
453The function \fIfclosure\fP creates a new object
454that we will call an fclosure,
455(although it is actually a vector).
456The fclosure contains a functional object, and a set of symbols and
457values for the symbols. In the above example, the fclosure functional
458object is the function code.
459The set of symbols and values just contains the symbol `x' and
460zero, the value of `x' when the fclosure was created.
461.lp
462When an fclosure is funcall'ed:
463.ip 1)
464The Lisp system lambda binds the symbols in the fclosure to their values in the fclosure.
465.ip 2)
466It continues the funcall on the functional object of the fclosure.
467.ip 3)
468Finally, it un-lambda binds the symbols in the fclosure and at the
469same time stores the current values of the symbols in the fclosure.
470.sp 1v
471.pp
472Notice that the fclosure is saving the value of the symbol `x'.
473Each time a fclosure is created, new space is allocated for saving
474the values of the symbols. Thus if we execute fclosure again, over
475the same function, we can have two independent counters:
476.sp 1v
477.in 0
478.nf
479.sz -2
480.hl
481\-> \fB(setq zz (fclosure '(x) 'code))\fP
482fclosure[1]
483\-> \fB(tester zz 2)\fP
484(in 0)(in 1)(out 2)(out 2)
485\-> \fB(tester zz 2)\fP
486(in 2)(in 3)(out 4)(out 4)
487\-> \fB(tester z 3)\fP
488(in 3)(in 4)(in 5)(out 6)(out 6)(out 6)
489.hl
490.fi
491.sz +2
492.sp 3v
493.sh 3 useful\ functions
494.pp
495Here are some quick some summaries of functions dealing with closures.
496They are more formally defined in \(sc2.8.4.
497To recap, fclosures are made by
498\fI(fclosure 'l_vars 'g_funcobj)\fP.
499l_vars is a list of symbols (not containing nil),
500g_funcobj is any object that can be funcalled.
501(Objects which can be funcalled, include compiled Lisp functions,
502lambda expressions, symbols, foreign functions, etc.)
503In general, if you want a compiled function to be closed over a
504variable, you must declare the variable to be special within the function.
505Another example would be:
506.(l
507 (fclosure '(a b) #'(lambda (x) (plus x a)))
508.)l
509Here, the #' construction will make the compiler compile the lambda expression.
510.pp
511There are times when you want to share variables between fclosures.
512This can be done if the fclosures are created at the same time using
513\fIfclosure-list\fP.
514The function \fIfclosure-alist\fP returns an assoc list giving
515the symbols and values in the fclosure. The predicate
516\fIfclosurep\fP returns t iff its argument is a fclosure.
517Other functions imported from Lisp Machine Lisp are
518.i symeval-in-fclosure,
519.i let-fclosed,
520and
521.i set-in-fclosure.
522Lastly, the function \fIfclosure-function\fP returns the function argument.
523.sh 3 internal\ structure
524.pp
525Currently, closures are implemented as vectors, with property being the
526symbol fclosure. The functional object is the first entry.
527The remaining entries are structures which point to the symbols
528and values for the closure, (with a reference count to determine
529if a recursive closure is active).
530.sh 2 foreign\ subroutines\ and\ functions
531.pp
532.Fr
533has the ability to dynamically load object files produced by other compilers
534and to call functions defined in those files.
535These functions are called
536.i foreign
537functions.*
538.(f
539*This topic is also discussed in Report PAM-124 of the Center for
540Pure and Applied Mathematics, UCB, entitled ``Parlez-Vous Franz?
541An Informal Introduction to Interfacing Foreign Functions to Franz LISP'',
542by James R. Larus
543.)f
544There are seven types of foreign functions.
545They are characterized by
546the type of result they return, and by differences in the interpretation
547of their arguments.
548They come from two families: a group suited for languages which pass
549arguments by reference (e.g. Fortran), and a group suited for languages
550which pass arguments by value (e.g. C).
551.sp 1v
552.lp
553There are four types in the first group:
554.ip \fBsubroutine\fP
555This does not return anything.
556The Lisp system
557always returns t after calling a subroutine.
558.ip \fBfunction\fP
559This returns whatever the function returns.
560This must be a valid Lisp object or it may cause the Lisp system to fail.
561.ip \fBinteger-function\fP
562This returns an integer which the Lisp system makes into a fixnum and returns.
563.ip \fBreal-function\fP
564This returns a double precision real number which the Lisp
565system makes into a flonum and returns.
566.sp 1v
567.lp
568There are three types in the second group:
569.ip \fBc-function\fP
570This is like an integer function, except for its different interpretation
571of arguments.
572.ip \fBdouble-c-function\fP
573This is like a real-function.
574.ip \fBvector-c-function\fP
575This is for C functions which return a structure.
576The first argument to such functions must be a vector (of type vectori),
577into which the result is stored.
578The second Lisp argument
579becomes the first argument to the C function, and so on
580.lp
581A foreign function is accessed through a binary object just like a
582compiled Lisp function.
583The difference is that the discipline field of a binary object
584for a foreign function is a string
585whose first character is given in the following table:
7f944314 586.(b
78dae1cf
NC
587.TS
588box center ;
589c | c .
590letter type
591=
592s subroutine
593_
594f function
595_
596i integer-function
597_
598r real-function.
599_
600c c-function
601_
602v vector-c-function
603_
604d double-c-function
605_
606.TE
7f944314 607.)b
78dae1cf
NC
608Two functions are provided for setting-up foreign functions.
609.i Cfasl
610loads an object file into the Lisp system and sets up one foreign
611function binary object.
612If there are more than one function in an object file,
613.i getaddress
614can be used to set up additional foreign function objects.
615.pp
616Foreign functions are called just like other functions, e.g
617\fI(funname\ arg1\ arg2)\fP.
618When a function in the Fortran group is called,
619the arguments are evaluated and then examined.
620List, hunk and symbol arguments are passed unchanged to
621the foreign function.
622Fixnum and flonum arguments are copied into a temporary location and
623a pointer to the value is passed (this is because Fortran uses call
624by reference and it is dangerous to modify the contents of a fixnum
625or flonum which something else might point to).
626If the argument is an array object,
627the data field of the array object is
628passed to the foreign function
629(This is the easiest way to send large
630amounts of data to and receive large amounts of data from a foreign
631function).
632If a binary object is an argument, the entry field of that object is
633passed to the foreign function (the entry field is the address of a function,
634so this amounts to passing a function as an argument).
635.pp
636When a function in the C group is called,
637fixnum and flownum arguments are passed by value.
638For almost all other arguments,
639the address is merely provided to the C routine.
640The only exception arises when you want to invoke a C routine
641which expects a ``structure'' argument. Recall that a (rarely used)
642feature of the C language is the ability to pass structures by value.
643This copies the structure onto the stack. Since the Franz's nearest
644equivalent to a C structure is a vector, we provide an escape clause
645to copy the contents of an immediate-type vector by value. If the
646property field of a vectori argument, is the symbol
647\*(lqvalue-structure-argument\*(rq,
648then the binary data of this immediate-type vector is copied
649into the argument list of the C routine.
650.pp
651The method a foreign function uses to access the arguments provided
652by Lisp is dependent on the language of the foreign function.
653The following scripts demonstrate how how Lisp can interact with three
654languages: C, Pascal and Fortran.
655C and Pascal have pointer types and the first script shows how to use
656pointers to extract information from Lisp objects.
657There are two functions defined for each language.
658The first (cfoo in C, pfoo in Pascal) is given four arguments, a
659fixnum, a flonum-block array, a hunk of at least two
660fixnums and a list of
661at least two fixnums.
662To demonstrate that the values were passed, each ?foo function prints
663its arguments (or parts of them).
664The ?foo function then modifies the second element of
665the flonum-block array and returns a 3 to Lisp.
666The second function (cmemq in C, pmemq in Pascal) acts just like the
667Lisp
668.i memq
669function (except it won't work for fixnums whereas the lisp
670.i memq
671will work for small fixnums).
672In the script, typed input is in
673.b bold ,
674computer output is in roman
675and comments are in
676.i italic.
677.in 0
678.nf
679.sp 2v
680.sz -2
681.hl
682\fIThese are the C coded functions \fP
683% \fBcat ch8auxc.c\fP
684/* demonstration of c coded foreign integer-function */
685
686/* the following will be used to extract fixnums out of a list of fixnums */
687struct listoffixnumscell
688{ struct listoffixnumscell *cdr;
689 int *fixnum;
690};
691
692struct listcell
693{ struct listcell *cdr;
694 int car;
695};
696
697cfoo(a,b,c,d)
698int *a;
699double b[];
700int *c[];
701struct listoffixnumscell *d;
702{
703 printf("a: %d, b[0]: %f, b[1]: %f\n", *a, b[0], b[1]);
704 printf(" c (first): %d c (second): %d\n",
705 *c[0],*c[1]);
706 printf(" ( %d %d ... )\n ", *(d->fixnum), *(d->cdr->fixnum));
707 b[1] = 3.1415926;
708 return(3);
709}
710
711struct listcell *
712cmemq(element,list)
713int element;
714struct listcell *list;
715{
716 for( ; list && element != list->car ; list = list->cdr);
717 return(list);
718}
719.sp 2v
720\fIThese are the Pascal coded functions \fP
721% \fBcat ch8auxp.p\fP
722type pinteger = ^integer;
723 realarray = array[0..10] of real;
724 pintarray = array[0..10] of pinteger;
725 listoffixnumscell = record
726 cdr : ^listoffixnumscell;
727 fixnum : pinteger;
728 end;
729 plistcell = ^listcell;
730 listcell = record
731 cdr : plistcell;
732 car : integer;
733 end;
734
735function pfoo ( var a : integer ;
736 var b : realarray;
737 var c : pintarray;
738 var d : listoffixnumscell) : integer;
739begin
740 writeln(' a:',a, ' b[0]:', b[0], ' b[1]:', b[1]);
741 writeln(' c (first):', c[0]^,' c (second):', c[1]^);
742 writeln(' ( ', d.fixnum^, d.cdr^.fixnum^, ' ...) ');
743 b[1] := 3.1415926;
744 pfoo := 3
745end ;
746
747{ the function pmemq looks for the Lisp pointer given as the first argument
748 in the list pointed to by the second argument.
749 Note that we declare " a : integer " instead of " var a : integer " since
750 we are interested in the pointer value instead of what it points to (which
751 could be any Lisp object)
752}
753function pmemq( a : integer; list : plistcell) : plistcell;
754begin
755 while (list <> nil) and (list^.car <> a) do list := list^.cdr;
756 pmemq := list;
757end ;
758.sp 2v
759\fIThe files are compiled\fP
760% \fBcc -c ch8auxc.c\fP
7611.0u 1.2s 0:15 14% 30+39k 33+20io 147pf+0w
762% \fBpc -c ch8auxp.p\fP
7633.0u 1.7s 0:37 12% 27+32k 53+32io 143pf+0w
764.sp 2v
765% \fBlisp\fP
766Franz Lisp, Opus 38.60
767.ft I
768.fi
769First the files are loaded and we set up one foreign function binary.
770We have two functions in each file so we must choose one to tell cfasl about.
771The choice is arbitrary.
772.ft P
773.br
774.nf
775\->\fB (cfasl 'ch8auxc.o '_cfoo 'cfoo "integer-function")\fP
776/usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxc.o -e _cfoo -o /tmp/Li7055.0 -lc
777#63000-"integer-function"
778\->\fB (cfasl 'ch8auxp.o '_pfoo 'pfoo "integer-function" "-lpc")\fP
779/usr/lib/lisp/nld -N -A /tmp/Li7055.0 -T 63200 ch8auxp.o -e _pfoo -o /tmp/Li7055.1 -lpc -lc
780#63200-"integer-function"
781.ft I
782Here we set up the other foreign function binary objects
783.ft P
784\->\fB (getaddress '_cmemq 'cmemq "function" '_pmemq 'pmemq "function")\fP
785#6306c-"function"
786.ft I
787.fi
788We want to create and initialize an array to pass to the cfoo function.
789In this case we create an unnamed array and store it in the value cell of
790testarr.
791When we create an array to pass to the Pascal program we will use a named
792array just to demonstrate the different way that named and unnamed arrays
793are created and accessed.
794.br
795.nf
796.ft P
797\->\fB (setq testarr (array nil flonum-block 2))\fP
798array[2]
799\->\fB (store (funcall testarr 0) 1.234)\fP
8001.234
801\->\fB (store (funcall testarr 1) 5.678)\fP
8025.678
803\->\fB (cfoo 385 testarr (hunk 10 11 13 14) '(15 16 17))\fP
804a: 385, b[0]: 1.234000, b[1]: 5.678000
805 c (first): 10 c (second): 11
806 ( 15 16 ... )
807 3
808.ft I
809.fi
810Note that cfoo has returned 3 as it should.
811It also had the side effect of changing the second value of the array to
8123.1415926 which check next.
813.br
814.nf
815.ft P
816\->\fB (funcall testarr 1)\fP
8173.1415926
818.sp 2v
819.fi
820.ft I
821In preparation for calling pfoo we create an array.
822.ft P
823.nf
824\->\fB (array test flonum-block 2)\fP
825array[2]
826\->\fB (store (test 0) 1.234)\fP
8271.234
828\->\fB (store (test 1) 5.678)\fP
8295.678
830\->\fB (pfoo 385 (getd 'test) (hunk 10 11 13 14) '(15 16 17))\fP
831 a: 385 b[0]: 1.23400000000000E+00 b[1]: 5.67800000000000E+00
832 c (first): 10 c (second): 11
833 ( 15 16 ...)
8343
835\->\fB (test 1)\fP
8363.1415926
837.sp 1v
838\fI Now to test out the memq's
839\-> \fB(cmemq 'a '(b c a d e f))\fP
840(a d e f)
841\-> \fB(pmemq 'e '(a d f g a x))\fP
842nil
843.hl
844.fi
845.sz +2
846.sp 3v
847.pp
848The Fortran example will be much shorter since in Fortran
849you can't follow pointers
850as you can in other languages.
851The Fortran function ffoo is given three arguments: a fixnum, a
852fixnum-block array and a flonum.
853These arguments are printed out to verify that they made it and
854then the first value of the array is modified.
855The function returns a double precision value which is converted to a flonum
856by lisp and printed.
857Note that the entry point corresponding to the Fortran function ffoo is
858_ffoo_ as opposed to the C and Pascal convention of preceding the name with
859an underscore.
860.sp 1v
861.in 0
862.nf
863.sz -2
864.hl
865
866% \fBcat ch8auxf.f\fP
867 double precision function ffoo(a,b,c)
868 integer a,b(10)
869 double precision c
870 print 2,a,b(1),b(2),c
8712 format(' a=',i4,', b(1)=',i5,', b(2)=',i5,' c=',f6.4)
872 b(1) = 22
873 ffoo = 1.23456
874 return
875 end
876% \fBf77 -c ch8auxf.f\fP
877ch8auxf.f:
878 ffoo:
8790.9u 1.8s 0:12 22% 20+22k 54+48io 158pf+0w
880% \fBlisp\fP
881Franz Lisp, Opus 38.60
882\-> \fB(cfasl 'ch8auxf.o '_ffoo_ 'ffoo "real-function" "-lF77 -lI77")\fP
883/usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxf.o -e _ffoo_
884-o /tmp/Li11066.0 -lF77 -lI77 -lc
885#6307c-"real-function"
886.sp 1v
887\-> \fB(array test fixnum-block 2)\fP
888array[2]
889\->\fB (store (test 0) 10)\fP
89010
891\-> \fB(store (test 1) 11)\fP
89211
893\-> \fB(ffoo 385 (getd 'test) 5.678)\fP
894 a= 385, b(1)= 10, b(2)= 11 c=5.6780
8951.234559893608093
896\-> \fB(test 0)\fP
89722
898
899.hl