The Pitmanual: System Programming

The Revised Maclisp Manual The Pitmanual Page A-24


System Programming

TTY-Related Interrupts


TTY Interrupts Concept Control Characters

It is possible to define control characters in Lisp to execute functions at interrupt level. Handlers can be be set with the TTYINT option to STATUS and SSTATUS .

Interrupt handlers are normally functions of two arguments, char and stream (upon which char was typed).

Certain primitive character interrupt handlers are defined which are safe to run even if garbage collection is in progress. Rather than use a function name, these primitive handlers are identified by the numeric code for the character which initially had the desired functionality. For example, the initial handler for Control-G is called 7 (or #^G ).

The following control characters are defined as interrupt characters in Maclisp:

Char Handler Effect
Control-A #^A (SETQ ^A T )
Control-B +INTERNAL-^B-BREAK (BREAK ^B)
Control-C #^C (SETQ ^D NIL )
Control-D #^D (SETQ ^D T )
Control-G #^G (^G )
Control-R #^R (SETQ ^R T )
Control-S #^W (SETQ ^W T )
Control-T #^T (SETQ ^R NIL )
Control-V #^V (SETQ ^W NIL )
Control-W #^W (SETQ ^W T )
Control-X #^X (ERROR 'QUIT )
Control-Z #^Z (VALRET "")

Interrupt handlers run with interrupts disabled unless the handler function explicitly re-enables interrupts.

Also, the interrupting character will still be on the input stream. In fact, there may be other characters ahead of it on the input stream since an interrupt runs immediately even before finishing pre-scanning other non-interrupting input.

Note that Control-S has the same definition as Control-W but a different effect. This is because Control-S only disables typeout at the interrupt level. Later, when seen by READ (usually in the Read-Eval-Print loop), it is also a splicing readmacro character which turns type-out back on. Control-W lacks this readmacro definition, so leaves typeout turned off until a Control-V is typed or until the variable ^W is somehow turned back on.

Control-H (backspace), which many Lisp versions ago caused a Lisp breakpoint is now a normal alphabetic character. Control-B has superseded it as the proper way to invoke a breakpoint at interrupt level.

Control-K (which re-types input to the READ and READLINE functions) and Control-L (which clears the screen and then re-types input) are not interrupt characters. They are handled at the tty prescan level.

Control-Q is not an interrupt character, it is a tty force-feed character.

The tty interrupt status of a character may be a function of two arguments or a fixnum.

If it is a function, then when the interrupt occurs it receives as arguments the file on which the interrupt occurred, and the character typed, as a fixnum.

If the function is a fixnum, it represents the internal system interrupt initially associated with the character whose ASCII code is the value of the fixnum. Not all codes are valid; it must be one of #^A , #^C, #^D , #^G , #^R , #^S, #^T, #^V, #^W , #^X, or #^Z.


TTYINT SStatus Option (SSTATUS TTYINT char val [fileobj])

[PDP-10 Only] Sets the tty interrupt information for char on a given tty input file array, fileobj (default T , the terminal), to a given val, which must be a handler such as would be later returned by (STATUS TTYINT ...).

Multics users may want (STATUS INTERRUPT ).

;; Set up control-E to type a stupid message.
(sstatus  ttyint  #^e #'(lambda  (stream char) (print 'hi)))
=> T 
;; Now type Control-E to test it. Note that the interrupt 
;; runs before the character echos!
HI ^E
;; Set up Control-F to do what Control-G does.
(SSTATUS  TTYINT  #^F  #^G )
;; Now type Control-F to see how it works
QUIT 
* 

Note that an interrupt can be associated with any ASCII character, not just control characters. On ITS , one must use (SSTATUS TTY ) to tell ITS that things like "?" or "#" are to be considered interrupt characters (this is similar to the activation character problem).

Note also that initially Control-S is set to be like Control-W as an interrupt character (see below).


TTYINT Status Option (STATUS TTYINT char [fileobj])

[PDP-10 Only] Returns the tty interrupt information for char on a given tty input file array, which defaults to T , the terminal. All argument positions are evaluated.

The char may be a character in fixnum or symbol representation.


^A (Uparrow A) Value NIL

In the initial Lisp system, Control-A is an interrupt which sets ^A to T . This was from the early days of Lisp when general tty interrupts were not available -- programs could query the value of ^A to see if it had changed from NIL (and reset the value to NIL so they could detect such interrupts again later).

Externally Signalled Interrupts


CLI-MESSAGE Value NIL

[ITS Only] The symbol CLI-MESSAGE , if not NIL , should be a function of one argument which handles a interrupt on the Lisp job's CLI device. The argument may be ignored since it is always NIL . To handle the interrupt, the function should open the “CLA:” device in order to read the message. One of the options in OPEN 's second argument should be CLA (as opposed to DSK or TTY ) because of the format of the input stream read from the CLA device (see ITS system documentation for more about this problem). This causes open to read the first two words of the file and use them as the file names for the truename function. The CLA: file should be opened in block mode for this purpose.

If CLI-MESSAGE is set to NIL , such interrupts are ignored. This is the default case.



[ITS only] Says whether CLI handling is enabled. See documentation on the CLI-MESSAGE variable.



[ITS Only] If flag is T , enables CLI handling using the handler given by the CLI-MESSAGE variable. If flag is NIL , disables CLI interrupt handling.

Web-Only Note:

The following is some sample code (complete with documentation) that I found in my notes and thought might be helpful:

;;; Notes about CLI  interrupts:
;;;
;;; A CLI  interrupt  is what happens when another job sends to yours. It is
;;; normally the case that other jobs will send directly to a user's HACTRN .
;;; If, however, Lisp is interrupted by a CLI  message, it can elect to handle
;;; handle the interrupt  in an arbitrary way.
;;;
;;; To define a handler, two things must be done:
;;; [1] Place the name of the handler function (function of one arg)
;;;	 in the variable CLI-MESSAGE .
;;; [2] Enable CLI  handling with (SSTATUS  CLI  T )
;;;
;;; The handler should take a single argument which it probably should ignore
;;; since I have no idea what it is likely to be.
;;;
;;; The handler should open the file "CLA:" in (CLA BLOCK) mode and immediately
;;; discard the first 8 characters which will be garbage.
;;;
;;; The remainder  of the stream, until a control-C or an eof, will be the text
;;; of the message sent. It may be read with TYI , READ , etc. and handled 
;;; however.
(eval-when  (eval  compile )
 (cond  ((not (get 'iota 'version ))
 (load  "liblsp;iota"))))
(defun  handle-cli-msg (ignore)
 (iota ((stream '((cla)) '(cla block)))
 (do ((i 0 (1+  i))) ((= i 8)) (tyi  stream))
 (do ((c (tyi  stream -1) (tyi  stream -1)))
 ((or (= c -1) (= c 3)))
 (format t  "~&~3,'0O ~@:C~%" c c)))) ;print out chars seen
(setq  cli-message  'handle-cli-msg)
(sstatus  cli  t )
; --------
(defun  eval-cli-msg (ignore) ;alternate handler
 (iota ((stream '((cla)) '(block cla)))
 (do ((i 0 (1+  i))) ((= i 8)) (tyi  stream))
 (do ((f (read stream nil ) (read stream nil )))
 ((null f))
 (errset  (eval  f) nil )))) ;Quietly evaluate forms...
;; Assumes the other lisp will have EVAL-CLI-MSG as value of CLI-MESSAGE 
(defun  eval-in-other-lisp (uname  jname  s-expression)
 (iota ((stream `((cli ) ,uname  ,jname ) '(out ascii  block)))
 (print s-expression stream)))

SYS-DEATH Value NIL

The value of this variable is a handler to be called if an interrupt is received from the operating system saying that the system is going down.

Web-Only Note:

Here's a sample use of this that I had laying around. Note that +EXTERNAL-YES\ NO-PREDICATE was one of my personal utility functions, not something pre-defined by MACLISP, so think of it as like YES-OR-NO-P in Common Lisp. Likewise, SAVE was a FEXPR that I had defined elsewhere, and (LSDMP DEATH) is not an evaluable form, but a filename in which SAVE will put data.

(SETQ  SYS-DEATH  'SYS-DEATH-HANDLER)
(DEFUN  SYS-DEATH-HANDLER N
 (COND  ((AND  (ZEROP  (CADR  (STATUS  ITS )))
 (OR  (NOT  (STATUS  TTY ))
 (+EXTERNAL-YES\ NO-PREDICATE ;user-defined
 '|Sys going down. Save environment?|)))
 (SAVE (LSPDMP DEATH)))))


[ITS Only] Useful in conjunction with the SYS-DEATH interrupt is (STATUS ITS ). This returns a list of five numbers:

(1) A flonum number of seconds until system is to go down.
-1.0 means the system does not plan to go down.
-2.0 means the system is already down.
(2) A fixnum, non-zero if the system is being debugged.
(3) The number of users on the system, as a fixnum.
(4) The number of memory errors the system has survived.
(5) A flonum number of seconds that the system has been up.

This information is obtained from the ITS SSTATU system call.

Web-Only Note:

No, amazingly enough, that's not a joke about -2.0 above. I thought it was but when I questioned it one day, someone with more skill about these things than I ever had just laughed and took me to the ITS system console, brought down timesharing on the mainframe (which leaves one in single-user mode typing to the console). In this mode, the relevant system call returns -2.0, indicating that timesharing is down.


TTY-RETURN Value NIL

[ITS Only] This is a handler to be run upon return from the superior job.

Alarm Clocks


ALARMCLOCK Function (ALARMCLOCK timername q)

[ITS and Multics only] ALARMCLOCK is a function for controlling timers. It can start and stop two seperate timers; one is a real-time timer and the other is a cpu-time timer. The first argument to ALARMCLOCK indicates which timer is being referred to: it may be the symbol TIME to indicate the real-time timer or the symbol RUNTIME to indicate the cpu-time timer. The second argument to alarmclock controls what is done to the selected timer. If it is a positive (non-bignum) number the timer is started. Thus if q is a positive fixnum or flonum, then (ALARMCLOCK 'TIME q) sets the real-time timer to go off in q seconds, and (ALARMCLOCK 'RUNTIME q) sets the cpu-time timer to go off in q microseconds. If the timer was already running the old setting is lost. Thus at any given time each timer can only be running for one alarm, but the two timers can run simultaneously. If the second argument to ALARMCLOCK is not a positive number, the timer is shut off, so (ALARMCLOCK timername NIL ) or (alarmclock timername -1) shuts off the timer. ALARMCLOCK returns T if it starts a timer, NIL if it shuts it off. When a timer goes off, the handler for that interrupt (controlled by the variable ALARMCLOCK ), if any, is run in (NOINTERRUPT T ) mode so that it can not be interrupted until it has done its thing. If it wants to allow interrupts, other timers, etc. it can do (NOINTERRUPT NIL ). In any case the status of the nointerrupt flag will be restored when the handler function returns (see NOINTERRUPT ).


ALARMCLOCK Value NIL

[ITS and Multics only] The value of alarmclock is the handler for the timer interrupt, which is signalled when a timer set up by the ALARMCLOCK function goes off.

The handler function should be a function of one argument, which will be a list of one element, the symbol TIME or the symbol RUNTIME , depending on the first argument in the call to the ALARMCLOCK function which set up the timer.


SLEEP Function (SLEEP k)

causes a real-time delay of k seconds, then returns T . k may be a fixnum or a flonum.

Enabling/Disabling Interrupts


NOINTERRUPT Function (NOINTERRUPT val)

[PDP-10 Only] (NOINTERRUPT T ) shuts off Lisp interrupts. This prevents alarmclock timers from going off and prevents the use of control characters such as Control-G and Control-B. Any of these interrupts that occur are simply deferred until interrupts are re-enabled. (NOINTERRUPT T ) mode is used to protect critical code in large subsystems written in Lisp. It is also used by the Lisp subsystem itself to protect against interrupts in the garbage collector.

(NOINTERRUPT NIL ) turns interrupts back on. Any interrupts which were saved will now get processed. NOINTERRUPT returns the previous state of the interruptdisable switch, T or NIL . The normal, initial state is NIL .

In most cases, it is best to bind interrupts using the WITHOUT-INTERRUPTS special form.



Reads the value of the pseudo-variable +INTERNAL-WITHOUT-INTERRUPTS . This variable should never be set, only bound. To set it, use (SSTATUS NOINTERRUPTS ...). Even when bound, it will always appear to be bound to NIL . This is the only right way to read the value it has been bound to.


NOINTERRUPTS SStatus Option (SSTATUS NOINTERRUPTS flag)

Sets the value of (STATUS NOINTERRUPTS ) to T or NIL according to flag.


WITHOUT-INTERRUPTS Special Form (WITHOUT-INTERRUPTS form1 form2 ...)

Executes form1, form2, etc. from left to right returning the value of the last. During execution, interrupts are disabled. After execution, interrupts are restored to the state they had prior to the WITHOUT-INTERRUPTS form. If interrupts had been off, they remain off; if interrupts had been enabled, they are re-enabled.


STATUS Special Form (STATUS key [data1 [data2 ...]])

Returns useful information about lots of things. What things the information is about, which kinds of data are required, and even whether various argument positions are evaluated or not depends on the choice of key.

The key argument position itself is not evaluated. It turns out that STATUS , unlike nearly all other functions in Lisp, does not do dispatching using EQ , but rather looks at the first five characters of the symbol to determine if it matches. This behavior causes many programmers to write (STATUS OPSYS) when they mean (STATUS OPSYSTEM-TYPE ), (STATUS FILES) or (STATUS FILESYS) when they mean (STATUS FILESYSTEM-TYPE ), etc. Doing this is not encouraged, as it is intended that the implementation of STATUS may some day be corrected and programs which cheat may break.

In this documentation, all argument positions to STATUS may be assumed to evaluate (except, of course, the key) unless otherwise noted.

To see a list of possible STATUS keys, see the Status Option Index.


STATUS Status Option (STATUS STATUS [key])

If key is supplied, returns true iff the given key is a valid first argument to STATUS . If key is not supplied, returns a list of all valid first arguments to STATUS . The key is not evaluated.

To see a list of possible STATUS keys, see the Status Option Index.


SSTATUS Special Form (SSTATUS key [data1 [data2 ...]])

Sets the state of various switches in the Lisp system. The state of many, but not all, of the things which SSTATUS can set can be read with (STATUS key ...). SSTATUS and STATUS share the same peculiar argument conventions; see documentation on STATUS for details.

To see a list of possible SSTATUS keys, see the SStatus Option Index.


SSTATUS Status Option (STATUS SSTATUS [key])

If key is supplied, returns true iff the given key is a valid first argument to SSTATUS . If key is not supplied, returns a list of all valid first arguments to SSTATUS . The key is not evaluated.

To see a list of possible SSTATUS keys, see the SStatus Option Index.

The ``Features List''


FEATURES Status Option (STATUS FEATURES)

Returns a list of symbols representing the features implemented in the LISP being used. The main idea behind this STATUS call is that an application package can be loaded into any MACLISP implementation and can decide what to do on the basis of the features it finds available. e.g., possible features include:

BIBOP Using PDP-10 “big bag of pages” memory management.
LAP “Lisp Assembly Program” facility available.
SORT Sorting functions (SORT , SORTCAR ) are present.
EDIT EDIT function is present.
FASLOAD FASLOAD facility is present.
^F “Moby I/O” facility is present.
BIGNUM Arbitrary-precision arithmetic is available.
STRINGS Character strings and related functions are present.
NEWIO All of the new-I/O functions are present.
MC This Lisp is on the MIT-MC machine.
ML This Lisp is on the MIT-ML machine.
AI This Lisp is on the MIT-AI machine.
H6180 This Lisp is on an H6180 (e.g., MIT-MULTICS).
PDP10 This Lisp is on a DEC PDP-10 machine.
ITS This Lisp is on some ITS system.
MULTICS This Lisp is on some Multics system.
DEC10 This Lisp is on some DEC TOPS-10 (or TENEX).
Note: TENEX runs under a TOPS-10 emulator.
NOLDMSG Disable “;Loading ...” typeout by HERALD forms.

The old idiom (CAR (LAST (STATUS FEATURES ))), which was generally considered to be an implementation name, such as ITS or DEC10 or Multics is now discouraged. Use (STATUS SITE ), (STATUS FILESYSTEM-TYPE ), or (STATUS OPSYSTEM-TYPE ) as appropriate instead.

The most frequent use of the features list is through the reader macro sequences #+ sym and #- sym. This functionality is more fully described elsewhere, but simply put, the form after a #+ sym is invisible to READ unless (STATUS FEATURE sym) is true in the readtime environment. Similarly, #- sym is visible only in environments where (STATUS NOFEATURE sym) is true. For example, the expression

(ABC #+ITS DEF #-ITS GHI #+LISPM JKL)

is read by a Lisp reader running on ITS as (ABC DEF). In a Maclisp under some other operating system, (ABC GHI) would be the result of READ on the above text. And on a Lisp Machine, (ABC GHI JKL) would be seen by READ . Use of the #+ and #- readtime conditionalization is, however, not recommended for novices.



Returns T if sym is on the features list, else NIL . The sym is not evaluated.

Synonym:

(AND  (MEMQ  'sym (STATUS  FEATURES )) T )


Adds sym to the features list. The sym is not evaluated.


NOFEATURE Status Option (STATUS NOFEATURE sym)

Returns T if sym is not on the features list, else NIL . The sym is not evaluated.

Synonym:

(NOT  (STATUS  FEATURE  sym))


Removes sym from the features list. The sym is not evaluated.

Job and System Flags


LISPVERSION Status Option (STATUS LISPVERSION)

Returns the version number of this Maclisp as an atomic symbol.


SITE Status Option (STATUS SITE)

[PDP-10 Only] Returns a site name such as AI , ML , MC , CMU, SAIL, etc., or the kind of operating system if Lisp does not know the site name (i.e., TOPS-20, TENEX, or TOPS-10).

System maintainers: To get it to return the name of a site rather than just the site type, try creating a file LISP:SITE .TXT whose only contents is the string which is the printname of the symbol (STATUS SITE ) should return.


FILESYSTEM-TYPE Status Option (STATUS FILESYSTEM-TYPE)

[PDP-10 Only] Returns one of ITS , DEC20, OR DEC10 .


OPSYSTEM-TYPE Status Option (STATUS OPSYSTEM-TYPE)

[PDP-10 Only] Returns one of ITS , TOPS-20, TENEX, TOPS-10, CMU, or SAIL.



[Multics Only] Returns the n+1th argument of the lisp command, as an interned atomic symbol. NIL is returned if n is more than the number of arguments on the lisp command.



In the PDP-10 implementation, returns the “job command line” as a list of characters (see EXPLODEC ).

In Multics, jcl is more structured. The first “argument” to the Multics lisp command, if given, is used to designate a saved environment to start Lisp with. The second “argument,” if present, is returned (in EXPLODEC 'd format) by (STATUS JCL ). If no second argument was given, (STATUS JCL ) returns NIL .


XJNAME Status Option (STATUS XJNAME)

[PDP-10 Only] Obsolete. Replaced by (STATUS SUBSYSTEM ).


SUBSYSTEM Status Option (STATUS SUBSYSTEM)

[PDP-10 Only] Returns the true name this job (ITS ) or fork (Tops-20) wanted to run under. For example, on ITS , if multiple LISP jobs are started, they are called LISP0, LISP1, etc. (STATUS JNAME ) will get the names with the digits, but (STATUS SUBSYSTEM ) should always return just LISP for this case.

Eventually this will be made meaningful on TOPS-10 and multics implementations. The intended interpretation is “the generic name of this program.”


JNAME Status Option (STATUS JNAME)

[PDP-10 Only] This returns “the unique identifier of this job within the time-sharing system.” For example, on systems where the first of many Lisp forks for a user is LISP, the second is LISP0, etc., (STATUS JNAME ) will return values like LISP0. See also (STATUS SUBSYSTEM ).

On Tops-10, returns a job identifier of form nnnLSP, where nnn is a TOPS-10 job number.


JNUMBER Status Option (STATUS JNUMBER)

[PDP-10 Only] Returns the job's job number.


HACTRN Status Option (STATUS HACTRN)

[ITS Only] Returns information about the superior job. The following return values are defined:

LISP A Lisp superior.
DDT A DDT superior.
T Superior job unknown.
NIL No superior job.

This information is determined from information in the ITS job's .OPTION user variable.


UNAME Status Option (STATUS UNAME)

Returns an atomic symbol whose pname is the current user's name or ppn. In the Multics implementation this is in the format User.Project; the dot will be slashified if print is used to display this.


USERID Status Option (STATUS USERID)

[PDP-10 Only] Returns the user's real user name. On ITS , multiple logins of a user JDOE will get names like JDOE0 and JDOE1 assigned for that login session. (STATUS USERID ) will always return the real name, JDOE in this case. To get names like JDOE0, you want (STATUS UNAME ).


XUNAME Status Option (STATUS XUNAME)

[PDP-10 Only] Archaic. Use (STATUS USERID ).


UDIR Status Option (STATUS UDIR)

Returns the name of the file directory the user was connected to at the time the Lisp was started.


HOMEDIR Status Option (STATUS HOMEDIR)

[PDP-10 Only] Returns the user's home directory as an interned symbol.


HSNAME Status Option (STATUS HSNAME [uname] [sitename])

[PDP-10 Only] For non-ITS sites, this is like (STATUS HOMEDIR ). The arguments uname and sitename are only meaningful on ITS sites. Elsewhere they are likely to be ignored or an error. On ITS , however, they may find the home directory of user on a given ITS site. The value of uname defaults to the Lisp user's name, and sitename defaults to the current site.

Time


RUNTIME Function (RUNTIME )

Returns the number of microseconds of cpu time used so far by the process in which LISP is running. The difference between two values of (RUNTIME ) indicates the amount of computation that was done between the two calls to runtime.


TIME Function (TIME )

Returns the time that the system has been up as a flonum in seconds.



Returns the day of the week as an interned symbol in uppercase. For example, on Monday, (STATUS DOW ) returns the symbol MONDAY.


DATE Status Option (STATUS DATE)

Returns the current date as a 3-list of fixnums, representing the date as (year month date), where year is based on 1900 and where month and date are based on 1. So July 4, 1976 would be (76. 7. 4.).


DAYTIME Status Option (STATUS DAYTIME)

Returns a 3-list of fixnums representing the current time of day as 24-hour clock time in the form of a list, (hour minute second), where all elements are based on 0. So the time 4:15:37pm would be given by (16. 15. 37.).



Archaic. The same as (TIME ), the number of seconds the system has been up.



Archaic. The same as (RUNTIME ), the number of microseconds of cpu time that has been used.

Dumping Environments


SUSPEND Function (SUSPEND [data] [file])

SUSPEND is used to save an entire loaded environment as an executable image for later invocation. This is how subsystems built on top of Lisp are created. To use SUSPEND , you must first load your system, then close any files you have opened except TYI and TYO . Then call SUSPEND . On the next page is a sample of an init file to dump a system.

The optional arguments to SUSPEND have meaning only on ITS . The data argument may be a string to VALRET after doing the argument, or bits to use in a .BREAK 16,, or NIL meaning to not suspend at all (only useful when file is also specified). If file is given, the current environment is dumped as an executable file (a TS file). If file is not specified, the user is expected to use DDT to dump the file. Also, if the filename is specified and the value of (STATUS FLUSH ) is not NIL , then the shared parts of the Lisp will not be saved.

On non-ITS sites, just call (SUSPEND ) with no arguments and save according to the site-specific saving protocol. For example, on Tops-20...

@LISP.EXE
LISP 2129
Alloc? N
* 
(load  "MYSYS")
T 
(suspend):$Job Suspended$
@SAVE (on  file) MYSYS.EXE
 MYSYS.EXE.1 Saved	
@RESET MYSYS
@

A suspended Lisp can be continued on ITS (with $P or :CONTINUE). On non-ITS sites, a suspended Lisp must be restarted (e.g., by START from the Tops-20 Exec).

Alternatively, after having saved the Lisp to a file (either by the file argument to SUSPEND or by some Exec or DDT save command), it is appropriate to kill the Lisp. This can be done all at once on ITS by something like:

(SUSPEND  ":KILL " '((DSK MYDIR) TS MYSYS))
 
;;; -*- LISP -*-
;;; Sample init file for dumping out an imaginary program 
;;; called MYSYS.
(COMMENT  LIST  100000 SYMBOL  20000 FIXNUM  10000) ;octal
(PROGN  ;; Magic to close this init file
 (CLOSE  (PROG1  INFILE  (INPUSH  -1)))
 ;; Load compiled system
 (LOAD  '((MYDIR) MYSYS FASL))
 ;; Personalized options to aid debugging
 (SETQ  BASE  10. IBASE  10. *NOPOINT  ())
 (DEFPROP  DEBUG ((LIBLSP) DEBUG FASL) AUTOLOAD )
 ;; Tell user he's dumping our system
 (FORMAT  T  "~&Dumping: MYSYS~@[.~A~], A System of Mine~%"
 (GET  'MYSYS 'VERSION ))
 ;; Set up runtime  environment features
 (SSTATUS  TOPLEVEL  '(MY-TOPLEVEL)) ;Toplevel loop
 (SSTATUS  FEATURE  NOLDMSG ) ;Suppress ";Loading ..." messages
 (SETQ  GC-OVERFLOW  '(LAMBDA  (X) T )) ;Suppress GC-OVERFLOW  breaks
 ;; Clean garbage made while dumping
 (GC )
 ;; On ITS , let this dump share pages with dump it's built from
 (SSTATUS  FLUSH  T )
 ;; Do the dumping
 (COND  ((STATUS  FEATURE  ITS )
 (SUSPEND  ":KILL " '((DSK MYDIR) TS MYSYS)))
 (T 
 (SUSPEND )))
 ;; *** Anything after here runs each time the MYSYS program starts. ***
 ;; My handling of fix files, init files, etc.
 (MY-STARTUP)
 'READY)

Operating System Interface


SYSCALL Function (SYSCALL n callname arg1 arg2 ...)

[ITS Only] This does system calls. n should be the number of values that will be returned. they will be returned as a list, unless an error occurs, in which case a numeric code describing the error will be returned.


VALRET Function (VALRET [sym])

(VALRET ) is supposed to be like the now-obsolete (IOC Z); that is, it does a .LOGOUT if LISP is a top level procedure, and otherwise valrets ":VK " to DDT.

*** Warning: There is a bad bug wherein (VALRET ) will kill your Lisp rather than returning harmlessly, making it work more like (QUIT ). Hence, this form should probably be avoided.

If an argument is provided but is not a symbol, it will be converted to a symbol.

If the string of characters making up sym is one of "$^X.", ":KILL ", or ":KILL^M" (the letters of KILL must be capitalized) then valret performs a "silent kill" by executing a .BREAK 16,20000. This may also allow programs that VALRET these forms to be transported to non-ITS sites and still work, though in practice it's not wise to depend on such a feature.

If the sym isn't one of those special configurations, it is passed to the superior (usually DDT) on ITS or placed in the rescan buffer on Tops-20. The superior job (ITS ) or fork (Tops-20) will then usually execute the commands it has been passed.

Here are some examples from the ITS implementation:

(valret ':PROCED/ :DISOWN/ ) ; procedes and disowns the LISP.
(valret '/ :KILL/ :TECO/^M) ; kills the LISP and starts up a TECO.

Low-Level Machine Addressing


GETDDTSYM Function (GETDDTSYM sym)

[PDP-10 Only] Returns the machine location represented by the symbolic name which is the argument. This works only if symbols have been loaded for the job. If symbols are not loaded, NIL is returned.


PUTDDTSYM Function (PUTDDTSYM sym i)

[PDP-10 Only] Assigns sym as the DDT symbolic name of location i.


LH/| Function (LH/| n space)

[PDP-10 Only] Supposedly an ITS-only feature. Allocates a piece of memory of datatype space, n words big (actually rounds up to enough words to fill a page). The returned value is a fixnum which is the address of the first word of the chunk of memory or 0 if the memory could not be gotten. GC will mark through the space if it is of type LIST , BIGNUM , or HUNK . The data in the memory itself is not marked or swept. No guarantees are made if space is SYMBOL or ARRAY --- all other types should work.

In spite of its return value convention, do not do (DECLARE (FIXNUM (LH/|))); this is not a fixnum function.


EXAMINE Function (EXAMINE address)

[PDP-10 Only] Returns a fixnum representing the raw contents of address which is given as its argument. (See also LH/| and DEPOSIT .)


DEPOSIT Function (DEPOSIT address value)

[PDP-10 Only] Both arguments must be fixnums. Deposits in a given machine address a fixnum value. A good way to get around using Lisp-pointers for certain specialized applications but highly machine-dependent and not recommended for general use. (See also LH/| and EXAMINE .)

High-Level Machine Addressing

The functions described on this page are intended for very special-puprose applications only, and are not useful in day-to-day programming. They are mostly useful to writers of system utilities who must do system calls, interface to LAP code, etc.


VALUE-CELL-LOCATION Function (VALUE-CELL-LOCATION sym)

[PDP-10 Only] Returns the address of symbol's value cell. The value cell itself is a cons whose cdr points at the value. Ages ago, when the value cell lived on the property list of a symbol, (GET sym 'VALUE ) used to obtain the value cell. In modern Maclisp, (MAKNUM (VALUE-CELL-LOCATION sym)) does that.


MAKNUM Function (MAKNUM q)

A dereferencing operator. Returns the machine address of q. Reasonably machine-dependent. In worlds with relocating garbage-collectors, it may be prone to timing-errors and hence useless.

*** Actually, this does something reasonably useful on Multics, but it doesn't return a machine address. ***


MUNKAM Function (MUNKAM fixnum)

This will return a pointer to the object at machine location specified by its argument. It is not recommended as a way of creating objects, but can be used effectively in undoing a dereference of an object (as done by MAKNUM ).

Note: MUNKAM is MAKNUM spelled backwards.

;; Example of (MUNKAM  (MAKNUM  x)) => x
(munkam  (maknum  '(foo bar)))
=> (FOO BAR)
;; Here's an example of accessing a symbol's value cell.
(setq  foo 3)
=> 3
;; Get our hands on  FOO's value cell.
(munkam  (value-cell-location  'foo))
=> (NIL  . 3)
;; Modify that cell
(rplacd  *  4)
=> (NIL  . 4)
;; Inspect that FOO was really changed.
foo
=> 4
;; Playing with the MAKNUMs of things if you have dropped the
;; original pointer may cause you grief because they can be
;; garbage-collected... consider the following:
(munkam  (prog1  (maknum  '(a . b)) (gc )))
=> (A B) ; the variable -  (minus sign) had a pointer to the cons  in GC 
(munkam  (prog1  (maknum  (cons  'a 'b)) (gc )))
=> (NIL  NIL  NIL  NIL  ... ; the free list! nothing pointed to (A . B) in GC 
(munkam  (prog1  (maknum  12346.) (gc )))
=> 12346. ; the variable -  (minus sign) had a pointer to the number  in GC 
(munkam  (prog1  (maknum  (1+  12345.)) (gc )))
=> 241077.	; the fixnum  free list! nothing pointed to 12346. during GC !

Hashing


SXHASH Function (SXHASH q)

SXHASH computes a hash code of an S-expression, and returns it as a (possibly negative) fixnum. A property of SXHASH is that

(EQUAL  x y) implies (= (SXHASH  x) (SXHASH  y)).

The number returned by SXHASH is some possibly large number in the range allowed by fixnums. It is guaranteed that:

1) SXHASH for an atomic symbol will always be positive.
2) SXHASH of any particular expression will be constant in
a particular implementation for all time.
3) Two different implementations may hash the same
expression into different values.
4) SXHASH of any object of type RANDOM will be zero.
5) (= (SXHASH i) i), for any fixnum i.


[PDP-10 Only] Returns info about which of two SXHASH algorithms is in use. If T , the default, then the old SXHASH algorithm is in effect. If NIL , the new SXHASH algorithm is in effect. This algorithm is incompatible with the old one, so might break some programs and hence is not the default. It tries to fix the bug of SXHASH working too symmetrically on lists. The new SXHASH algorithm defines (SXHASH x) to mean:

(+  (ROT  (SXHASH  (CAR  x)) 11.) (ROT  (SXHASH  (CDR  x)) 7.))


[PDP-10 Only] Sets the state of the SXHASH switch to flag. See documentation on (STATUS SXHASH ).

Allocation


ALLOC Function (ALLOC l)

The ALLOC function is used to examine and set parameters of various spaces having to do with storage management. To set parameters, the argument to alloc should be a list containing an even number of elements. The first element of a pair is the name of a space, and the second is either a fixnum or a 3-list. A fixnum specifies the PDLSIZE (for a pdl space) or the GCSIZE (for other spaces). A 3-list cannot be used with pdl space. It specifies, from left to right, the GCSIZE , GCMAX , and GCMIN . NIL means "don't change this parameter." Otherwise a fixnum must be supplied, except in the third element (the GCMIN ), where a flonum is acceptable.

An example of this use of ALLOC , in the PDP-10 (BiBOP) implementation:

(ALLOC  '(LIST  (30000. 5000. 0.25)
 FIXNUM  (4000. 7000. NIL )
 REGPDL  2000.))

or, in the Multics implementation:

(alloc  '(list (30000. nil  0.3)
 markedpdl 5000.
 unmarkedpdl 5000.))

ALLOC may also be called with an argument of T , which causes it to return a list of all the spaces and their parameters. This list is in a form such that it could be given back to ALLOC at some later time to set the parameters back to what they are now.

Valid space names for the PDP-10 are LIST , FIXNUM , FLONUM , BIGNUM , SYMBOL , ARRAY , HUNK2 , HUNK4 , HUNK8 , HUNK16 , HUNK32 , HUNK64 , HUNK128 , HUNK256 , HUNK512 , REGPDL , FLPDL , FXPDL , and SPECPDL .

The REGPDL is the “regular pdl.” It holds control information, compiled local variables, and arguments. The garbage collector marks through the relevant parts of this pdl. Naming conventions are not uniform in Maclisp for this pdl; elsewhere (e.g., in STATUS ) this is called just PDL , not REGPDL .

The SPECPDL is the “special pdl.” It holds information about special variables which have been dynamically bound. Bindings are shallow, so the values on this pdl are the inactive values, not the active ones. Relevant parts of this pdl are marked through by the garbage collector.

The FLPDL , or “flonum pdl,” and the FXPDL , or “fixnum pdl,” contain 36-bit fixnum and flonum data which are temporaries being used by compiled code, number-declared compiled local variable storage, etc. These pdls are not marked through by the garbage collector.

The Garbage Collector


GC Function (GC)

Causes a garbage collection and returns NIL .


GCPROTECT Function (GCPROTECT obj switch)

[PDP-10 Only] If first arg is a symbol, merely sets the flag in the symbol-header which says “compiled code needs me”; such symbols will never be GC 'd. Otherwise, it does a hash-table look-up of the s-expresssion on an internal array (stored in the cell labelled “GCPSAR:”) just like INTERN ; so you get EQification for random list structure, which is what FASLOAD does in order to minimize duplication in "constant" structures. If second arg is "?", then it merely does a lookup, with no interning - sort of like INTERNDP. One other crinkle added to this function was for the benefit of the OWL system: if the value of the symbol GCPROTECT is not NIL , then this “interning” action is not done, but instead each structure (except symbols, of course) is freshly consed up.


GCTWA Special Form (GCTWA [flag])

GCTWA is used to control the garbage collection of “truly worthless atoms,” which are atomic symbols which have no value and no special properties, and which are not referenced by any list structure, other than the obarray (the current obarray if there is more than one).

(GCTWA ) causes truly worthless atoms to be removed on the next garbage collection.

The flag, if supplied, is not evaluated and must be one of T or NIL .

(GCTWA T ) causes truly worthless atoms to be removed on each garbage collection from now on.

(GCTWA NIL ) causes this continual removal of truly worthless atoms to be shut off, but it does not affect whether the next garbage collection removes such atoms.

Note: The “A” for “atom” in “GCTWA ”is really misleading, since GCTWA affects the behavior of the garbage collector with respect to only symbols and not with respect to other kinds of atoms (such as numbers, arrays, etc.). However, this should cause no problem since the garbage collector can tell what truly worthless numbers, etc. are without needing hints from a switch.

The meaning of the value returned by GCTWA is given by the following table (numbers shown are in octal):

0 no GC of truly worthless atoms will be done.
1 truly worthless atoms will be GC 'd on next GC only.
10 truly worthless atoms are GC 'd on all GC 's.
11 both

It is possible to test whether subsequent GC 's are going to collect truly worthless atoms by checking the value of of the variable GCTWA .


GCTWA Value NIL

[PDP-10 Only] Holds a value saying whether the default during GC 's is for “truly worthless atoms” are to be GC 'd (T means Yes, NIL means No). See documentation on the GCTWA function for more information.


SYSTEM Status Option (STATUS SYSTEM sym)

Returns a list of the system properties of the atomic symbol sym, which is evaluated. This list may contain SUBR , FSUBR , LSUBR , MACRO , or AUTOLOAD if sym denotes a function; VALUE if it is a variable in the initial system; and will always contain SYMBOL for initial symbols. Note that symbols defined only by out-of-core packages do not answer T to (STATUS SYSTEM sym) so this feature is of limited value. If it answers with something other than NIL , you can be sure the argument was an initial Lisp symbol, but if it returns NIL , you cannot be sure that it is not. Further, this STATUS option must cons the list of properties, so it's somewhat storage inefficient since generally all it gets used for is for boolean value in the first place.

On Multics, the list returned never contains any of the symbols SYMBOL , MACRO , or AUTOLOAD .

Examples:

(STATUS  SYSTEM  'CAR )	=>	(SUBR  VALUE  SYMBOL )
(STATUS  SYSTEM  'LAMBDA )	=>	(SYMBOL )
(STATUS  SYSTEM  'FRED)	=>	NIL 

SYSP Function (SYSP sym)

If sym, which must be a symbol, is the name of a system function (and has not been redefined), SYSP returns the type of function (SUBR , LSUBR , or FSUBR ). Otherwise, it returns NIL .

Examples:

(SYSP  'FOO)	=> NIL 
(SYSP  'CAR )	=> SUBR 
(SYSP  'COND )	=> FSUBR 
(SYSP  'LAMBDA )	=> NIL 

RECLAIM Function (RECLAIM obj flag)

[PDP-10 Only] Usually, just calling the garbage collector directly (see GC ) or waiting for it to run is the right way to deal with the recycling of storage. For those rare cases where this is not enough, RECLAIM is provided to allow an individual piece of storage to be returned without running the entire garbage collector mechanism.

This function reclaims list structure or numbers; i.e., returns them to the “free list.” The user is responsible for dropping all pointers to RECLAIM ed object; failure to do so will leave him with pointers into the free list. Pure cells, value cells, hunks, arrays, objects of type random, and pointers to stack-allocated objects are ignored by RECLAIM . Only heap-consed lists and numbers will be reclaimed.

If flag is NIL , only the top level of obj is reclaimed. If obj is a number, that number is reclaimed. If obj is a list, the top level of conses in that list are reclaimed.

If flag is T , all levels are reclaimed. If obj is a number, that number is reclaimed. If obj is a list, all levels of that list are reclaimed.

Given:

(setq  x1 '(a b c) x2 '(d e f) x3 '(g h i) x4 '(j k l) x5 '(m n o))
(setq  n1 5000. n2 5000. n3 5000.)
(setq  foo (list x1 x2 n1 (hunk  x3 n2) (list x4 n3)))

(RECLAIM X5 NIL ) would reclaim the three cells of X5.

(RECLAIM FOO NIL ) would reclaim the five toplevel cells of FOO, leaving X1, X2, N1, etc. intact.

(RECLAIM FOO T ) would reclaim all list cells in FOO except those in X3 because RECLAIM will not recurse into the hunk. The hunk itself will also not be reclaimed. The numbers held by N1 and N3 would also be reclaimed.

(RECLAIM N2 NIL ) and (RECLAIM N2 T ) would do the same thing; i.e., reclaim the number held by N3.

The behavior of RECLAIM with respect to hunks is not affected by the value of HUNKP .


GC-DAEMON Value NIL

The value of the variable GC-DAEMON , if not NIL , should be a function of one argument to be called after each garbage collection.

*** What is the nature of the argument? ***



[PDP-10 Only] The value of the variable GC-OVERFLOW is a function of 1 argument to be run when a GC-OVERFLOW condition is signalled.

*** When are they signalled? What does it mean to handle this condition? What happens with return values? ***


GCPROTECT Value NIL

[PDP-10 Only] If the value of the symbol "GCPROTECT " is not NIL , then the "interning" action described in documentation for the GCPROTECT function is not done, but instead each structure (except symbols, of course) is freshly consed up.


^D (Uparrow D) Value NIL

If the value of the symbol ^D (Uparrow D, not Control-D) is not NIL , the garbage collector prints an informative message after each garbage collection.

Typing Control-D sets the variable ^D to T . By default, typing Control-C interactively to a Lisp sets this variable back to NIL , except on Tops-20 where the system definition of Control-C has precedence over the Lisp definition of Control-C, so there is no easy way to set this variable back to NIL other than (SETQ ^D NIL ).



Returns the number of microseconds spent garbage collecting.



Resets the gctime counter to n and returns the previous value of the GCTIME counter. See also (STATUS GCTIME ).


GCMAX Status Option (STATUS GCMAX space)

[PDP-10 Only] Returns the GCMAX parameter for a given space, which is evaluated. See ALLOC for more information about GCMAX .


GCMAX SStatus Option (SSTATUS GCMAX space i)

[PDP-10 Only] Sets the GCMAX parameter of a given space to a given fixnum value, i. Both space and i are evaluated.


GCMIN Status Option (STATUS GCMIN space)

[PDP-10 Only] Returns the GCMIN parameter for a given space, which is evaluated. See ALLOC for more information about GCMIN .


GCMIN SStatus Option (SSTATUS GCMIN space k)

[PDP-10 Only] Sets the GCMIN parameter of a given space to a given value, k, which must be a fixnum or flonum. Both space and i are evaluated.


GCSIZE Status Option (STATUS GCSIZE space)

[PDP-10 Only] Returns the GCSIZE parameter for a given space, which is evaluated. See ALLOC for more information about GCSIZE .


GCSIZE SStatus Option (SSTATUS GCSIZE space i)

[PDP-10 Only] Sets the GCSIZE parameter for a given space to a given fixnum value, i. Both space and i are evaluated.



[PDP-10 Only] Returns a list of four fixnums: the minimum number of dimensions an array may have, the maximum number of dimensions an array may have, the minimum axis length for an array, and the maximum axis length for an array. The list returned is freshly consed and may be destructively modified.


BPSH Status Option (STATUS BPSH)

[PDP-10 Only] *** Something about Binary Program Space High ? ***


BPSL Status Option (STATUS BPSL)

[PDP-10 Only] *** Something about Binary Program Space Low ? ***


MEMFREE Status Option (STATUS MEMFREE)

[PDP-10 Only] Returns the number of words of address space not yet allocated for any purpose.


PAGING Status Option (STATUS PAGING)

[Multics Only] Returns a list of the paging-device page faults and total page faults that have been incurred. The first element of this list may always be zero if there is no paging-device.



[PDP-10 Only] If T , Lisp will try to flush certain system pages from the current environment during a suspend expecting that it can find them in the SYS;TS LISP (ITS ) or LISP.EXE (Tops-20) it was loaded from. This flag seems to work only on ITS , but is harmless to set on Tops-20 and may someday work.



[PDP-10 Only] Sets the value of the FLUSH switch to T or NIL as given by flag.



[PDP-10 Only] LOSEF supposedly stands for “LAP Object Storage Efficiency Factor.” According to the implementors, this is the “wrong thing” and doesn't want to be documented at all. It has something to do with the size of the hash table used by LAP and/or FASLOAD in interning quoted constants at load time.



[PDP-10 Only] Sets (STATUS LOSEF ) to the given val.

Stack-Related Status Options



The maximum size to which a given pdl may grow before intervention is required. Used to detect infinite recursion.


PDLMAX SStatus Option (SSTATUS PDLMAX pdl value)

Sets PDLMAX for a given pdl to a given value.


PDLNAMES Status Option (STATUS PDLNAMES)

[PDP-10 Only] Returns a list of all the names of the pdls (machine stacks) used by Lisp.


PDLROOM Status Option (STATUS PDLROOM pdl)

[PDP-10 Only] The size beyond which the given pdl may not grow. This value is slightly larger than given by (STATUS PDLMAX ) to allow a little room for an error handler to run when a PDL-OVERFLOW occurs.


PDLSIZE Status Option (STATUS PDLSIZE pdl)

The number of words of valid data in the given pdl at the moment.



[PDP-10 Only] Returns the contents of the base of the Lisp fixnum stack pointer, FXP, as a fixnum. Note, this is not the current value of that stack pointer. It is what that pointer would be at Lisp toplevel.

Note: “FXPDL ” is pronounced like “fix-piddle.”



[PDP-10 Only] Returns the contents of the base of the Lisp flonum stack pointer, FLP, as a fixnum. Note, this is not the current value of that stack pointer. It is what that pointer would be at Lisp toplevel.

Note: “FLPDL ” is pronounced like “flow-piddle.”



[PDP-10 Only] Returns the contents of the base of the Lisp control stack pointer, P, as a fixnum. (This is the same pdl as the one ALLOC calls REGPDL ). Note, this is not the current value of that stack pointer. It is what that pointer would be at Lisp toplevel.

Note: “PDL ” is pronounced like “piddle.”


SPDL Status Option (STATUS SPDL)

[PDP-10 Only] Returns the contents of the base of the Lisp special stack pointer, SP, as a fixnum. Note, this is not the current value of that stack pointer. It is what that pointer would be at Lisp toplevel.

Note: “SPDL ” is pronounced like “spec-piddle.”

Storage Spaces


SEGLOG Status Option (STATUS SEGLOG)

[PDP-10 Only] Returns the log base 2 of segment, i.e. one unit of space allocation. On TOPS-10 systems this is one page (512 words), so the status call returns 9.


PURSIZE Status Option (STATUS PURSIZE spacename)

[PDP-10 Only] *** What does this do? ***


PURSPCNAMES Status Option (STATUS PURSPCNAMES)

[PDP-10 Only] Returns the names of all pure spaces. Presently this is (LIST FIXNUM FLONUM BIGNUM ) but in case this ever changes, This STATUS call is the right way to find them all. See also (STATUS SPCNAMES ).


SPCNAMES Status Option (STATUS SPCNAMES)

Returns the names of non-pure spaces.


SPCSIZE Status Option (STATUS SPCSIZE spacename)

Returns the size (in words) physically allocated to a given space, spacename. This is frequently less than the amount which has been specified as allocatable with ALLOC .

Binary Program Space

There are a number of features which control how binary code and constants are purified when a compiled program is loaded into LISP.


BPORG Value unspecified

[PDP-10 Only] The value of this variable should always be a fixnum, whose value is the address of the first unused word of “binary program space,” where SUBR code is stored. This value generally should only be examined by the user, not altered. BPORG is updated whenever binary code is loaded by LAP or FASLOAD .


BPEND Value unspecified

[PDP-10 Only] This variable should also always have a fixnum as its value; this indicates the last available word of binary program space. Below this address, arrays are allocated. This is updated by many internal LISP routines, such as the garbage collector, the array allocator, and LAP and FASLOAD .


PAGEBPORG Function (PAGEBPORG)

[PDP-10 Only] Calling this function causes “binary program space” (as marked by the BPORG variable) to be rounded up to a page boundary. It is necessary for this to be done if binary program space is to be purified; if it is not done, then future FASLOADing will attempt to write on a read-only page.


GETSP Function (GETSP n [flag])

[PDP-10 Only] Ensures that (- BPEND BPORG ) is at least n, allocating more memory if necessary.

The flag defaults to the value of the variable PURE . If flag is not NIL , then the memory added is marked as being potentially purifiable by PURIFY . This is generally used by clever subsystem loaders to expand binary program space quickly so that FASLOAD will not require several garbage collections to do the same thing. It can also be used by programs which create and destroy many arrays (see NORET ).


NORET Function (NORET val)

Sets the NORET flag.

On Multics, this flag is not used for anything useful.


NORET Value NIL

[PDP-10 Only] Holds the current value of the NORET flag. After a GC has been run, one of the last things done is to check how big the difference between BPEND and BPORG is; if it is more than several ITS pages, then an array-relocation phase is done in order to move downwards. Originally, in the pre-paging ITS days, this relocation actually returned core and swapping pages to the system, but nowadays, it merely prevents your LISP address space from being eaten up by dead space between the last loaded SUBR and beginning of array storage. One might set NORET to T , thereby preventing this action, if he wants to grab a big chunk of binary program space for his own use. This may be useful in conjunction with GETSP .

Pure cells, pure pages, ...


Purification Concept Read-Only Data

Purification is the term used to describe making something read-only. With respect to Lisp, this has two advantages:

A data structure which is pure does not get swept by the garbage collector. If (as is typically the case) pure structure does not reference impure structure, then the garbage collector does not even have to mark through it, thus saving mark time.

Pure structure can be shared (i.e., utilize the same virtual memory) between restored dumped Lisps. This results in less paging overhead for the operating system, and generally better performance.

On Multics, only code areas are pure; data areas are not, so this section isn't particularly relevant to Multics.


*PURE Value NIL

[PDP-10 Only] When you load FASL files, if *PURE is not NIL , then fasload will PURCOPY the quoted constants. Also PUTPROP will PURCOPY any property it sets up which has one of the indicators in the list held by the variable PUTPROP .

If this variable is not NIL , then Lisp will set things up so that constant datastructure referenced from loaded compiled code, the print-names of symbols which get interned, and things PUTPROP ed under any of the properties on the list which is the value of PUTPROP (described more below), can be purified. Normally, this variable is NIL ; if one is making a sharable dumped system, however, it should be set to T before things get loaded, and then reset to NIL before the Lisp is suspended.

If *PURE is set to the symbol SYMBOL , then everything except symbols will be pure-consed. This was added for use in the Macsyma loader, and may not be generally useful.

In the SAIL implementation, the value of *PURE , if not NIL , should be (rather than just T ) an estimate of the total number of words of pure free storage needed, including all that loaded by previous files and all that included in the initial lisp system. This causes FASLOAD to preallocate enough additional room in the high segment to accomodate the estimated total amount of pure storage. (The preallocation is necessary because it isn't possible to allocate list storage in the high segment once the loading of code has begun.) Making the estimate in *PURE too big merely wastes space in the high segment; making it too small causes PURCOPY to make its copies in the low segment when it runs out of room in the high segment. This whole feature only works if PURE is a negative fixnum.

It used to be the case that any call to COPYSYMBOL while *PURE was not NIL would return a purified symbol. As of May, 1978, this is no longer true. Now only symbols that are interned are automatically pure. This change in semantics seemed to result in a reduction in the size of COMPLR and Macsyma dumps.



[PDP-10 Only] The value of PUTPROP is a list of properties which should be purified. In fact, not only the objects on those properties, but the portion of the plist referencing the property name and the object will be purified. To do this, PUTPROP (etc.) violates its normal semantics somewhat; it does not necessarily put the new property at the front of the property list. Conceptually, it divides the plist into two “zones”; the impure zone, and the pure zone. The impure zone comes at the front, with the pure zone as some sublist of it, since pure data structures should not point to impure data structures (unless special gc protection measures are taken).

Note that because of the presence of two zones, PUTPROP (etc.) of something that is not already there may not add the property to the front of the property list. In particular, consider the following sequence:

(setplist  'foo nil ) ;for the sake of argument...
(putprop  'foo '(lambda  (x) (cdr  x)) 'expr)
(putprop  'foo (get 'car  'subr ) 'subr )

Normally, we would expect that FOO would behave like CAR after such a sequence because the SUBR property was more recent than the EXPR property. If *PURE is not NIL , however, FOO will behave instead like CDR because the SUBR property will be put after the EXPR property.


PURCOPY Function (PURCOPY obj)

This function makes and returns a copy of obj in pure storage. This is primarily of use in the creation of large sharable systems like Macsyma. In implementations other than PDP-10 implementations with pure spaces, PURCOPY simply returns its argument.


PURCOPY Value NIL

[PDP-10 Only] The value of the variable PURCOPY is a list of things which the PURCOPY function should not actually copy. For example, the class system (not defaultly part of Lisp) needs it to be true that class objects never move, so they can't be PURCOPY 'd.


PURIFY Function (PURIFY start end flag)

[PDP-10 Only] This function can be used to purify or depurify portions of the Lisp address space. The flag may be one of T , NIL , or BPORG . The start and end arguments should be fixnums.

If flag is NIL , the pages containing memory addresses start through end are made impure (writable). If flag is T , they are made pure (read-only).

If flag is BPORG , then the pages are made pure, but in addition some work is done to make sure that no UUO on those pages may ever be “clobbered” (see PURE and PURCLOBRL ). This option should always be used if the pages involved contain binary code loaded by LAP or FASLOAD .

If the first two arguments are zero, as in (PURIFY 0 0 'BPORG ), Lisp will purify those portions of its address space which have been “marked for purification” (see PURCOPY ), including all of binary program space. (A call to (PAGEBPORG ) needs to be done first).

PURIFY does nothing in the TOPS-10 implementation.


PURE Value 1

[PDP-10 Only] This variable should be made not NIL by the user before loading binary code which is to be made pure. It tells LAP and FASLOAD to be circumspect about any UUO's in the code, because pure UUO's cannot be clobbered to be PUSHJ's or JRST's. LAP solves this problem by clobbering the UUO immediately if the referenced function is already defined and is itself a subr rather than an expr; otherwise the UUO is made permanently unclobberable (i.e. CALL is converted to CALLF, etc.).

FASLOAD is somewhat more clever: it, too, tries to clobber each UUO immediately, but if it can't it puts the address of the UUO on a list called PURCLOBRL , which is checked at the end of each call to FASLOAD , and each UUO on the list is clobbered at that time, if the appropriate function had been loaded by that call to FASLOAD . If the function never does get defined, then PURIFY will also check PURCLOBRL and convert each UUO to its permanently unclobberable form.

If pure has a fixnum as its value, then FASLOAD (but not LAP ) behaves somewhat differently. PURE should be the desired size in words of the “uuolinks area”; this is rounded up to a whole number of pages. (If PURE is between 1 and 8, it is the number of pages rather than the number of words.) Let the number of pages be n. First FASLOAD calls PAGEBPORG , and then reserves 2n pages of binary program space, unless a previous call to fasload has already reserved them (i.e. they are reserved only once). Thus FASLOAD has two sets of n pages to work with; we shall call the first set “area 1” and the second set “area 2.” Now whenever FASLOAD has to load a clobberable UUO, it does not place it in the code being loaded, but rather hashes it and places it in area 1 if it was not there already; a copy is placed in the same relative position in area 2. Then an XCT instruction pointing to the UUO in area 1 is placed in the binary code. When all loading has been done, area 2 may be purified, but area 1 may not.

Now when running the code, the UUO's pointed to by the XCT's may be clobbered (the PDP-10 LISP UUO handler is clever about XCT), provided, of course, that the value of NOUUO is NIL , and the code will run faster the second time around because the XCT's will point to PUSHJ's. However, if (SSTATUS UUOLINKS ) is called, then area 2 is copied back into area 1, effectively unclobbering all the UUO's. This allows the called functions to be traced again, for example, or redefined as expr code. Naturally, an area large enough to contain all the UUO's should be reserved; (STATUS UUOLINKS ) yields information relevant to this. As a rule of thumb, the area should be 20% larger than the number of functions called by the loaded code (including LISP functions such as EQUAL ). For the DEC-10 version, PURE may be set to a negative value. The magnitude is used as above, while the sign controls which segment to load into (positive means low segments, negative means high segment). A negative value also causes uuolinks area 1 to go in the low segment, and area 2 in the high segment. For compatibility, a negative value means the same as a positive value to the ITS implementation.


PURCLOBRL Value NIL

[PDP-10 Only] Used by FASLOAD to keep track of UUOs which are potentially but not immediately clobberable.

See also: PURE

Wholines



[ITS Only] Returns the current GCWHO state as a fixnum.



[ITS Only] Sets the status of the GCWHO to the fixnum i, where the meaning of the fixnum is bit-coded:

1-bit When GC in progress, show “GC :reason” in wholine.
2-bit After a GC , clobber WHO2 word with GC runtime info.

Specifically, bit 2 turned on means that the left half of the WHO2 word gets the percentage of the run time which has been spent in GC , and the right half gets the GC run time in 40ths of a second. If the first two arguments to (SSTATUS WHO1 ...) are #o52 and '%, then these statistics will be printed in the form “NNN% HH:MM:DD.T ”, just like the standard system runtime percentage and value. In this way one can continuously monitor GC run time statistics. The 1 and 2 bits may be used together (i.e., 3) or independently. Note that while using the 2 bit the WHO3 variable is still left over for use by the user. Thus one might say:

(SSTATUS  WHO1  52 '% 166 0)
(SSTATUS  GCWHO  3)
(SSTATUS  WHO3  'QUUX)

and one would normally see “43% 00:15:07.8 QUUX,” but during a GC one would see “GC :FIXNUM ” or whatever.

A note for those who use suspend: If the suspended job is dumped out and later reloaded, the runtime (maintained by the time-sharing system) will have been reset, but not the GCTIME , which is maintained by Lisp. Therefore a routine which does a suspend should perform (SSTATUS GCTIME 0) on return from the SUSPEND in order to make the who-line and other gc statistics accurate.

The “.WHOn” user variables cause information to be displayed in the terminal's who-line. The meaning of i1, i2, i3, AND i4 is as follows:

VAR BITS MEANING
i1 200 If 1, suppress entire who-line.
100 Suppress space between halves of .WHO2
70 Mode for printing left half of .WHO2
0 Do not print
1 Date in packed form
--- bits 774000 year mod 100
--- bits 3600 month (1= January)
--- bits 174 day of month
2 Time in 40ths of a second, as HH:MM:SS.T
3 Time in half-seconds, as HH:MM:SS
4 octal halfword
5 Decimal halfword (no "." supplied)
6 Three sixbit characters
7 unused
7 mode for right half of .WHO2
i2 177 If non-zero, print between halves of
.WHO2 as an ASCII character.
200 If 1, print char twice
i3 200 If 1, suppress space between .WHO2
printout and .WHO3 printout
Otherwise like i1, but for .WHO3 .
i4 Like i2, but for .WHO3 .

That is, if the who-line is printed at all, what appears at the end is the characters:

IIIIXX-JJJJ= KKKKYY+LLLL

where

IIII is .WHO2 's left half, in i1's 70 bits' format.
JJJJ right half of .WHO2 , in i1's 7 bits' format.
KKKK left half of .WHO3 , in i3's 70 bits' format.
LLLL right half of .WHO3 , in i3's 7bits' format.
XX 0-2 chars, specified by i2.
YY 0-2 chars, specified by i4.
- Space, unless i1's 100 bit is 1.
= Space, unless i3's 200 bit is 1.
+ Space, unless i3's 100 bit is 1.
(SSTATUS  WHO1  #o166 0 #o144 '/!)
(SSTATUS  WHO2  'FOOBAR)
(SSTATUS  WHO3  (+  (LSH  #o1234 #o22) #o3456))
;; Mode line displays "FOOBAR 1234!5678"


[ITS Only] Reads the ITS user's .WHO1 variable, returning a list of the 4 relevant fixnums.


WHO1 SStatus Option (SSTATUS WHO1 i1 i2 i3 i4)

[ITS Only] Sets the .WHO1 user variable to

<.BYTE 8 ? i1 ? i2 ? i3 ? i4>

in midas terminology. i1 AND i3 must be fixnums; i2 AND i4 must be fixnums with ASCII values, or character objects.



[ITS Only] Reads the ITS user's .WHO2 variable as a fixnum.



[ITS Only] Sets the ITS user's “.WHO2 ” word. The argument q may be a fixnum or a symbol. If a symbol, the first 6 characters of the symbol are translated into sixbit and that value is used instead.



[ITS Only] Reads the ITS user's .WHO3 variable as a fixnum.



[ITS Only] Sets the ITS user's “.WHO2 ” word. The argument q may be a fixnum or a symbol. If a symbol, the first 6 characters of the symbol are translated into sixbit and that value is used instead.



The Revised Maclisp Manual (Sunday Morning Edition)
Published Sunday, December 16, 2007 06:17am EST, and updated Sunday, July 6, 2008.

AltStyle によって変換されたページ (->オリジナル) /