{Begin SubSec Interfork Communication in Interlisp-10} {Title Interfork Communication in Interlisp-10} {Text {index interfork communication} The functions described below permit two {index forks}forks (one or both of them Interlisp-10) to have a common area of address space for communication by providing a means of assigning a block of storage {it guaranteed not to move during garbage collections.} {FnDef {FnName GETBLK} {FnArgs N} {Text Creates a block {arg N} {it pages} in size (512 words per page). Value is the address of the first word in the block, which is a multiple of 512 since the block will always begin at a page boundary. If not enough pages are available, generates the error {lisp ILLEGAL OR IMPOSSIBLE BLOCK}.{index ILLEGAL OR IMPOSSIBLE BLOCK Error} }} {it Note: the block can be used for storing unboxed numbers {it ONLY}. } To store a number in the block, the following function could be defined: {lisp (SETBLOCK (LAMBDA (START N X) (CLOSER (IPLUS (LOC START) N) X]} Some boxing and unboxing can be avoided by making this function compile open via a substitution macro. {it Note: {index GETBLK FN}{fn GETBLK} should be used sparingly since several unmovable regions of memory can make it difficult or impossible for the garbage collector to find a contiguous region large enough for expanding array space. } {FnDef {FnName RELBLK} {FnArgs ADDRESS N} {Text releases a block of storage beginning at {arg ADDRESS} and extending for {arg N} pages. Causes an error {lisp ILLEGAL OR IMPOSSIBLE BLOCK}{index ILLEGAL OR IMPOSSIBLE BLOCK Error} if any of the range is not a block. Value is {arg ADDRESS}. }} }{End SubSec Interfork Communication in Interlisp-10} {Begin SubSec SUBSYS} {Title SUBSYS} {Text {note {fn SUBSYS} was written by J.W. Goodwin and modified by D. C. Lewis. It is Tenex/TOPS-20 dependent and may not be available in implementations of Interlisp other than Interlisp-10.} {index *BEGIN* SUBSYS FN} {index running other subsystems from within Interlisp} This section describes a function, {fn SUBSYS}, which permits the user to run a Tenex/TOPS-20 subsystem, such as SNDMSG, SRCCOM, TECO, or even another Interlisp, from inside of an Interlisp without destroying the latter. In particular, {lisp (SUBSYS 'EXEC)} will start up a lower exec, which will print the operating system herald, followed by {lisp @}. The user can then do anything at this exec level that he can at the top level, without affecting his superior Interlisp. For example, he can start another Interlisp, perform a {fn SYSIN}, run for a while, type a {index control-C}control-C returning him to the lower exec, RESET, do a SNDMSG, etc. The user exits from the lower exec via the command {index *PRIMARY* QUIT (TENEX Command)}QUIT,{foot POP on TOPS-20. }{comment endfootnote} which will return control to {fn SUBSYS} in the higher Interlisp. Thus with {fn SUBSYS}, the user need not perform a {fn SYSOUT} to save the state of his Interlisp in order to use a Tenex/TOPS-20 capability which would otherwise clobber the core image. Similarly, {fn SUBSYS} provides a way of checking out a {fn SYSOUT} file in a fresh Interlisp without having to commandeer another terminal or detach a job. While {fn SUBSYS} can be used to run any subsystem directly, without going through an intervening exec, this procedure is not recommended. The problem is that {index control-C}control-C always returns control to the next highest {it EXEC}. Thus if the user is running an Interlisp in which he performs {lisp (SUBSYS 'LISP)}, and then types control-C to the lower Interlisp, control will be returned to the exec above the first Interlisp. If the user elects to call a subsystem directly, he must therefore know how it is normally exited and always exit from it that way.{foot Interlisp is exited via the function {fn LOGOUT}, TECO via the command {lisp ;H}, SNDMSG via control-Z, and EXEC via {lisp QUIT}. }{comment endfootnote} Starting a lower exec does not have this disadvantage, since it can {it only} be exited via {index QUIT (TENEX Command)}{lisp QUIT} or {lisp POP}, i.e., the lower exec is effectively "errorset protected" against control-C. {FnDef {FnName SUBSYS} {FnArgs FILE/FORK INCOMFILE OUTCOMFILE ENTRYPOINTFLG} {Text If {arg FILE/FORK}={lisp EXEC}, starts up a lower exec, otherwise runs {lisp <SUBSYS>}system, e.g. {lisp (SUBSYS 'SNDMSG)}, {lisp (SUBSYS 'TECO)} etc. {lisp (SUBSYS)} is the same as {lisp (SUBSYS 'EXEC)}. Control-C{index control-C} always returns control to next higher {it EXEC}. Note that more than one Interlisp can be stacked, but there is no backtrace to help you figure out where you are. {arg INCOMFILE} and {arg OUTCOMFILE} provide a way of specifying files for input and output. {arg INCOMFILE} can also be a string, in which case a temporary file is created, and the string printed on it. {arg ENTRYPOINTFLG} may be {lisp START}, {lisp REENTER}, or {lisp CONTINUE}. {lisp NIL} is equivalent to {lisp START}, except when {arg FILE/FORK} is a handle (see below) in which case {lisp NIL} is equivalent to {lisp CONTINUE}. }} The value of {fn SUBSYS} is a large integer which is a handle to the lower fork.{index fork handle} The lower fork is {it not} reset unless the user specifically does so using {index KFORK FN}{fn KFORK}, described below.{foot The fork is also reset when the handle is no longer accessible, i.e., when nothing in the Interlisp system points to it. Note that the fork is accessible while the handle remains on the history list. }{comment endfootnote} If {fn SUBSYS} is given as its first argument the value of a previous call to {fn SUBSYS},{foot Must be the exact same large number, i.e., {fn EQ}. Note that if the user neglects to set a variable to the value of a call to {fn SUBSYS}, (and has performed an intervening call so that {lisp (SUBSYS T)} will not work), he can still continue this subsystem by obtaining the value of the call to {fn SUBSYS} for the history list using the function {index VALUEOF FN}{fn VALUEOF}, described in {PageRef Fn VALUEOF}. }{comment endfootnote} it continues the subsystem run by that call. For example, the user can do {lisp (SETQ SOURCES (SUBSYS 'TECO))}, load up the TECO with a big source file, massage the file, leave TECO with {lisp ;H}, run Interlisp for awhile (possibly including other calls to {fn SUBSYS}) and then perform {lisp (SUBSYS 'SOURCES)} to return to TECO, where he will find his file loaded and even the TECO pointer position preserved. Note that if the user starts a lower EXEC, in which he runs an Interlisp, control-C's from the Interlisp, then {index QUIT (TENEX Command)}{lisp QUIT} from the EXEC, if he subsequently continues this EXEC with {fn SUBSYS}, he can reenter or continue the Interlisp. Note also that calls to {fn SUBSYS} can be stacked. For example, using {fn SUBSYS}, the user can run a lower Interlisp, and within that Interlisp, yet another, etc., and ascend the chain of Interlisps using {index LOGOUT FN}{fn LOGOUT}, and then descend back down again using {fn SUBSYS}. For convenience, {lisp (SUBSYS T)} continues the last subsystem run. {lisp SNDMSG}, {lisp LISP}, {lisp TECO}, and {lisp EXEC} are all {index LISPXMACROS Var}{var LISPXMACROS} ({PageRef Var LISPXMACROS}) which perform the corresponding calls to {fn SUBSYS}. {lisp CONTIN} is a {lisp LISPXMACRO} which performs {lisp (SUBSYS T)}, thereby continuing the last {fn SUBSYS}.{foot The {lisp EXEC} {lisp LISPXMACRO} is defined to save its value on {var LASTEXEC}{index LASTEXEC Var} so that subsequent {lisp EXEC} commands will restart the same exec. }{comment endfootnote} {FnDef {FnName KFORK} {FnArgs FORK} {Text Accepts a value from {fn SUBSYS} and kills it (RESET in Tenex terminology). If {lisp (SUBSYS {arg FORK})} is subsequently performed, an error is generated. {lisp (KFORK T)} kills all outstanding forks (from this Interlisp). }} {index *END* SUBSYS FN} }{End SubSec SUBSYS} {Begin SubSec JFN Functions in Interlisp-10} {Title JFN Functions in Interlisp-10} {Text {index JFN} JFN stands for Job File Number. It is an integral part of the Tenex file system and is described in [Mur1], and in somewhat more detail in the Tenex JSYS manual.{index JSYS} In Interlisp-10, the following functions are available for direct manipulation of JFNs: {FnDef {FnName OPNJFN} {FnArgs FILE ACCESS} {Text Returns the {index JFN}JFN for {arg FILE}. If {arg FILE} not open, generates a {lisp FILE NOT OPEN} error.{index FILE NOT OPEN Error} {arg ACCESS}={lisp NIL}, {lisp INPUT}, {lisp OUTPUT}, or {lisp BOTH} as described in discussion of {fn OPENP}. For example, {lisp (JSYS 51Q (OPNJFN FILE) BYTE)} will write a byte on a file, while {lisp (JSYS 50Q (OPNJFN FILE) NIL NIL 2)} will read one byte. }} {FnDef {FnName GTJFN} {FnArgs FILE EXT V FLAGS} {Text Sets up a "long" call to GTJFN (see {index JSYS}JSYS manual). {arg FILE} is a file name possibly containing control-F and/or <esc>. {arg EXT} is the default extension, {arg V} the default version (overriden if {arg FILE} specifies extension/version, e.g., {lisp FOO.COM;2}). {arg FLAGS} is as described on page 17, section 2 of JSYS manual. {arg FILE} and {arg EXT} may be strings or atoms; {arg V} and {arg FLAGS} must be numbers. Value is {index JFN}JFN, or {lisp NIL} on errors. }} {FnDef {FnName RLJFN} {FnArgs JFN} {Text Releases {arg JFN}. {lisp (RLJFN -1)} releases all JFN's which do not specify open files. Value of {fn RLJFN} is {lisp T}. }} {FnDef {FnName JFNS} {FnArgs JFN AC3 STRPTR} {Text Converts {arg JFN} (a small number) to a file name. {arg AC3} is either {lisp NIL}, meaning format the file name as would {fn OPENP} or other Interlisp-10 file functions, or else is a number, meaning format according to {index JSYS}JSYS manual.{index JFN} The value of {fn JFNS} is atomic except where enough options are specified by {arg AC3} to exceed atom size. In this case, the value is returned as a string. {arg STRPTR} is an optional string pointer to be reused. In this case, the string characters are stored in an internal scratch string, {index MACSCRATCHSTRING Var}{var MACSCRATCHSTRING}, so that a subsequent call to {fn JFNS} will overwrite the characters returned by this one. The value of {fn JFNS} when {arg STRPTR} is supplied is always a string. }} The following function is available in Interlisp-10 for specialized file applications: {FnDef {FnName OPENF} {FnArgs FILE X} {Text Opens {arg FILE}. {arg X} is a number whose bits specify the access and mode for {arg FILE}, i.e., {arg X} corresponds to the second argument to the Tenex JSYS OPENF (see JSYS Manual).{index JSYS} Value is full name of {arg FILE}. The first argument to {fn OPENF} can also be a number, which is then interpreted as a {index JFN}JFN. {fn OPENF} does not affect the primary input or output file settings, and does not check whether the file is already open - i.e., the same file can be opened more than once, possibly for different purposes. }} Note that for almost all applications the function {fn OPENFILE} ({PageRef Fn OPENFILE}) provides a more convenient (and implementation independent) way of opening files. }{End SubSec JFN Functions in Interlisp-10} {Begin SubSec Display Terminals} {Title Display Terminals} {Text The value of the variable {var DISPLAYTERMFLG}{index DISPLAYTERMFLG Var} indicates whether the user is running on a display terminal or not. {var DISPLAYTERMFLG} is used in various places in the system, e.g., {fn PRETTYPRINT}, {fn HELPSYS}, etc., primarily to decide how much information to present to the user (more on a display terminal than on a hard copy terminal). {var DISPLAYTERMFLG} is initialized to the value of {lisp (DISPLAYTERMP)}, whenever Interlisp is (re)-entered, and after returning from a sysout. {FnDef {FnName DISPLAYTERMP} {FnArgs } {Text Value is {lisp T} if user is on a display terminal, {lisp NIL} otherwise. In Interlisp-10, {fn DISPLAYTERMP} is defined to invoke the appropriate jsys to check the user's terminal type. }} }{End SubSec Display Terminals}