1 MANUAL UPDATE                 Thursday, November 15, 1974
  2 
  3   This document is a list of changes to the MACLISP language between
  4 the time the MACLISP Reference Manual (Revision 0) was written
  5 and the present date.  References to the manual are made by section
  6 number and page number.  This document does not purport to correct
  7 typographical errors in said manual.
  8 
  9 
 10                    New Functions
 11 
 12 \\     This subr of two arguments is like gcd, but only accepts
 13        fixnums.  This makes it faster than gcd.
 14 
 15 copysymbol
 16        A subr of two arguments.  The first argument must be a symbol,
 17        and the second should be t or nil.  The result is a new,
 18        uninterned symbol, with the same pname as the argument.  If the
 19        second argument is t, the new symbol will be given the same
 20        value as the original and will have a copy of its property list.
 21        Thus the new will start out with the same value and properties
 22        as the old, but if it is setq'ed or putprop'ed, the value or
 23        property of the old will not be changed.
 24        If the second argument is nil, the new symbol has no value
 25        and no properties (except possibly internal system properties.)
 26 
 27 nreconc  A subr of two arguments.
 28        (nreconc x y) is exactly the same as (nconc (nreverse x) y)
 29        except that it is more efficient.
 30 
 31 getcharn  A subr of two arguments.  gethcharn is identical to getchar
 32        except that the selected character is returned as a fixnum
 33        rather than as a character object.
 34 
 35 subrcall  An fsubr.  subrcall is used to invoke a subr-pointer directly,
 36        rather than by referring to an atomic symbol of which the
 37        subr-pointer is the subr property.  The form is:
 38           (subrcall type p a1 a2 ... an)
 39        All arguments except the first are evaluated.  type is the type
 40        of result expected:  fixnum, flonum, or nil (any type.)  p is
 41        the subr pointer to be called.  a1 through an are the arguments
 42        to be passed to the subr.
 43        subrcall compiles into efficient machine code.
 44 
 45 lsubrcall  An fsubr.  lsubrcall is identical to subrcall except that the
 46        subr-pointer called has to be an lsubr instead of a subr.  This
 47        is because many LISPs use different internal calling sequences
 48        for lsubrs and subrs.
 49 
 50 arraycall  An fsubr.  arraycall is similar to subrcall and lsubrcall
 51        except that an array-pointer is used instead of a subr-pointer.
 52        (See the section below on arrays.)  The first argument of
 53        arraycall must correspond to the type that the array was given
 54        when it was created.  An arraycall expression may be used as
 55        the first argument to store.
 56 
 57 Section 2.1, page 7
 58 
 59   An array is NOT always associated with an atomic symbol which is its
 60 name.  Rather, an array is always designated by an array-pointer, which
 61 is a special kind of atomic LISP object.  Frequently, an array-pointer
 62 will be placed on the property list of a symbol under the indicator
 63 array and then that symbol will be used as the name of the array, since
 64 symbols can have mnemonic names and are more easily referred to in
 65 typing at lisp than "pointers."
 66 
 67 Section 2.2, page 9 (typep)
 68 
 69 typep can also return the atom array, if its argument is an array-pointer.
 70 
 71 Section 4.1, page 24 (equal)
 72 
 73 The definition of equal given is grossly incorrect.
 74 The correct definition is:
 75     (defun equal (x y)
 76         (or (eq x y)
 77             (and (numberp x) (numberp y) (numequal x y))
 78             (and (not (atom x))
 79                  (not (atom y))
 80                  (equal (car x) (car y))
 81                  (equal (cdr x) (cdr y)))))
 82 
 83     with an auxiliary function for numeric equality, defined
 84     (approximately) as follows:
 85 
 86     (defun numequal (x y)     ;numerical equality
 87         (and (eq (typep x) (typep y))
 88              (zerop (difference x y))))
 89 
 90 
 91 Section 2.1, page 6.
 92 
 93 Another property of the special atomic symbol nil is that its
 94 car and its cdr are always nil.  This is true even if a property
 95 is putprop'ed onto nil; thus, unlike all other atomic symbols,
 96 (cdr nil) is not its property list.
 97 [This is not yet implemented in ITS LISP.]
 98 
 99 Section 6.1, page 48.
