file: LISPIO, node: Top, up: (LISP), next: Basic I/O, Source: lspman;ch13 > version of 1/6/75 This is an old exposition on NEWIO; some options, functions, and variables have disappeared since then. * MENU: * Basic I/O:: * Files:: * Naming Files:: * Opening and Closing:: * Specifying the Source or Destination for I/O:: * Basic IO Functions:: * Handling End of File:: * Default File Names:: * Operating System Requests:: (THIS SECTION SEEMS TO BE MISSING) * Terminals:: * File System:: * Random Access Files:: * OLDIO:: * Read - advanced:: * Obarray:: * Readtable:: * Printer Format:: * Input Format:: * Moby IO::  file: LISPIO, node: Basic I/O, previous: Top, up: Top, next: Files, Source: lspman;ch13 > version of 1/6/75 Input and output can be done in LISP in terms of S-expressions or in terms of characters. Operations may also be performed on certain devices, such as displays, robot arms, etc., in terms which are peculiar to the particular device, using the so-called "moby I/O" facility. Initially we will discuss just I/O on the user's terminal. S-expressions can be input by using the function read. (read) reads one S- expression, which is either a list enclosed in matching parentheses or an atom delimited by a special character such as a space or a parenthesis, which is saved and used to begin the next S-expression read. read returns the S- expression which it read, converting it from the external representation as characters to LISP internal form. See Chapter 2 and section 13.1.2. (readch) reads in one character and returns it as a character object. (tyi) reads in one character and returns a number which is the ascii code for the character. (print x) prints out the S-expression x in a form which is readable by humans but which could also be read back into LISP if it was printed to a file rather than to the terminal. See section 13.2.3 for an explanation of how to do this. The expression printed out is preceded by a newline and followed by a space. (In PDP-10 systems, a newline is actually two characters, a carriage return followed by a line feed. Except sometimes it is just a carriage return.) If special characters are used with other than their normal meanings, for example if a parenthesis appears in the pname of an atom, they are preceded by slashes so that the output could be read back in. Strings are enclosed in double quotes for the same reason. (prin1 x) is the same as (print x) except that the leading newline and trailing space are omitted. prin1 can be used to print multiple items on a line, but spacing between the items must be provided for explicitly, for example by evaluating (tyo 40). (princ x) is like (prin1 x) except that special characters are not slashified and strings are not quoted. This makes the output more pleasing in certain situations, however it cannot be read back into LISP. (terpri) types out a newline. Output of characters can be accomplished using either tyo or princ. (tyo n) outputs a character whose ascii code is given by the number n. princ may be used to output character objects. As implied above, these functions can also be used to do I/O on devices other than the terminal. The ways to do this will be explained in section 13.2.3. Note that what LISP does when it is at its "top level," that is when you first start talking to it, is first to call read, then to call eval on what was read, then to print the result and advance the terminal to a new line on which the next piece of input may be typed. This may be expressed as repeated evaluation of: (prog2 (terpri) (print (eval (read))) )  file: LISPIO, node: Files, previous: Basic I/O, up: Top, next: Naming Files, Source: lspman;ch13 > version of 1/6/75 I/O in LISP consists of communication between the LISP environment and sequences of characters called files, located in the external world. LISP refers to these files by using "file objects," which are special objects within the LISP environment which serve as representatives of, or symbols for, the files in the external world. Because there is a one-to-one correspondence between files and file objects, it is often convenient to confuse the two and call them both "file." The LISP system includes functions which can manipulate files in various ways: A file may be "opened," that is a file object may be created and associated with a named file in the external world. A file may be "closed," that is the association between the file-object and the external file may be broken and the file-object deleted. The file-accessing information contained in a file-object may be examined or changed; for example, the line length of an output file may be adjusted. The characters of information in the external file may be read or written. The attributes of the external file, such as its name, may be changed. In order to "open" a file, the external file and the file object must be named so that a connection may be established between them. The problem of naming file objects is solved trivially by making the rule that whenever a file object is created its name is decided by the system and returned as the value of the function that created it. File objects are then referred to in the same way as any S-expression. Note that the name of a file object does not have a printable form, so that if you want to manipulate the file object by typing from the terminal (rather than from a program), you must keep the file object as the value of an atomic symbol. The naming of files in the outside world is more difficult because MACLISP has to operate with several different outside worlds, that is, under several different operating systems. It was thought undesirable to build too many assumptions about the operating system into the language, because that would restrict the transporting of programs between MACLISP implementations. The assumptions that are built in are that the operating system provides named files located in named directories or on named devices, which may be accessed sequentially as streams of characters. The function filepos makes the additional assumption that simple random-access facilities are available. An interactive environment is also assumed. Some of the I/O functions assume that the names of files may be broken up into an arbitrary or implementation-defined number of components, so that names take on a form such as "foo.bar.lisp" or "moby mess". However, it is possible for a MACLISP to operate with somewhat reduced effectiveness under an operating system which does not satisfy all of these assumptions. The user of a program or a subsystem written in LISP wants to be able to type in file names in the form customary in the particular operating system being used, and he wants to see them typed out in the same form. But if a program wants to do more with the file name supplied by the user than simply pass it on to the system I/O functions, it needs to have that name translated to a uniform internal format, in which the interesting components of the name are seperate atoms in a list, not buried inside a character string whose format is not even known to the program. To resolve this conflict, two forms for file names have been defined, and functions are provided to make the implementation-dependent translation from one form to the other. The forms of a file name are called the namelist and the namestring. The namestring is the implementation dependent form. Namestrings are represented as LISP character strings, however atomic symbols may also be used, in which case the pname of the atomic symbol is used as the character string. The contents of a namestring is just a sequence of characters which have meaning to the user and to the function namelist, which converts a namestring to a namelist. Namestrings should be read in using the readstring function and printed out using princ, so that no quotes will appear around them. A namelist is a list whose car somehow specifies the device and/or directory which contains the file, and whose cdr specifies the name of the file. The exact way in which the car specifies the device/directory is implementation- dependent. It should not be of concern to programs. The cdr of a namelist is a list of names which are the components of the file name if the operating system uses multi-component file names. Each name is represented as an atomic symbol, which is "interned" so that it may be tested with the function eq. An additional feature of namelists is the "star convention," by which a namelist may contain unspecified components, which are indicated by the atom *. Certain other constructions, explained in section 13.3, may also be used. The star convention allows a single namelist to specify a class of files, and allows programs to apply defaults to their file-name arguments in a straightforward fashion. Some additional information about file objects has been collected here. It is in brief form and will be elaborated in later sections. There is no way to input file objects to the reader, because they do not have pnames or anything of that sort, but for convenience in error messages and debugging the printer will print a file object as a sharp sign (#), followed by the namestring of the external file to which the file object is attached. # is the character which is used to indicate that an object of unknown type is being printed. The information contained within a file object is here described briefly. Namelist the namelist for the external file of which the file object is a representative. Eoffn a function which is applied when the end of an input file is reached. Endpagefn a function which is applied when the end of a page is reached on an output file. Linel the number of characters per line on an output file. Charpos the horizontal position on the line, where 0 is the left margin. Chrct the number of character positions remaining on the current line of an output file. Pagel the number of lines per page. Linenum the number of the current line, with 0 being the top of the page. Pagenum the number of the current page, with the first page being 0. Filepos the position within the file of the character currently being accessed. (Not necessarily meaningful for all kinds of files.) Other internal information used by the LISP I/O functions in transactions with the operating system. Note that as a special case t is considered to be a file object which represents the terminal. In the Multics implementation, nil will also be accepted to mean the terminal. This is for compatibility only, and will go away some day.  file: LISPIO, node: Naming Files, previous: Files, up: Top, next: Opening and Closing, Source: lspman;ch13 > version of 1/6/75 Some examples may help clarify the connection between namelists and namestrings. In the Multics system, files are stored in a tree structure of directories. A file's name consists of a sequence of names separated by the ">" character. The last name is the name of the file, and preceding names are the names of directories in a path from the "root" directory down through the tree to the file in question. Each name may consist of several components seperated by periods. Thus a typical namestring in the Multics implementation of MACLISP would be ">udd>AutoProg>Hacker>hacks>my.new.hack" The corresponding namelist is: (>udd>AutoProg>Hacker>hacks my new hack) In addition, the star convention for namelists may also be represented in namestring form. Some examples of the correspondence are: (* foo) == "foo" - omitted components are * (* foo * bar) == "foo.*.bar" (frotz foo . bar) == "frotz>foo.**.bar" (* foo . *) == "foo.**" Multics MACLISP can also use "streams" for files. Streams are a sequential- I/O entity in Multics. For example, input from and output to the terminal are performed by means of streams. In MACLISP the convention has been defined that a "$" character at the beginning of a namestring distinguishes the name of a stream from the name of a file stored in the directory hierarchy. Thus the namestring "$user_input" indicates the stream used for input from the terminal. The corresponding namelist is: (stream user_input) In the ITS (pdp-10) system, files are stored in directories which are kept on devices. Directories may not be kept within directories, so there is no tree structure. Each file-name has exactly two components. Thus a file whose name has first component foo and second component bar, located in directory comlap on device ml, would have the namestring: ml:comlap;foo bar As a namelist this would be represented: ((ml . comlap) foo bar) If the device and directory were omitted, the namelist would be: (* foo bar) If only one component of the name were specified, the second would be *. In the DEC-10 implementation, namestrings take the form dev:name.ext[proj,prog] The corresponding namelist is ((dev proj prog) name ext) and *'s are substituted for omitted components in the same way as for the ITS version described above. namelist SUBR 1 arg namelist converts its argument to a namelist. Omitted or * components in the argument produce *'s in the result. The argument to namelist can also be a file object or nil. Giving namelist a file object causes it to return the namelist of that file object. Giving it nil causes it to return the default namelist. namestring SUBR 1 arg namestring converts its argument from a namelist to a namestring. It is the opposite of namelist. The argument to namestring can also be a file object or nil. Giving namestring a file object causes it to convert that file object's namelist to a namestring and return it. Giving namestring nil causes it to convert the default namelist to a namestring and return it. shortnamestring SUBR 1 arg shortnamestring is just like namestring except that there is no mention of directory or device in the resulting string. Example: (shortnamestring '(abc d e)) => "d.e" defaultf SUBR 1 arg (defaultf x), where x is a namelist or a namestring, sets the default namelist to x. The default namelist is used to fill out any *'s in the argument to openi, openo, etc. In Multics MACLISP, the default namelist is initially set to: (working-directory . *) when lisp is first entered. In ITS MACLISP, the default namelist is initially set to: ((dsk udir) . *) when lisp is first entered. udir is what (status udir) returns, namely the user's directory. In DEC-10 MACLISP the default namelist is set to ((dsk proj prog) . *) when lisp is first entered. Note: to obtain the default namelist, use (namelist nil).  file: LISPIO, node: Opening and Closing, previous: Naming Files, up: Top, next: Specifying the Source or Destination for I/O, Source: lspman;ch13 > version of 1/6/75 openi SUBR 1 arg This function is used to create a file object and associate it with a file in the external world. The argument is a namelist or namestring which specifies the file to be opened. The return value is the file object which was created. 3openi first creates a file object and initializes its endpagefn (for an output file) or eoffn (for an input file) to the default. The linel and pagel are set to appropriate values for the type of device on which the file resides. The charpos, linenum, and pagenum are set to zero. The namelist is set by merging the argument to openi and the default namelist. See the description of the mergef function, in section 13.3, for the full details. Basically what happens is that components of the file name not elist. openi now negotiates with the operating system to obtain the file. A fail-act correctable error occurs if this does not succeed. The file created by openi can be used for input. Example: (inpush (openi "input_file_1")) openo SUBR 1 arg openo is like openi except that the file object created is used for output. Any pre-existing file of the same name is over-written. Example: (setq outfiles (list openo "output.data"))) opena SUBR 1 arg opena is just like openo except that if there is a pre-existing file with the same name, the output is appended to the end of the file, where openo would erase the old contents of the file and begin outputting at the beginning of the file. Note that the pagenum, linenum, and charpos are set to zero, not the number of pages, lines, etc. actually present in the file. close SUBR 1 arg (close x), where x is a file, closes x and returns t. If x is already closed nothing happens, otherwise the file system is directed to return x to a quiescent state. For a description of the way in which the argument to openi, openo, or opena has the defaults applied to it, see section 13.3.  file: LISPIO, node: Specifying the Source or Destination for I/O, previous: Opening and Closing, up: Top, next: Basic IO Functions, Source: lspman;ch13 > version of 1/6/75 When an I/O function is called, the source (file) from which it is to take its input or the destinations (files) on which it is to place its output may be specified directly as an argument to the function, or they may be specified by default. The default input source and output destinations are specified by several system variables, which may be setq'ed or lambda-bound by the user. They are described below. infile is the default input source, if the switch ^q is t. If ^q is nil the terminal is used as the default input source. outfiles is a list of default output destinations. Output is sent to all of these files if the ^r switch is t. Output also goes to the terminal unless the ^w switch is t. Note that in the values of infile and outfiles t means the terminal, and anything other than t must be a file object. infile VARIABLE The value of infile is a file object which is the default input source if ^q is non-nil. infile can also be t which specifies that input will be from the terminal even if ^q is not nil. The initial value of infile is t. ^q SWITCH If the value of ^q is non-nil, the default input source is the value of the atom infile. If ^q is nil, the default input source is the terminal. instack VARIABLE The value of instack is a list of pushed-down values of infile. It is managed by the function inpush. The initial value is nil. outfiles VARIABLE The value of outfiles is a list of file objects which are output destinations if ^r is not nil. Elements of the list outfiles may be either file objects created by openo or opena, or t meaning output to the terminal. Note that output goes to the terminal anyway if ^w is nil, so it is possible to get double characters this way. ^r SWITCH If the value of ^r is non-nil, the default output destinations include the files in the list which is the value of the atom outfiles. ^w SWITCH If the value of ^w is non-nil, the default output destinations do not include the terminal. (Unless ^r is on and t is a member of the outfiles list.)  file: LISPIO, node: Basic IO Functions, previous: Specifying the Source or Destination for I/O, up: Top, next: Handling End of File, Source: lspman;ch13 > version of 1/6/75 Now the basic I/O functions can be explained in full detail: read LSUBR 0 to 2 args This is the S-expression input function. (read) reads an S-expression from the default input source. (read f), where f is a file or t meaning the terminal, reads an S-expression from f. During the reading, infile and ^q are bound so that evaluation of (read) within a macro-character function will read from the correct input source. (read x), where x is not a file, not nil, and not t, passes x as an argument to the end-of-file function of the input source if the end of the file is reached. Usually this means that read will return x if there are no more S-expressions in the file. (read x f) or (read f x) specifies the end-of-file value x and selects the input source f. (read f t) suppresses the calling of the end-of-file function if the end of the file is reached. Instead, read just returns t. readch LSUBR 0 to 2 args readch reads in one character and returns a character object. The arguments are the same as for read. readline LSUBR 0 to 2 args readline reads in a line of text, strips off the newline character or characters at the end, and returns it in the form of a character string. The arguments are the same as for read. One use for readline is reading in file names typed by the user at his terminal in response to a question. tyi LSUBR 0 to 2 args tyi inputs one character and returns a fixnum which is the ascii code for that character. The arguments are the same as for read. tyipeek LSUBR 0 or 1 arg (tyipeek) is like (tyi) except that the character is not eaten; it is still in the input stream where the next call to an input function will find it. Thus (= (tyipeek) (tyi)) is (almost) always t. If the end of the file is reached, tyipeek returns 3, the ascii code for "end of text." The end of file function is not called, and the file is not closed. (tyipeek n), where n is a fixnum less than 200 octal, skips over characters of input until one is reached with an ascii code of n. That character is not eaten. (tyipeek n), where n is a fixnum > or = 1000 octal, skips over characters of input until one is reached whose syntax bits from the readtable, logically anded with (lsh n -9.), are nonzero. (tyipeek t) skips over characters of input until the beginning of an S-expression is reached. Splicing macro characters, such as ";" comments, are not considered to begin an object. If one is encountered, its associated function is called as usual (so that the text of the comment can be gobbled up or whatever) and tyipeek continues scanning characters. prin1 LSUBR 1 or 2 args (prin1 x) outputs x to the current output destination(s), in a form suitable for reading back in. (prin1 x f) outputs x on the file f, or the terminal if f is t. print LSUBR 1 or 2 args print is like prin1 except that the output is preceded by a newline and followed by a space. This is the output function most often used. (print x) prints x to the default output destinations. (print x f) prints x to the file f, or to the terminal if f is t. princ LSUBR 1 or 2 args princ is like prin1 except that special characters are not slashified and strings are not quoted. The output generated by princ may be easier for a human to read, but it cannot be read back in to lisp. (princ x) outputs x to the current output destination(s). (princ x f) outputs x to the file f, or the terminal if f is t. tyo LSUBR 1 or 2 args (tyo n) types out the character whose ascii code is n on the current output destination(s). (tyo n f) types out the character whose ascii code is n on the file f or on the terminal if f is t. tyo returns its first argument. terpri LSUBR 0 or 1 arg (terpri) sends a newline to the current output destination(s). (terpri f) sends a newline to f, where f may be an output file or t meaning the terminal. inpush SUBR 1 arg (inpush f), where f is a file object open for input or t to specify the terminal, pushes the current input source onto the input stack and selects f as the current input source. This is like (setq instack (cons infile instack)) (setq infile f) f is returned. (inpush 0) just returns infile. (inpush -1) pops a new input source off of the input stack: (setq infile (car instack) instack (cdr instack)) except that in the case where instack is nil, i.e. empty, inpush leaves instack nil and makes infile t, which means the terminal. (inpush -n) does (inpush -1) n times. (inpush 1) does (inpush (inpush 0)), (inpush +n) does that n times. The result of inpush is the newly selected input source. If inpush causes infile to be set to t, ^q is set to nil since the terminal has become the input source.  file: LISPIO, node: Handling End of File, previous: Basic IO Functions, up: Top, next: Default File Names, Source: lspman;ch13 > version of 1/6/75 Calls to the input functions read, readch, readline, and tyi specify an optional argument called the "eofval." If this argument is omitted nil is assumed. If the end of the input file is reached during the execution of the function, the eofval argument is used by the following procedure: Each input file object has an end-of-file handler, its eoffn. When an end of file occurs while input is being taken from this file, the eoffn is examined. (Eof on the terminal cannot occur.) If the eoffn is nil, then the following default action is taken: If eofval on the call to the reader was not supplied, then the input file is closed and the reader continues taking characters from a new input file popped off the input stack. If the input stack is empty, (setq ^q nil) is done and the reader continues reading from the terminal. If an eofval was supplied on the call to read, then the reader immediately returns it. The input file is not closed. This is not strictly true in the case where the input function is read (or readline) and it is in the middle of an object (or a line). In this case, rather than allowing the object to cross files, a fail-act error occurs. The argument passed to the user interrupt service function is the list (read-eof). If the interrupt service function returns an atom (such as nil), the reader signals an error; but if it returns a list, the reader goes on reading from the new input source as if there had not been any end-of-file. If the eoffn for the input file is not nil, then it is a function and it is applied with two arguments. The first argument is the file object that eof'ed. The second argument is the eofval on the call to the reader, or, if an eofval was not supplied, nil. If the eoffn returns nil, the file is closed and reading continues from the input source popped off the input stack. The above prohibition of objects crossing eofs applies. If the eoffn returns t, reading continues from whatever input source was made the current default one by the eoffn. If the eoffn returns something other than t or nil, then the reader immediately returns whatever the eoffn returned, and the file is not closed unless the eoffn closes it. eoffn LSUBR 1 or 2 args (eoffn x), where x is an input file, gets x's end-of-file function. The end-of-file function is called if the end of the file is reached during input. (eoffn nil) gets the default end-of-file function. (eoffn x f) sets x's end-of-file function to f. (eoffn nil f) sets the default end-of-file function to f. f may be nil, which means that no end-of-file function is to be used.  file: LISPIO, node: Default File Names, previous: Handling End of File, up: Top, next: Operating System Requests, Source: lspman;ch13 > version of 1/6/75 The I/O system provides a mechanism for applying defaults which programs can use and which is used when a file object is created by the open functions. A default namelist, eoffn, and endpagefn are remembered for initialization of file objects when they are created by the openi, openo, opena, or open function. These defaults may be examined and modified by use of the eoffn, endpagefn, namelist, and defaultf functions. Passing nil instead of a file object indicates that the defaults are being referred to. There is also a system of defaults for file names (actually for namelists), which is based on the use of namelists containing the special atom *. If one of the elements in a namelist is the atom *, it indicates that that component is not specified. Thus the namelist (* foo bar) specifies a file named foo.bar but it is not said in what directory or on what device it exists. Similarly a namelist like (dir foo *) indicates a file in directory dir, with a two component name of which the first component is foo, but the second component is not specified. A namelist may also be dotted, that is, it may end with an atom rather than with nil. If it ends with an atom other than *, i.e. if it looks like (devdir name1 name2 name3 . foo) it specifies a file whose name begins with the components name1.name2.name3, ends with the component foo, and may also have any number of components in between. For example, ignoring directories, in a system such as Multics where the namestring consists of the file-name components from the namelist concatenated together with periods, the namelist (-- moe larry . mung) could specify all of the following file names: moe.larry.mung moe.larry.curly.mung moe.larry.foo.bar.blech.mung and so on. This form of namelist can be used to apply what is sometimes called a "default extension." A namelist can also have a dotted star, that is it can be in the form (devdir -names- . *) This specifies a file whose name begins with the components -names-, and may have zero or more components following those. Thus (-- mung bung . *) means any of these file names: mung.bung mung.bung.lung mung.bung.foo.goo.zoo The process of applying defaults to file names consists of "merging" two (or more) namelists into a single namelist, where one of the namelists is a user-supplied file specifier and the other is a set of defaults. For this purpose, the function mergef is supplied. mergef is also used by openi, openo, etc. when they combine their argument with the default namelist to get the namelist of the file to be opened. mergef LSUBR 2 or more args mergef is used for applying defaults to file specifiers, which may be namelists or namestrings. (mergef x y) returns a namelist obtained by selecting components from x and y, which are converted to namelists. Where a component of x is *, the corresponding component of y is selected. It is an error if y is not that long. When a component of x is not *, it is selected and the corresponding component of y is skipped. If y ends with a dotted atom other than a this atom is added to the end of the namelist if it is not already there. The same applies if x ends with a dotted atom. If x ends with a dotted *, the rest of y is copied over. (mergef x nil) strips off the last component of x. (mergef w x y z) is equivalent to (mergef (mergef (mergef w x) y) z).  file: LISPIO, node: Operating System Requests, previous: Default File Names, up: Top, next: Terminals, Source: lspman;ch13 > version of 1/6/75  file: LISPIO, node: Terminals, previous: Operating System Requests, up: Top, next: File System, Source: lspman;ch13 > version of 1/6/75 cursorpos LSUBR 0 to 2 args The cursorpos function is used to manipulate the cursor on those display terminals which which can address each character on their screen. Often they show exactly one character at each position on the screen and can change each of these characters separately. Even if the terminal cannot do this, those functions of cursorpos which make sense for the particular terminal will work. With no arguments cursorpos returns the dotted pair (line . column), where line is the line number, starting from 0 at the top of the screen, and column is the column position, starting from 0 at the left edge of the screen. If the terminal being used is not a display terminal with this type of cursor, nil is returned instead. With two arguments, (cursorpos line column) moves the display cursor to the indicated position and returns t if it was successful, or nil if the terminal was incapable of doing this. Either of the two arguments may be nil, indicating that that coordinate should not be altered. With one argument, cursorpos executes a number of special control operations. The argument must be a character object chosen from the following list: F move one column to the right (forward) B move one column to the left (backward) D move down by one line U move up by one line C clear the screen T go to top left corner of screen Z go to bottom left corner of screen E erase contents of screen after current point L erase from current point to end of line X delete character to left K delete character under cursor listen SUBR no args (listen) returns a fixnum which is non-zero if there is any input that has been typed in on the terminal but has not yet been read. In the ITS implementation it also waits for all terminal output and cursor motion to be completed. tty VARIABLE The atom tty is initially bound to an implementation-defined number describing the type of terminal being used. The values presently defined by the ITS implementation are: 0 normal terminal with no special capabilities 1 cursor oriented display terminal, such as datapoint 2 "losing" datapoint 3 Imlac 4 ARDS 5 pdp-11 TV 6 ARDS with sideways screen 7 "software" terminal In other implementations, tty will generally be zero, indicating "just an ordinary terminal."  file: LISPIO, node: File System, previous: Terminals, up: Top, next: Random Access Files, Source: lspman;ch13 > version of 1/6/75 deletef SUBR 1 arg (deletef x), where x is a namelist, a namestring, or a file object, deletes the file specified by x. The return value is the namelist of the file actually deleted, i.e. x mergef'ed over the defaults. Examples: In the Multics implementation, (deletef "foo.bar") => (>udd>proj>user>junk foo bar) In the ITS implementation, (deletef "foo bar") => ((ml loser) foo bar) rename SUBR 2 args (rename x y), where x and y are namelists, namestrings, or file objects, renames the file specified by (mergef x (names nil)) to the name specified by (mergef y x (names nil)). The directory part of y is ignored; a file may not be renamed onto a different device or directory. The return value is the namelist of the new name of the file. Examples: In the Multics implementation, (rename "foo.baz" "*.bar") => (>udd>Bar>Foo foo bar) and renames >udd>Bar>Foo>foo.baz to foo.bar. In the ITS implementation, (rename "foo baz" "* bar") => ((ml loser) foo bar) and renames ml:loser;foo baz to foo bar. allfiles SUBR 1 arg (allfiles x), where x is a namelist, returns a list of namelists which are precise; i.e. they do not contain any stars or dotted parts. These are the namelists for all the files in the file system which match the namelist x. Whatever search rules are customary in the particular operating system are used. allfiles with a precise namelist as an argument can be used as a predicate to determine whether or not a file exists. The argument to allfiles may also be a namestring or a file object. clear-input SUBR 1 (clear-input x), where x is a file or t meaning the terminal, causes any input that has been received from the device but has not yet been read to be thrown away, if that makes sense for the particular device involved. force-output SUBR 1 (force-output x), where x is a file or t meaning the terminal, causes any buffered output to be immediately sent to the file, if that makes sense for the particular device involved.  file: LISPIO, node: Random Access Files, previous: File System, up: Top, next: OLDIO, Source: lspman;ch13 > version of 1/6/75 filepos LSUBR 1 or 2 args (filepos x), where x is a file object open for input, returns the current character position within the file as a fixnum. The beginning of the file is 0. (filepos x n), where x is a file object open for input and n is a non- negative fixnum, resets the character position of the file to position specified by n. It is an error if this position does not lie within the file or if the file is not randomly accessible. n is returned.  file: LISPIO, node: OLDIO, previous: Random Access Files, up: Top, next: Read - advanced, Source: lspman;ch13 > version of 1/6/75 The functions uread, uwrite, ufile, ukill, crunit, uprobe, uappend, and uclose are part of an older LISP I/O system. They are retained for compatibility. Various "status" functions are also part of this older I/O system. (See section 12.7) These eight functions name files in a different way from the other I/O functions. A file is named by a 4-list, (name1 name2 dev dir) Name1 and name2 together make up the "filename," dev is the "device," and dir is the "directory." In the ITS implementation of MACLISP, these go together to make up the ITS file name: dev: dir; name1 name2 In the DEC-10 implementation, dev is the device name, name1 is the file name, name2 is the extension, and dir is a list of two fixnums, the project number and the programmer number. Thus the 4-list (name1 ext dev (proj prog)) represents the file dev:name1.ext[proj,prog] In the Multics implementation, dev is ignored and dir is the directory pathname. The entry-name is name1.name2. Thus the Multics filename is: dir>name1.name2 These eight functions maintain their own set of defaults, which are updated every time one of these functions is called, so that the defaults correspond to the last file that was used. The defaults may be examined with (status crfile), which returns the first two elements of the default 4-list, and (status crunit) which returns the last two. It is not necessary to specify all four parts of the 4-list when one of these eight functions is used. If the list contains less than four elements, the elements at the end which were dropped are supplied from the defaults. These functions are fsubrs which do not evaluate their arguments. They may be applied to a 4-list, e.g. (apply 'uread (cons filename '(stuff dsk macsym))) or they may be called with the 4-list as four arguments, which is convenient when calling them from top level. e.g.: (uread foo bar dsk crock) uread FSUBR This function selects an input file. The argument list is a 4-list as described above. The specified file is made the default input source. Note that the ^q switch must be turned on before input will be automatically taken from this file. uwrite FSUBR uwrite opens an output file. When done with this file, ufile must be used to close it and give it a name. The arguments are the last two elements of a 4-list, specifying the device and directory on which the file is to be written. The first two parts of the 4-list are not specified until the file is ufile'd. ufile FSUBR (ufile name1 name2) closes the uwrite output file and gives it the name name1.name2. The arguments are not evaluated. (ufile) takes name1 and name2 from the defaults. crunit FSUBR (crunit) returns the current device and directory. (crunit dev dir) sets the device and directory and returns it. The arguments are not evaluated. Example: (crunit) => (dsk >udd>Bar>Foo>subdirectory) ukill FSUBR (ukill -args-), where -args- are as for uread, deletes the specified file. uread VARIABLE The value of uread is a file object being used for input initiated by the uread function, or nil if no file is currently being uread. uwrite VARIABLE The value of uwrite is a file object being used for output initiated by the uwrite function, or nil if no file is currently being uwritten. uprobe FSUBR uprobe takes arguments like uread and returns t if the specified file exists, nil if it does not. uappend FSUBR uappend takes arguments like uread, but opens the specified file for output like uwrite does, renaming the file so no one else will get at it while you are outputting to it. ufile is used to finish outputting and rename the file back. The difference between uappend and uwrite is that the output is stuck onto the end of the file, instead of replacing what was previously there. uclose SUBR no arguments (uclose) closes the uread input file. This is useful before a suspend (ITS) or a save (Multics.) There are also some status/sstatus functions associated with these. These are (status crunit), (status crfile), (status uread), and (status uwrite).  file: LISPIO, node: Read - advanced, previous: OLDIO, up: Top, next: Obarray, Source: lspman;ch13 > version of 1/6/75 * MENU: * Obarray:: * Readtable::  file: LISPIO, node: Obarray, previous: Read - advanced, up: Read - advanced, next: Readtable, Source: lspman;ch13 > version of 1/6/75 obarray VARIABLE & ARRAY The value of obarray is an array which is a table of known atomic symbols - when an atomic symbol is read in it is "interned" on this obarray, that is, made eq to any atomic symbols with the same pname that were previously read in. If an atomic symbol, such as one created by (gensym), is not in this table an atomic symbol read in with the same pname will not be the same - there will be two separate copies. The obarray may be manipulated by the functions remob and intern. A new obarray may be created by using the *array function. The atom obarray may be setq'ed or lambda-bound to different obarrays at different times, which allows multiple sets of atomic symbols to be kept seperate - you can have different atomic symbols with the same pname interned on different obarrays at the same time. Note that the value of obarray is not an atomic symbol which names an array, but the array-object itself, as obtained by (get 'name 'array). The array property of obarray is the same array as its initial value. Example of the use of multiple obarrays: (setq private-obarray (*array nil 'obarray)) ;make another obarray. ((lambda (obarray) (read)) private-obarray) ;read using atoms on private obarray ;instead of regular one Formerly MACLISP included a makoblist function, which could be used to construct obarrays. This function no longer exists; the replacements for it are: (makoblist nil) => (listarray 'obarray) (makoblist x) => (*array x 'obarray) See chapter 9 for details of *array and listarray. See also the functions remob and intern.  file: LISPIO, node: Readtable, previous: Obarray, up: Read - advanced, next: Printer Format, Source: lspman;ch13 > version of 1/6/75 The readtable is a special table used to control the reader. It has an entry for each character, containing 26. syntax bits and a "chtran" character translation code. The "chtran" allows characters to be translated when they are put into pnames that are being read in. The syntax bits are used by the reader to determine the significance and syntactic meaning of each character it encounters. A table of the meanings of the bits follows. Initially the syntax bits are set to give the standard LISP meanings for all the characters, but the user can change them to make the read function usable as a lexical analyzer for a wide variety of input formats or languages. It is also possible to have several readtables containing different syntax and to switch from one to the other by binding the atom readtable. Table of Syntax Bits Octal Value Meaning 1 alphabetic: A-Z and a-z 2 "extended alphabetic" - used for characters which are not letters, but which are to be treated the same as letters. E.g. ":" in the standard syntax table. 4 digit: 0-9 40 This is the "alternate meaning" bit. When added in it alters the meaning of other bits. For example, 10 is plus sign but 10+40 is minus sign. 10 plus sign. 50 minus sign. 20 fixed-point-scaling number modifier character. In the standard readtable "^" has this syntax. An example of its use is 13^2, which is the same as 1300. 60 fixed point left-shift number modifier. In the standard readtable "_" has this syntax. An example of its use is 7_5, which is 7 shifted left 5 bits, or 340 octal. 100 Indicates that the character should be "slashified" by print, prin1, and explode if it appears in a pname but is not the first character in that pname. 200 Decimal point. Embedded in a number it indicates floating point. At the end of a number it indicates that the number is to be interpreted in decimal regardless of the value of ibase. Note that the decimal point need not be the same as the dotted-pair dot. 400 The character will be "slashified" by print, prin1, and explode if it is the first character in a pname. Thus special characters which need to be slashified usually have 500 = 100+400 in their syntax bits. 1000 Indicates that this character is the "rubout" character (in the pdp-10 implementations only.) 2000 The slashifier character, which is used as an escape. It makes special characters like space and parentheses look like letters. Normally "/" has this syntax. If this character appears in input to read or readlist, the following character is taken to have a syntax of 000000002 and its chtran is not used. This allows it to be used in a pname even if it is a special character. 4000 indicates a macro character. This bit should not be set explicitly, only by using (setsyntax c 'macro f) or (setsyntax c 'splicing f). When this character is seen in input to read or readlist, an associated function is called and the value returned by the function is assumed to have been read. 4040 same as 4000 except the macro is "splicing." That is, the associated function returns not an object to be inserted in the list being read, but a list to be spliced (nconc'ed) into the list being read. Splicing macros at top level (not inside a list) have their values ignored by the reader. The same applies to splicing macros that return nil, as this is the empty list. 10000 Right parenthesis. 10040 Right super-parenthesis. A super parenthesis cancels out all left parentheses back to the beginning of the object or to a left super-parenthesis. 20000 The dotted-pair dot. 40000 Left parenthesis. 40040 Left super-parenthesis. The chtran of a left super-parenthesis must be set to the ascii code for the corresponding right super-parenthesis so that the reader can check for proper matching of super parentheses. 100000 A blank, i.e. a character which delimits an atom or a number but is otherwise ignored. In the standard read table, space, tab, comma, and newline have this syntax. 600000 "Single-character object." This character begins, ends, and is an atomic symbol. The difference between a single character object and a letter is that a single character object need not be delimited by spaces or any other special characters. If ":" had this syntax then "(:::)" would read as a list of length three, unlike "(aaa)" which reads as a list of length one. In the standard readtable no characters have this syntax. 400000 A character with this syntax bit turned on ends pnames and numbers. In the standard readtable all the special characters such as space, parentheses, and dot have this syntax. 1000000 This character is the exponent introducer (e) for floating-point numbers. 1000040 This character is the string quote, which begins and ends character strings (usually a " sign.) 2000000 This character causes vertical motion (newline, newpage.) 4000000 In the pdp -10 implementations, this bit indicates a "force feed" character. The lisp reader in the pdp-10 implementation works in two passes. The first pass reads characters until it has either a string which looks like an atom followed by a blank, or it has a string containing balanced parentheses, or a force feed character is encountered. Then the second pass is called to read that string and make actual lisp objects according to these syntax rules. If the detailed syntax reveals that not enough has been typed, more is read in the same way. The reason for this two-pass scheme is to allow editing of the input with rubouts as much as possible. If you alter the syntax substantially by defining macro characters, the first pass may not do the right thing, so you may have to define some characters to be force feeds in order to get LISP to respond at the proper time. Peculiar behavior will occur if the force-feed characters, control characters, space, and parentheses are not "activation characters," which are the characters which cause the time-sharing system to activate LISP when it is waiting for input to be typed. See the ITS Reference manual for a description of activation characters. Use (sstatus tty ttyst1 ttyst2 ttysts) to set the ITS variables which control activation characters. If (sstatus linmode t) is done, only newline is a forcefeed and activation character. In the Multics implementation newline is always a forcefeed character and an activation character and no other character can play this role. The syntax for most characters is a combination of several of these bits. Here is a table of the syntax codes assigned to various characters in the standard readtable: worthless control characters 000400500 backspace (to allow underlining in pnames) 000000002 space, tab, newline, newpage (the "white space" characters) 000500500 (002500500 for nl and np) " 001400540 ' 000404500 ( 000440500 ) 000410500 + 000000410 - 000000450 , 000500500 000420700/ 000402500 0-9 000000404 ; 000404540 A-Z 000000001 E 001000001 ^ 000000022 _ 000000062 a-z 000000001 e 001000001 The remaining special characters have 000002 syntax. setsyntax SUBR 3 args (setsyntax c s x) adjusts the syntax of the character c in the readtable. c can be a fixnum which is the ascii code for a character, or it can be a character object or a string one character long. s can be one of the following: nil don't change the syntax of c a fixnum set the syntax bits for c to that fixnum single set the syntax of c to the syntax for single-character objects macro set the syntax of c to be a macro character in which case x is the function for the macro splicing which is like macro except it makes a splicing macro a character object or string in which case the standard initial syntax for this character is used. x can be a fixnum to which c's chtran should be set, or a character object or one-character string to which c's chtran should be set, or nil meaning don't change c's chtran, or a function if the second argument was splicing or macro. If c is a macro character, it is changed back to its standard syntax and chtran before anything else is done, unless it is a macro in the standard readtable, in which case its syntax is set to 502 (slashified extended alphabetic) and its chtran is set to itself. setsyntax always returns t. readtable VARIABLE & ARRAY The value of readtable is an array which contains tables used by the reader to determine the meaning of input characters. This array may be manipulated using the functions setsyntax, status, and sstatus. Multiple readtables may be constructed by using the *array function, and the atom readtable may be lambda-bound or setq'ed to one or another of these readtables. Note that the value of readtable is not an atomic symbol which names an array, but the array-object itself, which is the result of (get 'x 'array) if x names an array. The array property of readtable is the same as its initial value, which is the read table with the standard meanings for all characters. Formerly MACLISP included a makreadtable function, used for creating readtables. It has been replaced by *array, as follows: (makreadtable t-or-nil) => (*array (gensym) 'readtable t-or-nil) (makreadtable x) => (*array x 'readtable) See chapter 9 for details of *array. See also the functions status and sstatus (section 12.7).  file: LISPIO, node: Printer Format, previous: Readtable, up: Top, next: Input Format, Source: lspman;ch13 > version of 1/6/75 This section describes how the functions print, prin1, princ, explode, exploden, and explodec convert LISP objects to strings of characters so that they can be printed out in readable form. Atomic symbols are represented by their "pnames," which are the strings of characters by which they were originally typed in. When special characters appear in a pname, they are sometimes "slashified," i.e. preceded by a "/" to remove their special meaning. See the descriptions of the individual functions to see which slashify and which don't. Strings are printed out as the characters they contain. Those functions which slashify put quotes (") around strings to distinguish them from atomic symbols and to indicate that any special characters, such as space or period, they may contain are not to be considered to have their special meanings. Flonums are printed out in decimal radix, with an embedded decimal point. If the magnitude of the number is outside of a certain range, a trailing exponent delimited by an "e" is printed. Fixnums are printed in the radix specified by the variable base. Negative fixnums have a preceding "-" sign. If base is ten and the variable *nopoint is nil, which it is unless changed by the user, fixnums will be printed with a trailing decimal point. If the base is greater than ten, letters will be used as digits. Fixnums with many trailing zeros are made more legible by use of the "_", or left-shift, operator, unless (sstatus _ nil) is done. The "_" character is used because on certain formerly-used terminals it was printed as a leftward arrow. The use of the "_" can be described by example: in octal radix, "12345000000" would be printed instead as "12345_18.". Bignums are printed in much the same format as fixnums. Lists or "conses" are represented using the parentheses notation that has been used throughout this manual. A dotted pair whose cdr is nil is printed as a list but other dotted pairs are printed using the dot. Thus (cons 'a nil) prints as (a), while (cons 'a 'b) prints as (a . b). (list 'a 'b 'c) prints as (a b c) rather than (a . (b . (c . nil))). Array-pointers are printed as a sharp sign (#), followed by the type of array, followed by the dimensions, followed by the machine address of the array in a format useful to system debuggers. In the case of a dead array, only "#dead-array" is printed. An example of the format is shown below: #FIXNUM-4:3-343425 (ITS) or #fixnum-4:3-335|2206 (Multics) File objects are printed as a sharp sign and the namestring of the file. Random objects which do not fit any of the above categories are printed as a sharp sign and the octal internal representation of the object. The reader will not recognize these sharp-sign strings, if fed back into it, as array-pointers, file-objects, etc. They will probably be read as atomic symbols. *nopoint SWITCH If the value of *nopoint is nil, trailing decimal points are printed when numbers are printed out in base ten. This allows these numbers to be read back in correctly even if ibase is not ten. If *nopoint is non-nil, the trailing decimal points are suppressed. The initial value of *nopoint is nil. base VARIABLE The value of base is a number which is the radix in which numbers are to be printed. The initial value of base is 8. Most files have a limit on the number of characters that may be printed on a single line when output is done to these files. For example, on the user terminal the maximum number of characters per line is determined by the width of the platen or display screen. This limit is called the file's "linel." When a file-object is created, its linel is set to a value appropriate for the device on which the file resides. Each file also has another number associated with it, called its "charpos." The charpos is the horizontal position, starting with 0 at the left margin. If no backspaces or tabs are used it is the number of characters that have been printed so far on the current line. As characters are sent to the file, the charpos increases for printing characters or is adjusted appropriately for format effectors such as carriage return or backspace. When charpos exceeds linel, an automatic newline is provided by the output functions, such as print, to ensure that the line being sent to the file is not longer than the file's linel. This feature can be turned off by use of the (sstatus terpri) function. Note that the linel is not an absolute limit since some implementations will not break atoms across lines, so that a particularly long atom near the right margin could result in a line longer than linel. Some other attributes of a file are its linenum, pagel, and pagenum. The linenum is the line number, starting with 0 at the top of a page. The pagel is the number of lines per page. The pagenum is the page number, starting with zero at the beginning of the file. The following functions can be used to examine or modify the attributes of files: linel LSUBR 1 or 2 args (linel f), where f is an output file, or t meaning the terminal gets the number of characters per line on f. Lines output to f that exceed this length get an extra newline inserted. If the linel = 0, this feature is suppressed. (linel f n) sets the file f's linel to the fixnum n. charpos LSUBR 1 or 2 args (charpos f), where f is a file or t meaning the terminal, returns the current character position of f, with 0 being the left margin. (charpos f n) sets the charpos of f to the fixnum n. This does not move a cursor or anything of that sort. chrct LSUBR 1 or 2 args This is an older, now obsolete, version of charpos. (chrct x), where x is an output file or t meaning the terminal, returns the number of character positions remaining on the line being output to x. (chrct x y), where x is a file and y is a fixnum, sets x's chrct to y and returns y. pagel LSUBR 1 or 2 args (pagel f), where f is a file or t meaning the terminal, returns the number of lines per page of the file f. (pagel f n) sets the number of lines per page of the file f to the fixnum n. linenum LSUBR 1 or 2 args (linenum f), where f is a file or t meaning the terminal, returns the current line number of f, with 0 being the top of the page. (linenum f n) sets the line number of f to the fixnum n. Note that this does not causes any physical motion, it simply changes the number. pagenum LSUBR 1 or 2 args (pagenum f), where f is a file or t meaning the terminal, returns the current page number of f, which is 0 when the file is first opened. (pagenum f n) sets the page number of the file f to the fixnum n. The printing of large lists can be limited by use of the variables prinlevel and prinlength. If these variables are nil, they have no effect, but if they are set to fixnum values they take effect as follows: prinlevel specifies the maximum depth of nested parentheses that will be printed. If this depth of nesting is exceeded, a sharp sign (#) will be printed and the list structure below that depth will be omitted. prinlength specifies the maximum number of list elements (atoms or sub-lists) that will be printed in any one list. If more than this number need to be printed, the excess will be omitted and 3 dots (...) will be printed to indicate the omission. These features operate under the control of some abbreviation control bits set by (sstatus abbreviate). (sstatus abbreviate 1) enables it for print, prin1, etc. when they output to files. (sstatus abbreviate 2) enables it for flatsize, flatc, explode, etc. (sstatus abbreviate 3) enables it for both. (sstatus abbreviate t) enables it for everything (currently the same as 3). (sstatus abbreviate nil) or (sstatus abbreviate 0) turns it off. Note that abbreviation is always in effect for the terminal. The only way to turn it off is to setq prinlevel and prinlength to nil (which is their initial value). prinlevel VARIABLE prinlevel can be set to the maximum number of nested lists that will be printed before the printer will give up and just put a "#". If it is nil, which it is initially, any number of nested lists can be printed. Otherwise, the value of prinlevel must be a fixnum. The effect of prinlevel is under the control of (sstatus abbreviate). prinlength VARIABLE prinlength can be set to the maximum number of elements of a list that will be printed before the printer will give up and just put "...". If it is nil, which it is initially, any length list can be printed. Otherwise, the value of prinlength must be a fixnum. The effect of prinlength is under the control of (sstatus abbreviate). endpagefn LSUBR 1 or 2 args (endpagefn f), where f is an output file, returns the end of page function of f. This is a function which is invoked whenever the file is advanced to a new page. nil is returned if f has no endpagefn. (endpagefn f z) sets the endpagefn of the file f to the functional form z. If z is nil f's endpagefn is removed. Note that if f is t it means set the endpagefn of the terminal, which may or not be implemented depending on the implementation and the type of terminal.  file: LISPIO, node: Input Format, previous: Printer Format, up: Top, next: Moby IO, Source: lspman;ch13 > version of 1/6/75 This section describes the forms of input which will be accepted by the read function and converted to LISP objects. A string of digits, with an optional leading sign and trailing decimal point, is read as a fixnum, unless it is too large to fit in a fixnum, in which case it is read as a bignum. If a trailing decimal point is included, the number is converted in decimal radix. Otherwise the variable ibase specifies the radix. Initially it is eight. If ibase is greater than ten, and the number begins with a leading "+" or "-" sign, and (status +) is not nil, upper- or lower-case letters may be used as digits, with "a" and "A" being 10., "b" 11., etc. If (status +) is nil, the standard initial setting, this feature is turned off and what looked like a number with letters as digits would be read as an atomic symbol. ibase VARIABLE The value of ibase is a number which is the radix in which numbers will be read. The initial value of ibase is 8. "Fixed point number modifier" characters may be used in fixnums or bignums. In the standard readtable these characters are "_" and "^". "mmm_nn" causes the number mmm to be shifted left nn bits. Note that nn is interpreted in the ibase radix unless a trailing decimal point is placed on it. If mmm is to be read in decimal, a trailing decimal point may be placed just before the "_". "mmm^nn" is read in as mmm followed by nn zeros, i.e. as mmm multiplied by the nn'th power of the input radix. nn must have a trailing decimal point if it is not to be interpreted in the ibase radix. A string of digits with a leading or embedded decimal point, and/or an exponent introduced by "e" or "E", is read as a flonum. The number and the exponent may be optionally signed. The number and the exponent are interpreted in decimal radix regardless of ibase. The number is generally converted to binary and rounded to the equivalent of 6 to 8 decimal digits of precision, depending on the implementation. A string of letters, numbers, and "extended alphabetic" characters represents an atomic symbol whose pname is the string, provided that it does not look like a number (e.g. all numeric characters.) A special character, such as a parenthesis, a period, or a space, may be included in an atomic symbol by preceding it with a slash. A slash itself is represented by two slashes. A string of digits may be made to represent an atomic symbol rather than a number by preceding one of the digits with a slash, to make it into an alphabetic character. A parenthesized sequence of items such as atoms or parenthesized lists is read in as a list. The items may be seperated by spaces or commas. If a dot appears, it must be between the last two items, and a dotted pair or a list ending in an atom other than nil is created. Where there would be ambiguity between a dotted-pair or a decimal point, the decimal-point interpretation will be chosen, so dotted-pair dots should be surrounded by spaces. Thus (1.2) is different from (1 . 2). It is good practice to always put spaces around dotted- pair dots. In the future the reader may be changed to require this. A sequence of characters enclosed in double quotes (such as "foo") is read as a character string. If a quote is to be included in the string, two quotes must be written. The readtable may be set up so that certain characters are "single character objects." These characters read in as atomic symbols whose pname is the single character, without the benefit of delimiting spaces or commas. In the standard readtable there are no single character objects. Characters may be defined as macro characters. (See the setsyntax function.) When these characters are encountered by the reader, a special action defined by a LISP function is performed, unless, of course, the character is slashified. Two macro characters included in the standard readtable are ' and ;. 'x is equivalent to (quote x), similarly '(a b) is equivalent to (quote (a b)). The ; is used to introduce a comment: the semicolon and the rest of the line to the right of the semicolon are skipped over. Note that the specific characters used in all the constructions defined above are only the initial default characters for these constructions. Any other characters may be substituted by changing the readtable. See the setsyntax function.  file: LISPIO, node: Moby IO, previous: Input Format, up: Top, next: Top Source: lspman;ch13 > version of 1/6/75 This section describes how to use some of the peculiar I/O devices present on the MIT A.I. Lab pdp-10. The Display Slave The Display Slave runs on the pdp-6, if it is available, otherwise on the pdp-10. It displays pictures on the 340 display (or on a GT-40) under control of commands sent to it by certain LISP functions. The following conventions are used in the descriptions of these functions: x,y are assumed to be fixnum arguments to line drawing, point inserting, and other such functions. They represent coordinates. n is a fixnum argument whose meaning is described under the particular functions which use it. item is the numerical index or name of some display slave item, returned by discreate. bright each item has a brightness level associated with it, ranging between 1 and 8. The default is 8. scale each item has a scale, or magnification, factor associated with it. The scale factor ranges between 1 and 4. The default is 1. 2 doubles the length of drawn lines and the size of text; 3 quadruples; and 4 multiplies by 8. Text looks much nicer (on the 340) if drawn with a magnification of 2. flag is an indicator, which if nil specifies that a given action is to be undone, or if non-nil specifies that the given action is to be done. bsl is either nil indicating no change, or is a list (bright scale) specifying new values of these parameters for a given action. All numbers in this section are octal unless followed by a decimal point, in which case they are decimal. The display slave maintains a number of items, whose names are indicated by 'item' above. Each item has associated with it variables determining the brightness, scale, and visibility of points and lines in the item. Like the LOGO Turtle, we think of the item as having a "pen" which can be "down" so that a line is visible when the turtle is requested to move from one place to another, or "up" so that no visible mark is made. For the functions which affect brightness, scale, or the penup status, 0 generally means no change. Functions which take an optional 'bsl' argument, namely disapoint, discuss, and disaline, will treat it as a temporary setting for these values, and upon exit will restore them to their values prior to the call. The optional penup argument to disaline is similarly treated as temporary. Arguments that are intended to specify coordinates on the screen for the functions disaline, disapoint, and discuss are interpreted in one of four ways depending on the slave variable "astate," which can be set by disini. "astate" is not a lisp variable. 0 relative mode - the point specified is in relation to the "home" of the item on which the function is acting. 1 absolute mode - x and y are interpreted as direct screen coordinates, modulo 1024., with (0,0) at the lower left-hand corner. 2 incremental mode - the coordinates specified are relative to the current position of the pen of the item which is being acted upon. 3 polar mode - like incremental, but the x and y arguments, which must be flonums instead of fixnums, are considered as the radius and angle respectively in a polar coordinate system centered on the current pen position, with zero degrees being horizontal and to the right. NB: functions like discreate, dislocate, and dismotion, which specify an item's home, always take the coordinates of the home in absolute mode. To emphasize that the interpretation of x and y is controlled by astate, we will write astate(x,y) to mean the point specified by x and y. discreate LSUBR 0 or 2 args (discreate x y) creates a new display item with home at (x,y) on the screen. (discreate) creates one with home at (0,0). discreate returns the item number of the newly-created item, by which it may be referred to in later calls. disini LSUBR 0 or 1 args disini seizes and initializes the slave. If the user already has the slave (this is not the first disini), it is re-initialized. astate is set to the argument if there is one, provided it is 0, 1, 2, or 3. Otherwise astate is not changed. Initially astate is 0. The previous value of astate is returned. display SUBR 2 args (display item flag) makes the item visible or not depending on whether flag is t or nil. disflush LSUBR 0 or more args (disflush) flushes the slave. (disflush item item ... item) flushes the indicated items, i.e. deletes them from the slave's memory. dislocate SUBR 3 args (dislocate item x y) moves the item's home to (x,y). disblink SUBR 2 args (disblink item flag) makes item blink if flag is non-nil, stop blinking if flag is nil. discopy SUBR 1 arg (discopy item) makes a copy of item, and returns the new item, which has its home at the same location. dismark SUBR 2 args (dismark item n) if n = 0, removes marker from item. If n < 0, inserts standard marker on item. If n > 0, inserts display-item n as marker on item. discribe SUBR 1 arg (discribe item) returns a list of the parameters of item: (home-x, home-y, pen-pos-x, pen-pos-y, bright, scale, penup, marker) dischange SUBR 3 args (dischange item bright scale) adds bright and scale to the corresponding variables of item. dislink SUBR 3 args (dislink item-1 item-2 flag) links or unlinks item-1 to item-2 (links if flag non-nil, unlinks if flag nil.) item-2 is the "inferior" of item-1, and will be dislocated, dischanged, displayed, and disblinked whenever item-1 is. dislist LSUBR 0 or 1 args (dislist) returns a list of all items "on display," that is made visible by (display item t). (dislist item) returns a list of all inferiors of item. diset SUBR 3 args (diset item n bsl) sets the values for penup, brightness, and scale for the item. If n is -1, put pen down. If n is +1, lift pen. If n is 0, leave pen alone. Set bright and scale from bsl, as described above. disaline LSUBR 3 to 5 args (disaline item x y bsl n) sets penup, bright, and scale from bsl and n as in diset, then moves pen position to astate(x,y), leaving a visible line if the pen is down, and restore the item's penup, bright, and scale. The forms (disaline item x y), (disaline item x y n), and (disaline item x y bsl) are also allowed. The unspecified parameters are left unchanged. disapoint LSUBR 2 or 3 args (disapoint x y bsl) displays a point at astate(x,y) as part of u item. bsl is interpreted as by disaline, as a temporary setting of bright and scale. It may be omitted. discuss LSUBR 4 or 5 args (discuss item x y text bsl) processes bsl as disapoint does, then inserts the characters of text, as if princ'ed, into the item beginning at the point astate(x,y). bsl may be omitted. dismotion SUBR 4 args (dismotion item x y speed) causes item to be slowly dislocate'ed so that its home eventually becomes (x,y). If either x or y is negative the item is placed under control of spacewar console 1. The button returns control to the tty. [???] The argument speed is an inverse measure of the speed at which the item will move. speed = 0 is the maximum. disgorge SUBR 1 arg (disgorge item) creates a (gensym) atom, gives it an array property, and fills the array with the internal display code of item. disgobble SUBR 1 arg (disgobble array-name) takes the array named array-name and generates a display item from the internal display code in the array. Examples: A subroutine to draw a light box with a medium point inside it at the center of the screen. A description of the item is returned. ((lambda (oastate b) (disaline b -100 -100 1) ;go to lower left corner of box (diset b 0 (list 3 boxscale));set scale from global variable ;set bright but don't change penup (disaline b 0 200) ;draw box in incremental mode (disaline b 200 0) (disaline b 0 -200) (disaline b -200 0) (disini 0) ;go to relative mode to (disapoint b 0 0 '(6 0)) ;draw the point (disini oastate) ;restore astate (discribe b)) ;return value. (disini 2) ;enter with astate 2 (discreate 1000 1000)) ;and b set to this item. To add some text on top of the box, assuming astate = 0 and that b is the item as above: (discuss b -200 207 "here is the box - see the box" '(6 2)) To move the box b right 100 units: (setq foo (discribe b)) (setq foo (list (car foo) (cadr foo))) (dislocate b (+ 100 (car foo)) (cadr foo)) To put a cross where the pen is now, and some text where it used to be before it was moved: (dismark b -1) (discuss b (caddr foo) (cadddr foo) "turtle slept here")) To brighten the box and point (but text is already brightest, so it does not change): (dischange b 2 0) To get rid of the box: (disflush b) To get rid of the slave: (disflush) The display slave is also available in the Multics implementation of MACLISP, in a somewhat different form. The Multics Graphics System is used so the "display" can be any device. The setup_graphics command must be used to specify what device is to be used. The Multics display slave is not part of the initial LISP environment. It must be loaded in. (As of this writing, 19 December 1974, the Multics display slave is actually not yet available. However it is expected to be finished soon.) Blinking is simulated by the use of dotted lines. dismotion is not implemented unless the graphic device supports the "animation" feature of the Multics Graphics System. The graphic data does not actually appear until (disgo) is evaluated, and the display will be redrawn from the beginning each time (disgo) is used. The Multics display slave accepts both fixnums and flonums as coordinates. The display slave consists of a set of LISP functions which are autoloaded in when disini is first called. Arms, Hands, and Eyes TO BE SUPPLIED