The Revised Maclisp ManualThe PitmanualPage A-24
Published by HyperMeta Inc.
 
Prev | Index | Next
[Blue Marble]
Climate Change
Is cap and trade really sufficient?


System Programming

TTY-Related Interrupts


TTY InterruptsConceptControl 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.


TTYINTSStatus 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).


TTYINTStatus 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)ValueNIL

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-MESSAGEValueNIL

[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.


CLIStatus Option(STATUS CLI)

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


CLISStatus Option(SSTATUS CLI flag)

[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-DEATHValueNIL

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)))))

ITSStatus Option(STATUS ITS)

[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-RETURNValueNIL

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

Alarm Clocks


ALARMCLOCKFunction(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).


ALARMCLOCKValueNIL

[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.


SLEEPFunction(SLEEP k)

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

Enabling/Disabling Interrupts


NOINTERRUPTFunction(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.


NOINTERRUPTSStatus Option(STATUS NOINTERRUPTS)

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.


NOINTERRUPTSSStatus Option(SSTATUS NOINTERRUPTS flag)

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


WITHOUT-INTERRUPTSSpecial 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.


STATUSSpecial 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.


STATUSStatus 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.


SSTATUSSpecial 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.


SSTATUSStatus 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''


FEATURESStatus 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.


FEATUREStatus Option(STATUS FEATURE sym)

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

Synonym:

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

FEATURESStatus Option(SSTATUS FEATURE sym)

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


NOFEATUREStatus 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))

NOFEATURESStatus Option(SSTATUS NOFEATURE sym)

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

Job and System Flags


LISPVERSIONStatus Option(STATUS LISPVERSION)

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


SITEStatus 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-TYPEStatus Option(STATUS FILESYSTEM-TYPE)

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


OPSYSTEM-TYPEStatus Option(STATUS OPSYSTEM-TYPE)

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


ARGStatus Option(STATUS ARG n)

[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.


JCLStatus Option(STATUS JCL)

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.


XJNAMEStatus Option(STATUS XJNAME)

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


SUBSYSTEMStatus 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.”


JNAMEStatus 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.


JNUMBERStatus Option(STATUS JNUMBER)

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


HACTRNStatus 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.


UNAMEStatus 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.


USERIDStatus 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).


XUNAMEStatus Option(STATUS XUNAME)

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


UDIRStatus Option(STATUS UDIR)

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


HOMEDIRStatus Option(STATUS HOMEDIR)

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


HSNAMEStatus 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


RUNTIMEFunction(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.


TIMEFunction(TIME)

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


DOWStatus Option(STATUS DOW)

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


DATEStatus 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.).


DAYTIMEStatus 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.).


TIMEStatus Option(STATUS TIME)

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


RUNTIMEStatus Option(STATUS RUNTIME)

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

Dumping Environments


SUSPENDFunction(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


SYSCALLFunction(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.


VALRETFunction(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


GETDDTSYMFunction(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.


PUTDDTSYMFunction(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.


EXAMINEFunction(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.)


DEPOSITFunction(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-LOCATIONFunction(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.


MAKNUMFunction(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. ***


MUNKAMFunction(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


SXHASHFunction(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

SXHASHStatus Option(STATUS SXHASH)

[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.))

SXHASHSStatus Option(SSTATUS SXHASH flag)

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

Allocation


ALLOCFunction(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


GCFunction(GC)

Causes a garbage collection and returns NIL.


GCPROTECTFunction(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.


GCTWASpecial 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):

no GC of truly worthless atoms will be done. 
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.


GCTWAValueNIL

[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.


SYSTEMStatus 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

SYSPFunction(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

RECLAIMFunction(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 RECLAIMed 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-DAEMONValueNIL

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? ***


GC-OVERFLOWValue+INTERNAL-GCO-BREAK

[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? ***


GCPROTECTValueNIL

[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)ValueNIL

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).


GCTIMEStatus Option(STATUS GCTIME)

Returns the number of microseconds spent garbage collecting.


GCTIMESStatus Option(SSTATUS GCTIME n)

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


GCMAXStatus 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.


GCMAXSStatus 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.


GCMINStatus 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.


GCMINSStatus 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.


GCSIZEStatus 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.


GCSIZESStatus 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.


ARRAYStatus Option(STATUS ARRAY)

[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.


BPSHStatus Option(STATUS BPSH)

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


BPSLStatus Option(STATUS BPSL)

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


MEMFREEStatus Option(STATUS MEMFREE)

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


PAGINGStatus 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.


FLUSHStatus Option(STATUS FLUSH)

[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.


FLUSHSStatus Option(SSTATUS FLUSH flag)

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


LOSEFStatus Option(STATUS LOSEF)

[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.


LOSEFSStatus Option(SSTATUS LOSEF val)

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

Stack-Related Status Options


PDLMAXStatus Option(STATUS PDLMAX pdl)

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


PDLMAXSStatus Option(SSTATUS PDLMAX pdl value)

Sets PDLMAX for a given pdl to a given value.


PDLNAMESStatus Option(STATUS PDLNAMES)

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


PDLROOMStatus 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.


PDLSIZEStatus Option(STATUS PDLSIZE pdl)

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


FXPDLStatus Option(STATUS FXPDL)

[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.”


FLPDLStatus Option(STATUS FLPDL)

[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.”


PDLStatus Option(STATUS PDL)

[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.”


SPDLStatus 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


SEGLOGStatus 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.


PURSIZEStatus Option(STATUS PURSIZE spacename)

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


PURSPCNAMESStatus 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).


SPCNAMESStatus Option(STATUS SPCNAMES)

Returns the names of non-pure spaces.


SPCSIZEStatus 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.


BPORGValueunspecified

[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.


BPENDValueunspecified

[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.


PAGEBPORGFunction(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.


GETSPFunction(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).


NORETFunction(NORET val)

Sets the NORET flag.

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


NORETValueNIL

[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, ...


PurificationConceptRead-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.


*PUREValueNIL

[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 PUTPROPed 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.


PUTPROPValue(+INTERNAL-STRING-MARKER SUBR FSUBR LSUBR)

[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.


PURCOPYFunction(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.


PURCOPYValueNIL

[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.


PURIFYFunction(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.


PUREValue1

[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.


PURCLOBRLValueNIL

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

See also: PURE

Wholines


GCWHOStatus Option(STATUS GCWHO)

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


GCWHOSStatus Option(SSTATUS GCWHO i)

[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 
 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"

WHO1Status Option(STATUS WHO1)

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


WHO1SStatus 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.


WHO2Status Option(STATUS WHO2)

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


WHO2SStatus Option(SSTATUS WHO2 q)

[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.


WHO3Status Option(STATUS WHO3)

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


WHO3SStatus Option(SSTATUS WHO3 q)

[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.


[Blue Marble]
Climate Change
Melting ice affects more than just coastal cities.

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