100 
101 The existence of the definedp predicate should not be relied upon.
102 boundp no longer returns (nil . value) if the symbol is bound;
103 instead it is a true predicate and returns t if the symbol is bound,
104 nil if it is not.
105 
106 Section 6.2, page 49.
107 
108 NOTE:  the property list of nil is not kept on (cdr nil).
109 
110 Section 6.4, page 53.
111 
112 getcharn is the same as getchar except that a number is returned
113 instead of a single character object.
114 
115 Section 7.7, page 71 (zunderflow)
116 
117 If zunderflow is non-nil, quotient of a flonum by a bignum which
118 is too large to be converted to a flonum will be regarded as a
119 floating underflow and so will return 0.0.
120 
121 Chapter 9, page 79.
122 
123   In the "new array" scheme which is now in MACLISP, the following
124 changes to the handling of arrays exist.  (In addition, the
125 introductory portion of Chapter 9 ought to explain what an array is,
126 for the benefit of those not cursed with a knowledge of FORTRAN.)
127 
128   There are several types of arrays.  The main types are ordinary
129 arrays, referred to by the type-code t, fixnum arrays, referred
130 to by the type-code fixnum, and flonum arrays referred to by the
131 type-code flonum.  Ordinary arrays are the same arrays as before,
132 capable of holding any type of data.  Fixnum arrays and flonum
133 arrays are "number" arrays, which can only hold fixnums or flonums
134 respectively.  These arrays permit more efficient code to be compiled
135 for numerical applications.  (See the array* declaration in chapter 14
136 and the arraycall function.)
137   The type of an array must be declared when it is created with array
138 or *array.  Some other types of arrays are un-garbage-collected arrays,
139 with a type-code of nil, which are the same as ordinary arrays except
140 that they are not protected by the garbage collector and therefore
141 can be used for certain esoteric hacks; obarrays, with a type-code of
142 obarray, which are used to maintain tables of known atomic symbols
143 so that the same atomic symbol will be referenced when the same pname
144 is typed in; and readtables, with a type-code of readtable, which are
145 used to remember the syntax specifications for the LISP input reader.
146 Normally, there is only one readtable and one obarray, supplied by the
147 system as the values of the atoms readtable and obarray, respectively,
148 but the user may create additional readtables and obarrays in order
149 to provide special non-LISP environments or to gain additional control
150 over the LISP environment.  The atoms readtable and obarray can be bound
151 to make the various functions which need them, such as read, employ a
152 user-supplied readtable or obarray.
153   An array-pointer may also be "dead", in which case it does not point
154 to any array.  One of the functions array, *array, or *rearray may be
155 used to revivify a dead array-pointer.
156   An array is designated by a special atomic object called an
157 array-pointer.  Array pointers can be returned by the array-creation
158 functions array and *array.  An array pointer may either be used
159 directly to refer to the array, or, for convenience in referring to
160 the array through input/output media, it may be placed on the property
161 list of an atomic symbol under the indicator array, and then that
162 symbol can be used as the name of the array (as before.)
163 
164   The first argument of array or *array may be an atomic symbol, which
165 makes that atomic symbol the name of an array, redefining the array
166 pointer on its property list if there already was one, or it may
167 be an array pointer, which causes that array pointer to be redefined,
168 or it may be nil, which causes a new array pointer to be created
169 and returned.  Except in the latter case, array returns its first
170 argument.  *array always returns the array pointer, never the atomic
171 symbol (this is an incompatibility.)
172   A readtable or an obarray may not be created with user-specified
173 dimensions.  The dimensions are always determined by LISP.
174 Ordinary and un-garbage-collected arrays are initialized to nil,
175 as before.  Fixnum arrays are initialized to 0.  Flonum arrays are
176 initialized to 0.0.
177   Obarrays are initialized according to the third argument of array
178 or *array.  nil causes a completely empty obarray to be created.
179 Not even nil will be interned on this obarray.  t causes the current
180 obarray (value of the symbol obarray) to be copied.  An array-pointer
181 which is an obarray, or an atomic symbol which names an obarray,
182 causes that obarray to be copied.  If no third argument is given,
183 the current obarray is copied.
184    Readtables are initialized in a similar fashion.  If the third
185 argument of array or *array is nil, then the current obarray is
186 copied.  If it is t, then the readtable being created is initialized
187 to the initial standard LISP readtable, including the macro characters
188 ' and ;.  An array-pointer or symbol of a readtable to be copied
189 may also be given.  If no third argument is given, the current readtable
190 is copied.  The reason that the interpretation of t and nil for
191 readtables if reversed from obarrays is for compatibility with the old
192 makreadtable function.
193   Note that an array-pointer may be REDEFINED to an entirely different
194 type and size of array.  It remains the same array-pointer, eq to
195 itself.  If a variable was setq'ed to the array-pointer, that
196 variable will now indicate the new array.
197   The *rearray function allows its first argument to be either an
198 atomic symbol with an array property, or an array-pointer.
199 If there is only one argument, the array is killed.  The array
200 becomes a "dead array" as described above.  If more than one
201 argument is given, they are the same arguments as to array or
202 *array.  *rearray with more than argument cannot be used to
203 change the type of an array, and cannot operate on a readtable
204 or an obarray.  The modified array will be initialized from
205 its old contents rather than nil, 0, or 0.0.  The elements
206 are taken in row-major order for initialization purposes,
207 and if there are not enough, nil, 0, or 0.0 will be used
208 to fill the remaining elements of the modified array
209 according to the type.
210   The array functions fillarray, listarray, bltarray, arraydims,
211 sort, and sortcar will accept array-pointers as well as symbols
212 with array properties.  In bltarray the types must match, except
213 that ordinary (t) and un-garbage-collected (nil) are considered
214 the same type.
215   In order to get the range of subscripts on arrays checked,
216 it is necessary to set the *rset flag non-nil, i.e. run in
217 (*rset t) mode, and to use interpreted code.  The amount of
218 checking performed when *rset is nil and/or compiled code
219 is used is not defined.
220 
221 
222 Section 12.3.1, page 95.
223 
224   CTRL/U is not actually implemented anywhere and some LISPs use
225 CTRL/H instead of CTRL/B.
226 
227 Section 12.5.2, page 109.
228 
229 The form of the "frames" returned by evalframe and errframe
230 is a list where the car is the type of frame, the cadr is
231 a pdl-pointer, the caddr is some data depending on the type of frame,
232 and the cadddr of the list is an alist-pointer (binding
233 context pointer.)  The three types
234 of frames are eval (evaluation), apply (apply, map, compiled call,
235 funcall, etc.), and err (error.)  The formats are:
236 
237     (eval <pdl-ptr> <form-or-symbol-being-evaluated> <alist-ptr>)
238 
239     (apply <pdl-ptr> (<function> . <argument-list>) <alist-ptr>)
240 
241     (err <pdl-ptr> (<message> <datum-in-error> <user-interrupt>)
242                      <alist-ptr>)
243 
244 In an err frame, the <datum-in-error> and/or <user-interrupt> may
245 be omitted, depending on the type of error.  Note that applying
246 the function error to caddr of an err frame will re-create the error.
247 
248 Section 12.7, page 120 (status & sstatus)
249 
250   The following 'status' functions have been added:
251 
252 (sstatus uuolinks t) - causes all "uuo links" from compiled
253 code that has been loaded to compiled functions or builtin
254 subrs, lsubrs, or fsubrs to be "snapped."  This can be used
255 to perform the link-snapping overhead only once, just before
256 a software package for general use is "save"ed.  (This only
257 exists in the Multics implementation at present.)
258 (sstatus uuolinks nil) or (sstatus uuolinks) performs the
259 previous function of unsnapping all uuo-links so that subrs
260 may be redefined.
261 
262 (status dow) returns an atomic symbol which is the name of
263 the current day of the week.
264 
265 (status linmode) reads the "line mode," and
266 (sstatus linemode x) sets the "line mode" to x (t or nil.)
267 In some implementations the "line mode" may not be changed.
268 If the "line mode" is t, user input is buffered up a line
269 at a time before being sent to LISP.  The input-editing
270 conventions of the host operating system are used.  If the
271 "line mode" is nil, LISP sees each character as it is typed
272 and applies its own input editing conventions.  This mode can
273 provide input facilities more suited to LISP and possibly better
274 handling of the terminal, if it is a type that LISP knows a
275 great deal about.  However, it uses more machine resources.
276 It is possibly for a user program to take direct control of the
277 terminal when the "line mode" is t, however this may require
278 knowledge of the undocumented (sstatus tty) function.
279 The Multics implementation always operates with a "line mode" of t.
280 The ITS implementation at present only operates with a "line mode"
281 of nil.
282 
283 (status newline) - returns a fixnum which is the ascii code for
284 the character used to mark the end of a line of input.  End of line
285 may be checked for by
286                 (= (setq ch (tyi)) (status newline))
287 
288 (sstatus feature foo) - makes foo a feature.  Thus user- or
289 system-supplied packages which are loaded into the environment
290 can set features indicating their presence, as an extension
291 of the features set by LISP itself to indicate its own features.
292 foo is not evaluated.  For example, the "trace" package does
293 (sstatus feature trace) and the "grind" and "grindef" S-expression
294 formatting package does (sstatus feature grind) and (sstatus feature
295 grindef), depending on how much of it has been loaded in.
296 Similarly, the compiler will set (sstatus feature compiler),
297 and (sstatus feature fastarith) if it has the capability of producing
298 fast code for arithmetic operations, to inform the program being
299 compiled of what is going on.
300 
301 (sstatus nofeature foo) turns off the foo feature.  foo is not
302 evaluated.  This is used by packages that have the ability
303 to remove themselves from the environment upon a command
304 such as (remtrace).
305 
306 (sstatus crfile foo bar) sets the file names in the defaults
307 used by uread, etc. to foo bar.  In effect, this sets
308 the "current file."
309 
310 Section 13.4.1, page 152 (cursorpos.)
311 
312   (cursorpos 'L) is intended to supersede (cursorpos ']).
313 They do the same thing, it is just a better name for the function.
314 
315 Section 13.7, page 164.
316 
317   The printer prints an array-pointer as a sharp sign (#),
318 followed by the type of array, followed by the dimensions,
319 followed by the machine address of the array in a format
320 useful to system debuggers.  In the case of a dead-array,
321 only "#dead-array" is printed.  An example of the format
322 is shown below:
323 
324                 #FIXNUM-4:3-343425   (ITS)
325   or            #fixnum-4:3-335|2206 (Multics)
326 
327 The reader will not recognize such strings, if fed back into
328 it, as array-pointers.  They will probably be read as atomic
329 symbols.
330 
331 Section 13.9, page 175.
332 
333   The "display slave" still does not exist in Multics LISP,
334 unfortunately.
335 
336 Section 14.2, page 186 (array* declaration.)
337 
338   The extended form (array* (type (arr1 dim1.1 dim1.2 ... dim1.n) ...))
339 can be used.  The dimensions declared must be either fixnums
340 or nil or ?, which indicate a dimension not known at compile time.
341 If dimensions are declared, the compiler can generate faster code.
342   The array* declaration causes the compiler to generate in-line code
343 for accesses of and "store"s into the arrays declared.  This code
344 is somewhat faster than the usual subroutine-call array accessing.
345 The compiler will also generate in-line code if the arraycall function
346 is used; in this case the array must be named by an array-pointer
347 rather than by an atomic symbol.
348 
349 Section 14.2, page 187.  (closed declaration)
350 
351 The following declaration was accidentally omitted:
352 
353 (closed t) causes arithmetic operations to be close-compiled,
354 that is the function + will generate in-line code but the function
355 plus will not in any circumstances.  This declaration is necessary
356 if you take plus of two fixnums and want a bignum if the result
357 overflows.  If the declaration is not specified, the compiler will
358 produce code that assumes overflow will not occur, which may
359 give incorrect results in the above case.
360 
361 (closed nil) reverses the effect of (closed t), allowing the compiler
362 to generate in-line code for functions such as plus when it can
363 identify, by declaration or implication, the operands to be all
364 fixnums or all flonums.
365 
366 Section 15, page 224.
367 
368   The "strace" package is a highly out of date version of trace;
369 in fact, you may not be able to find it at all at your site.
370 However, if the variable sprinter is
371 setq'ed non-nil, trace will use the grind package to do its output,
372 so "strace" is no longer necessary.
373 
374   The trace specifications may be "factored."  For example,
375 
376             (trace ((foo bar) value wherein baz))
377 is equivalent to
378             (trace (foo value wherein baz) (bar value wherein baz))
379 
380 Section 16.5, page 237.
381 
382   The grinder directive ;;*ppage has been renamed to ;;*user-paging.
383 
384 Section 4.1, page 28.
385 
386 Append the following to the end of the section:
387 
388 maknum     SUBR 1 arg
389 
390 (maknum x) returns a non-negative fixnum which is uniquely
391 associated with x.  x may be any LISP object.  It is uniquely
392 associated in the sense that (maknum x) is numerically
393 equal to (maknum y) if and only if (eq x y) is true.
394 
395 munkam     SUBR 1 arg
396 
397 munkam is the reverse of maknum.  Given a number which was
398 obtained from maknum, munkam returns the object which was
399 given to maknum to get it to return that number.
400 
401 
402 Chapter 15, page 224.
403 
404 Replace the last two paragraphs on page 224 with the following:
405 
406 All output printed by trace can be ground into an indented,
407 readable format, by simply setting the variable sprinter to t.
408 Setting sprinter to nil changes the output back to use
409 the ordinary print function, which is faster and uses less
410 storag but is less readable for large list structures.
411 
412 
413 Add to the end of chapter 9.
414 
415    Number arrays may be efficiently saved in the file system and
416 restored by using the functions loadarrays and dumparrays.
417 
418 loadarrays       SUBR 1 arg
419 
420 (loadarrays <file-spec>) reloads the arrays in the file,
421 and returns a list of 3-lists, of the form:
422 
423       ( (<newname> <oldname> <size>) ... )
424 
425 <newname> is a gensym'ed atom, which is the name of the reloaded
426 array.  <oldname> is the name the array had when it was dumped.
427 <size> is the number of elements in the array.
428 
429 dumparrays      SUBR 2 args
430 
431 (dumparrays (<array1> <array2> ... ) <file-spec>)
432 dumps the listed arrays into the specified file.  The arrays
433 must be fixnum or flonum arrays.
434 
435 In both of the above, the <file-spec> argument is dependent
436 on the system.  In ITS or DEC-10 LISP, the <file-spec> is a
437 list of 0 to 4 items, as in uread, and the same defaults
438 apply.  In Multics LISP, the <file-spec> is an atomic symbol
439 or a string which gives the pathname of the segment to be used.
440 The defaults and other features of the LISP I/O system are
441 not applied.  Only a segment may be specified; not a stream.
442 
443 As a special compatibility feature, in Multics LISP loadarrays
444 will recognize a pdp-10 dumparrays file.  (One can be moved to
445 Multics through the ARPA network File Transfer Protocol if the
446 type image and bytesize 36 commands are employed.)  The pnames
447 will be converted to lower case and any flonums present will
448 be converted appropriately.  dumparrays can create a file
449 which pdp-10 loadarrays can read, including upper-case pnames
450 and pdp-10 format flonums, if it is invoked as follows:
451 
452       (dumparrays (<array1> <array2> ...) '(pdp10 <file-spec>))
453 
454        More New Functions
455 
456 maknum       SUBR of 1 argument
457 
458   (maknum x) returns a positive fixnum which is unique to the
459 object x; that is, (maknum x) and (maknum y) are numerically
460 equal if and only if (eq x y).  This can be used in hashing.
461 In the pdp-10 implementations, maknum returns the memory address
462 of its argument.  In the Multics implementation, an internal
463 hash table is employed.  Note that unlike sxhash, maknum will
464 not return the same value on an expression which has been print'ed
465 out and read bac in again.
466 
467 munkam          SUBR of 1 argument
468 
469    munkam is the opposite of maknum.  Given a number, it returns
470 the object which was given to maknum to get that number.
471 
472 ^               SUBR of 2 arguments
473 
474   ^ is the fixnum-only exponentiation function.  It is somewhat
475 faster than expt, but requires its arguments to be fixnums, uses
476 fixnum arithmetic, and always returns a fixnum result.  Note that
477 in situations where expt would have returned the correct result
478 in bignum form, ^ will give an arithmetic overflow error.
479 
480 ^$           SUBR of 2 arguments
481 
482   ^$ is the flonum-only exponentiation function.  The first argument
483 must be a flonum, the second must be a fixnum (repeat, a FIXNUM),
484 and the result is a flonum.
485 
486 symeval        SUBR of 1 argument
487 
488   symeval is used to get the value of an atomic symbol, when
489 which symbol is to be used is not known when the program is
490 written, for example in an interpreter written in lisp.  If
491 the argument to symeval is not an atomic symbol, or is an
492 atomic symbol but does not currently have a value, an error
493 is signalled.  The advantage of symeval over eval is that
494 it is compiled into very efficient code (which will not
495 detect the above error, so watch out.)
496 [The ITS implementation does not seem to have this function yet.]
497 
498 uprobe        FSUBR
499 
500 Takes arguments like uread and returns t if the specified file
501 exists, nil if it does not.
502 
503 uappend       FSUBR
504 
505 Takes arguments like uread, but opens the specified file for output
506 like uwrite does, renaming the file so no one else will get at it
507 while you are outputting to it.  ufile is used to finish outputting
508 and rename the file back.  The difference between uappend and uwrite
509 is that the output is stuck onto the end of the file, instead of
510 replacing what was previously there.
511 
512 uclose         SUBR of no arguments
513 
514 (uclose) closes the uread input file.  This is useful before a
515 suspend (ITS) or a save (Multics.)
516 
517             Changes to Existing Functions
518 
519 expt now allows its second argument to be a flonum, in which case
520     the first argument is converted to a flonum and the
521     exponentiation is performed in floating point, using
522     logarithms.  The result is a flonum.
523 
524 defprop and defun now do a remprop before they do a putprop.  This
525     ensures that the property they put on always comes first
526     in the property list, which is useful in cases such as
527     replacing a subr with an expr when the subr replaced a
528     previous expr.
529 
530 remprop returns a different value when it finds the property
531     to be removed.  Instead of t, the part of the property
532     list beginning with the indicator removed is returned.
533     This is a value similar to what getl returns.
534 
535 On page 19, chapter 3.
536 
537    The statement that the funarg facility does not correctly
538 handle setq's is no longer operative.  setq's will be performed
539 in the correct environment no matter what combination of
540 *function's, a-list (or binding context) pointers, etc. you use.
541 
542 In chapter 13.
543 
544   You should no longer use nil to indicate the terminal to an
545 I/O function, for instance (read nil) or (print x nil).  Instead,
546 t should be used.  nil will still work for quite a while.  Later
547 nil will be changed to mean "the default."  Consequently,
548 
549 On page 145
550 
551   (read t) should be changed to (read infile t).
552 
553 Add to page 89.
554 
555         Variables used by the top-level read-eval-print loop
556 
557 *  contains the last S-expression printed out by the read-eval-print
558     loop, that is, the value of the last form typed in.  After an
559     error return to top level, the value of * is * itself, since
560     a star has just been typed out.
561 
562 + contains the value of the last S-expression typed in.  This can
563     be used to edit it or to do it over again.
564 
565 - contains the value of the current S-expression typed in.  This is
566     mostly just used to hold this form until after it has been
567     evaluated, at which time (setq + -) is done.
568 
569 By special dispensation the value of + is preserved across a break.
570 That is, when an error-break is entered (assuming the user has
571 not replaced the system handler for the error with his own) the
572 value of + is the form which was last typed, normally the one
573 which caused the error.  While the user types forms at the
574 break-loop, the value of + is set to each form he types in the usual
575 way.  When the user returns from the break, + is set back to
576 the form typed before the break was entered (the last form typed
577 at top level.)  Actually, if you think about it you will see
578 that this is done by binding -, not +.
579 
580 // is used to temporarily hold the value of errlist when an error
581 returns to top level.  This is so that lambda-binding errlist will
582 have an effect (assuming no one lambda-binds //).
583 
584 The top-level form given on page 89 should be revised to read:
585 
586 (errset
587   (progn
588     (setq ^r nil ^q nil ^w nil)      ;reset internal vars
589     (mapc 'eval //)                  ;do errlist, which // was set to
590     (setq * '*)                      ;cause an asterisk to be typed
591     ;now enter the read-eval-print loop, remaining
592     ; there unless an error should occur.
593     (do nil (nil)                    ;= do forever
594       (setq * (cond ((status toplevel)
595                      (eval (status toplevel)))
596                     (t (print *)
597                        (terpri)
598                        (eval (setq - (read))))
599                 ))
600      (setq + -)) ))
601 
602 The defpl1 declaration, page 187.
603 
604             Using the `defpl1' feature of the lisp compiler
605 
606   The Multics lisp compiler provides a feature by which you can compile
607 a lisp subr which represents, in the lisp environment, a subroutine
608 in the outside world which has a PL/I-compatible calling sequence.
609 When the lisp subr is applied, the subroutine will be called with
610 arguments derived from the arguments given to the lisp subr.  Results
611 returned by the subroutine may be passed back to lisp either as the
612 return value of the lisp subr, or by setq'ing an atomic symbol.
613 
614   Because lisp and PL/I use different data types, a correspondence between
615 the types must be set up:
616 
617   Numbers.  fixed binary with a precision not more than 35. corresponds
618 to the lisp fixnum.  float binary with a precision of not more than 27.
619 corresponds to the lisp flonum.  Nonzero scale factors, complex numbers,
620 decimal or pictured numbers, and large precisions are not supported.
621 
622   Bit strings.  A bit string of up to 36. bits corresponds to a lisp
623 fixnum.  The bits are stored left-justified in the fixnum, thus in
624 the case of bit(1) the fixnum is 0 for "0"b and negative for "1"b.
625 Note that because of the left-justification most bit strings map into
626 "illegal" fixnums which cannot be typed in as octal numbers (because
627 a bignum would be produced.)  The `lsh' function can be useful here.
628 These bit strings work as either `aligned' or `unaligned.'  Bit strings
629 longer than 36. bits are not supported.
630 
631   Character strings.  Lisp character strings and PL/I character strings
632 correspond directly.  For input arguments, lisp will also automatically
633 convert an atomic symbol to a character string by taking its pname, as
634 usual.  Usually the PL/I argument will be declared `char(*).'
635 For output arguments, you must declare the character string with
636 some fixed length, even if it is declared "char (*)" in the PL/I
637 program.  The construct "(return char (*))", however, IS supported,
638 for the last argument only, to produce the arbitrary-length
639 result of the PL/I "returns char (*)" construct.
640 
641   Varying Character Strings.  Varying character strings are somewhat
642 special.  Lisp will take whatever string argument you supplied (the null
643 string if it is a `return' argument) and create a varying string of
644 the length you declared, initialized to the string you supplied.  Thus
645 usually its current length will be less that its maximum length.
646 This varying string will be passed to the PL/I subroutine.  When the
647 subroutine returns, whatever it leaves in the varying string will
648 be made back into a lisp string and returned (if it is an `update'
649 or `return' argument.)  This procedure is necessary because lisp
650 strings may not vary in length.  Note that you must declare the
651 length of the string; `char(*) varying' is illegal.  However, the
652 PL/I subroutine may declare it `char(*) varying' since a descriptor
653 is passed.
654 
655   Pointers.  Both packed and unpacked pointers are supported.  These are
656 both represented in lisp as fixnums in packed pointer format, that is
657 2 octal digits of bit offset, 4 octal digits of segment number, and 6
658 octal digits of word offset.  The null pointer is 007777000001 octal.
659 It is not possible to reference, within lisp, what a pointer points at.
660 Because of the packed pointer representation, ring numbers in pointers
661 are not supported.  If you declare the PL/I subroutine to take unpacked
662 pointers, which is the default, lisp will do the conversion between
663 packed and unpacked representations.
664 
665   Raw lisp objects.  A PL/I subroutine which knows about lisp may be
666 passed (or return) raw lisp objects.  In PL/I these should be
667 declared `fixed bin(71)' and then the based overlays declared in sundry
668 lisp include files should be used.
669 
670   Arrays.  Arrays of any number of dimensions may be passed.  The arrays
671 can only contain numbers or raw lisp objects however.  Usually you
672 would pass a lisp fixnum (or flonum) array and in PL/I declare it
673 dimension(*,*) fixed bin(35) (or float bin(27).)  In the dimension
674 attribute put as many stars as there are dimensions.  Proper matching
675 of types and dimensions will be checked at run time.
676 NOTES:  Arrays with more than 15 dimensions may tend to lose.  If you
677 are calling a Fortran program, you need to be aware that for multi
678 dimensional arrays, Fortran interchanges the order of the subscripts.
679 Arrays as return or update arguments (defined below) are not supported.
680 However, the lisp array is passed by reference, so if the PL/I subroutine
681 stores into elements of the array the appropriate thing will happen.
682 
683   Because lisp passes arguments by value, while PL/I passes arguments by
684 reference, it is necessary to pay attention to whether an argument is
685 input to the PL/I subroutine, output from (returned by) the PL/I subroutine,
686 or both (updated by the PL/I subroutine.)  `Output from' includes both
687 arguments that are stored into and values returned by a return statement.
688 If the PL/I subroutine has a `returns' attribute, this is considered
689 to be an extra argument stuck on the end of the argument list.  Note that
690 PL/I `returns(char(*))' is a special case, and is supported.  Return
691 of bit (*) is not supported.
692 
693   Input arguments to the PL/I subroutine are derived from arguments to
694 the lisp subr according to the data type transformations described above.
695 
696   Return arguments from the PL/I subroutine are passed back to lisp
697 according to the user's declaration; they may be ignored, setq'ed onto
698 an atomic symbol, or passed back as the value of the lisp subr.  If
699 more than one is passed back in the latter way, they are consed up into
700 a list.  If there are none, nil is returned.
701 
702   Update arguments are a combination of the two types described above.
703 They are derived from the arguments to the lisp subr, and they are also
704 passed back like return arguments.
705 
706   Now the detailed syntax of the `defpl1' feature will be described.
707 It is invoked by using the defpl1 declaration in the lisp compiler,
708 in a form generally as follows:
709 
710     (declare (defpl1 lisp-name external-name (arg-dcl-1)
711                 (arg-dcl-2) ... (arg-dcl-n) ))
712 
713   lisp-name is an atomic symbol, which will be defined as a subr when
714 the output of the compilation is `load'ed.  This subr will take as
715 many arguments as the PL/I subroutine has input and update arguments.
716 
717   external-name is a string which is the name of the subroutine to
718 be called, as it would be written in PL/I.  If external name is "",
719 the pname of lisp-name will be used so that you need not type the
720 same thing twice.
721 
722   (arg-dcl-1) through (arg-dcl-n) are lists.  Each one gives the
723 attributes of one of the arguments to the PL/I subroutine.  First
724 you must give attributes describing whether it is an input, update,
725 or return argument.  These are:
726 
727     <no attribute given>        an input argument
728 
729     return                      a return argument, passed back as
730                                 the value of the subr.
731 
732     return ignore               a return argument which is ignored.
733 
734     return (setq var)           a return argument to which the atomic
735                                 symbol var is setq'ed.  var should be
736                                 declared special.
737 
738     update                      an update argument, passed back as
739                                 the value of the subr.
740 
741     update ignore               an update argument whose returned
742                                 value is ignored.
743 
744     update (setq var)           an update argument whose returned
745                                 value is setq'ed onto var.
746 
747   Next you specify the data type attributes, in a form quite similar
748 to the way you would in PL/I.  (But don't forget that the declaration
749 of each argument is enclosed in its own pair of parentheses, instead
750 of being separated from the others with commas.)  The following
751 keywords are recognized for data type attributes:
752 
753     fixed       float      binary      bin         bit
754     pointer     ptr        packed-ptr  packed-pointer
755     character   char       aligned     unaligned   lisp
756     array       varying
757 
758   Note that `packed-pointer' is used rather than `pointer unaligned,'
759 and `array' is used rather than `dimension.'  `lisp' means a
760 raw lisp object.  Precisions, array extents, and string lengths
761 are specified as parenthesized numbers or asterisks, just as in PL/I.
762 Note that unless you declare otherwise to the compiler or put a
763 decimal point, these numbers will be interpreted as octal.
764 
765   Here is an example, although not of a very useful case:
766 
767     (declare (defpl1 hcs_$initiate "" (char(*)) (char(*))
768               (char(*)) (fixed bin(1)) (fixed bin(2))
769               (return pointer) (return (setq code) fixed bin(35))))
770 
771 If this was compiled and loaded into lisp, you could type
772 
773     (hcs_$initiate ">system_control_1" "whotab" "" 0 0)
774 
775 and lisp would reply with a number such as 356000000, and code
776 would have been setq'ed to 0 presumably.
777 
778 [END]