[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33. "The I/O System"

.setq io-chapter chapter-number Zetalisp provides a powerful and flexible system for performing input and output to peripheral devices. To allow device independent I/O (that is, to allow programs to be written in a general way so that the program's input and output may be connected with any device), the Zetalisp I/O system provides the concept of an "I/O stream". What streams are, the way they work, and the functions to create and manipulate streams, are described in this chapter. This chapter also describes the Lisp "I/O" operations read and print, and the printed representation they use for Lisp objects.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.1 "The Character Set"

.setq character-set section-page

Zetalisp represents characters as fixnums. The Lisp Machine's mapping between these numbers and the characters is listed here. The mapping is similar to ASCII, but somewhat modified to allow the use of the so-called SAIL extended graphics, while avoiding certain ambiguities present in ITS. For a long time ITS treated the Backspace, Control-H, and Lambda keys on the keyboard identically as character code 10 octal; this problem is avoided from the start in the Lisp Machine's mapping.

It is worth pointing out that although the Zetalisp character set is different from the pdp-10 character set, when files are transferred between Lisp Machines and pdp-10's the characters are automatically converted. Details of the mapping are explained below.

Fundamental characters are eight bits wide. Those less than 200 octal (with the 200 bit off) and only those are printing graphics; when output to a device they are assumed to print a character and move the "cursor" one character position to the right. (All software provides for variable-width fonts, so the term "character position" shouldn't be taken too literally.)

Characters in the range of 200 to 236 inclusive are used for special characters. Character 200 is a "null character", which does not correspond to any key on the keyboard. The null character is not used for anything much; fasload uses it internally. Characters 201 through 236 correspond to the special function keys on the keyboard such as Return and Call. The remaining characters are reserved for future expansion.

It should never be necessary for a user or a source program to know these numerical values. Indeed, they are likely to be changed in the future. There are symbolic names for all characters; see below.

Most of the special characters do not normally appear in files (although it is not forbidden for files to contain them). These characters exist mainly to be used as "commands" from the keyboard.

A few special characters, however, are "format effectors" which are just as legitimate as printing characters in text files. The names and meanings of these characters are:

Return
The "carriage return" character which separates lines of text. Note that the pdp-10 convention that lines are ended by a pair of characters, "carriage return" and "line feed", is not used.

Page
The "page separator" character which separates pages of text.

Tab
The "tabulation" character which spaces to the right until the next "tab stop". Tab stops are normally every 8 character positions.

The space character is considered to be a printing character whose printed image happens to be blank, rather than a format effector.

In some contexts, a fixnum can hold both a character code and a font number for that character. The following byte specifiers are defined:

Variable: %%ch-char
The value of %%ch-char is a byte specifier for the field of a fixnum character which holds the character code.

Variable: %%ch-font
The value of %%ch-font is a byte specifier for the field of a fixnum character which holds the font number.

Characters read in from the keyboard include a character code and control bits. A character cannot contain both a font number and control bits, since these data are both stored in the same bits. The following byte specifiers are provided: .setq %%kbd page

Variable: %%kbd-char
The value of %%kbd-char is a byte specifier for the field of a keyboard character which holds the normal eight-bit character code.

Variable: %%kbd-control
The value of %%kbd-control is a byte specifier for the field of a keyboard character which is 1 if either Control key was held down.

Variable: %%kbd-meta
The value of %%kbd-meta is a byte specifier for the field of a keyboard character which is 1 if either Meta key was held down.

Variable: %%kbd-super
The value of %%kbd-super is a byte specifier for the field of a keyboard character which is 1 if either Super key was held down.

Variable: %%kbd-hyper
The value of %%kbd-hyper is a byte specifier for the field of a keyboard character which is 1 if either Hyper key was held down.

This bit is also set if Control and/or Meta is typed in combination with Shift and a letter. Shift is much easier than Hyper to reach with the left hand.

Variable: %%kbd-control-meta
The value of %%kbd-control-meta is a byte specifier for the four-bit field of a keyboard character which contains the above control bits. The least-significant bit is Control. The most significant bit is Hyper.

The following fields are used by some programs that encode signals from the mouse in a the format of a character. Refer to the window system documentation for an explanation of how these characters are generated.

Variable: %%kbd-mouse
The value of %%kbd-mouse is a byte specifier for the bit in a keyboard character which indicates that the character is not really a character, but a signal from the mouse.

Variable: %%kbd-mouse-button
The value of %%kbd-mouse-button is a byte specifier for the field in a mouse signal which says which button was clicked. The value is 0, 1, or 2 for the left, middle, or right button, respectively.

Variable: %%kbd-mouse-n-clicks
The value of %%kbd-mouse-n-clicks is a byte specifier for the field in a mouse signal which says how many times the button was clicked. The value is one less than the number of times the button was clicked.

When any of the control bits (Control, Meta, Super, or Hyper) is set in conjunction with a letter, the letter will always be upper-case. The character codes which consist of a lower-case letter and non-zero control bits are "holes" in the character set which are never used for anything. Note that when Shift is typed in conjuction with Control and/or Meta and a letter, it means Hyper rather than Shift.

Since the control bits are not part of the fundamental 8-bit character codes, there is no way to express keyboard input in terms of simple character codes. However, there is a convention which the relevant programs accept for encoding keyboard input into a string of characters: if a character has its Control bit on, prefix it with an Alpha. If a character has its Meta bit on, prefix it with a Beta. If a character has both its Control and Meta bits on, prefix it with an Epsilon. If a character has its Super bit on, prefix it with a Pi. If a character has its Hyper bit on, prefix it with a Lambda. To get an Alpha, Beta, Epsilon, Pi, Lambda, or Equivalence into the string, quote it by prefixing it with an Equivalence.

.setq character-set-differences page

When characters are written to a file server computer that normally uses the ASCII character set to store text, Lisp Machine characters are mapped into an encoding that is reasonably close to an ASCII transliteration of the text. When a file is written, the characters are converted into this encoding, and the inverse transformation is done when a file is read back. No information is lost. Note that the length of a file, in characters, will not be the same measured in original Lisp Machine characters as it will measured in the encoded ASCII characters. In the currently implemented ASCII file servers, the following encoding is used. All printing characters and any characters not mentioned explicitly here are represented as themselves. Codes 010 (lambda), 011 (gamma), 012 (delta), 014 (plus-minus), 015 (circle-plus), 177 (integral), 200 through 207 inclusive, 213 (delete/vt), and 216 and anything higher, are preceeded by a 177; that is, 177 is used as a "quoting character" for these codes. Codes 210 (overstrike), 211 (tab), 212 (line), and 214 (page), are converted to their ASCII cognates, namely 010 (backspace), 011 (horizontal tab), 012 (line feed), and 014 (form feed) respectively. Code 215 (return) is converted into 015 (carriage return) followed by 012 (line feed). Code 377 is ignored completely, and so cannot be stored in files. 7 .group

 
000 center-dot ()             040 space       100 @           140 `
001 down arrow ()             041 !           101 A           141 a
002 alpha ()                  042 "           102 B           142 b
003 beta ()                   043 #           103 C           143 c
004 and-sign ()               044 $           104 D           144 d
005 not-sign ()               045 %           105 E           145 e
006 epsilon ()                046 &           106 F           146 f
007 pi ()                     047 '           107 G           147 g
010 lambda ((ctl-h))                 050 (           110 H           150 h
011 gamma (	)                  051 )           111 I           151 i
012 delta (
)                  052 *           112 J           152 j
013 uparrow ()                053 +           113 K           153 k
014 plus-minus ()             054 ,           114 L           154 l
015 circle-plus ((ctl-m))            055 -           115 M           155 m
016 infinity ()               056 .           116 N           156 n
017 partial delta ()          057 /           117 O           157 o
020 left horseshoe ()         060 0           120 P           160 p
021 right horseshoe ()        061 1           121 Q           161 q
022 up horseshoe ()           062 2           122 R           162 r
023 down horseshoe ()         063 3           123 S           163 s
024 universal quantifier ()   064 4           124 T           164 t
025 existential quantifier () 065 5           125 U           165 u
026 circle-X ()               066 6           126 V           166 v
027 double-arrow ()           067 7           127 W           167 w
030 left arrow ()             070 8           130 X           170 x
031 right arrow ()            071 9           131 Y           171 y
032 not-equals ()             072 :           132 Z           172 z
033 diamond (altmode) ()      073 ;           133 [           173 {
034 less-or-equal ()          074 <           134 \           174 |
035 greater-or-equal ()       075 =           135 ]           175 }
036 equivalence ()            076 >           136 ^           176 ~
037 or ()                     077 ?           137 _           177 (ctl-qm)
200 null character     210 overstrike    220 stop-output   230 roman-iv
201 break              211 tab           221 abort         231 hand-up
202 clear              212 line          222 resume        232 hand-down
203 call               213 delete/vt     223 status        233 hand-left
204 terminal escape    214 page          224 end           234 hand-right
205 macro/backnext     215 return        225 roman-i       235 system
206 help               216 quote         226 roman-ii      236 network
207 rubout             217 hold-output   227 roman-iii
237-377 reserved for the future


                    The Lisp Machine Character Set


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2 "Printed Representation"

People cannot deal directly with Lisp objects, because the objects live inside the machine. In order to let us get at and talk about Lisp objects, Lisp provides a representation of objects in the form of printed text; this is called the printed representation. This is what you have been seeing in the examples throughout this manual. Functions such as print, prin1, and princ take a Lisp object, and send the characters of its printed representation to a stream. These functions (and the internal functions they call) are known as the printer. The read function takes characters from a stream, interprets them as a printed representation of a Lisp object, builds a corresponding object and returns it; it and its subfunctions are known as the reader. (Streams are explained in (streams).)

This section describes in detail what the printed representation is for any Lisp object, and just what read does. For the rest of the chapter, the phrase "printed representation" will usually be abbreviated as "p.r.".


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2.1 "What the Printer Produces"

.setq printer section-page The printed representation of an object depends on its type. In this section, we will consider each type of object and explain how it is printed.

.setq slashification page Printing is done either with or without slashification. The non-slashified version is nicer looking in general, but if you give it to read it won't do the right thing. The slashified version is carefully set up so that read will be able to read it in. The primary effects of slashification are that special characters used with other than their normal meanings (e.g. a parenthesis appearing in the name of a symbol) are preceeded by slashes or cause the name of the symbol to be enclosed in vertical bars, and that symbols which are not from the current package get printed out with their package prefixes (a package prefix looks like a symbol followed by a colon).

For a fixnum or a bignum: if the number is negative, the printed representation begins with a minus sign ("-"). Then, the value of the variable base is examined. If base is a positive fixnum, the number is printed out in that base (base defaults to 8); if it is a symbol with a si:princ-function property, the value of the property will be applied to two arguments: minus of the number to be printed, and the stream to which to print it (this is a hook to allow output in Roman numerals and the like); otherwise the value of base is invalid and an error is signalled Finally, if base equals 10. and the variable *nopoint is nil, a decimal point is printed out. Slashification does not affect the printing of numbers.

Variable: base
The value of base is a number which is the radix in which fixnums are printed, or a symbol with a si:princ-function property. The initial value of base is 8.

Variable: *nopoint
If the value of *nopoint is nil, a trailing decimal point is printed when a fixnum is printed out in base 10. This allows the numbers to be read back in correctly even if ibase is not 10. at the time of reading. If *nopoint is non-nil, the trailing decimal points are suppressed. The initial value of *nopoint is nil.

For a flonum: the printer first decides whether to use ordinary notation or exponential notation. If the magnitude of the number is too large or too small, such that the ordinary notation would require an unreasonable number of leading or trailing zeroes, then exponential notation will be used. The number is printed as an optional leading minus sign, one or more digits, a decimal point, one or more digits, and an optional trailing exponent, consisting of the letter "e", an optional minus sign, and the power of ten. The number of digits printed is the "correct" number; no information present in the flonum is lost, and no extra trailing digits are printed that do not represent information in the flonum. Feeding the p.r. of a flonum back to the reader is always supposed to produce an equal flonum. Flonums are always printed in decimal; they are not affected by slashification nor by base and *nopoint.

For a small flonum: the printed representation is very similar to that of a flonum, except that exponential notation is always used and the exponent is delimited by "s" rather than "e".

For a symbol: if slashification is off, the p.r. is simply the successive characters of the print-name of the symbol. If slashification is on, two changes must be made. First, the symbol might require a package prefix in order that read work correctly, assuming that the package into which read will read the symbol is the one in which it is being printed. See the section on packages ((package)) for an explanation of the package name prefix. Secondly, if the p.r. would not read in as a symbol at all (that is, if the print-name looks like a number, or contains special characters), then the p.r. must have some quoting for those characters, either by the use of slashes ("/") before each special character, or by the use of vertical bars ("|") around the whole name. The decision whether quoting is required is done using the readtable (see (readtable)), so it is always accurate provided that readtable has the same value when the output is read back in as when it was printed.

For a string: if slashification is off, the p.r. is simply the successive characters of the string. If slashification is on, the string is printed between double quotes, and any characters inside the string which need to be preceeded by slashes will be. Normally these are just double-quote and slash. Compatibly with Maclisp, carriage return is not ignored inside strings and vertical bars.

For an instance or an entity: if the object has a method for the :print-self message, that message is sent with three arguments: the stream to print to, the current depth of list structure (see below), and whether slashification is enabled. The object should print a suitable p.r. on the stream. See (flavor) for documentation on instances. Most such objects print like "any other data type" below, except with additional information such as a name. Some objects print only their name when slashification is not in effect (when princ'ed).

For an array which is a named structure: if the array has a named structure symbol with a named-structure-invoke property which is the name of a function, then that function is called on five arguments: the symbol :print-self, the object itself, the stream to print to, the current depth of list structure (see below), and whether slashification is enabled. A suitable printed representation should be sent to the stream. This allows a user to define his own p.r. for his named structures; more information can be found in the named structure section (see (named-structure)). If the named structure symbol does not have a named-structure-invoke property, the printed-representation is like that for random data-types: a number sign and a less than sign, the named structure symbol, the numerical address of the array, and a greater than sign.

Other arrays: the p.r. starts with a number sign and a less-than sign. Then the "art-" symbol for the array type is printed. Next the dimensions of the array are printed, separated by hyphens. This is followed by a space, the machine address of the array, and a greater-than sign.

Conses: The p.r. for conses tends to favor lists. It starts with an open-parenthesis. Then, the car of the cons is printed, and the cdr of the cons is examined. If it is nil, a close parenthesis is printed. If it is anything else but a cons, space dot space followed by that object is printed. If it is a cons, we print a space and start all over (from the point after we printed the open-parenthesis) using this new cons. Thus, a list is printed as an open-parenthesis, the p.r.'s of its elements separated by spaces, and a close-parenthesis.

This is how the usual printed representations such as (a b (foo bar) c) are produced.

The following additional feature is provided for the p.r. of conses: as a list is printed, print maintains the length of the list so far, and the depth of recursion of printing lists. If the length exceeds the value of the variable prinlength, print will terminate the printed representation of the list with an ellipsis (three periods) and a close-parenthesis. If the depth of recursion exceeds the value of the variable prinlevel, then the list will be printed as "**". These two features allow a kind of abbreviated printing which is more concise and suppresses detail. Of course, neither the ellipsis nor the "**" can be interpreted by read, since the relevant information is lost.

Variable: prinlevel
prinlevel can be set to the maximum number of nested lists that can be printed before the printer will give up and just print 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.

Variable: prinlength
prinlength can be set to the maximum number of elements of a list that will be printed before the printer will give up and print a "...". If it is nil, which it is initially, any length list may be printed. Otherwise, the value of prinlength must be a fixnum.

For any other data type: the p.r. starts with a number sign and a less-than sign ("<"), the "dtp-" symbol for this datatype, a space, and the octal machine address of the object. Then, if the object is a microcoded function, compiled function, or stack group, its name is printed. Finally a greater-than sign (">") is printed.

Including the machine address in the p.r. makes it possible to tell two objects of this kind apart without explicitly calling eq on them. This can be very useful during debugging. It is important to know that if garbage collection is turned on, objects will occasionally be moved, and therefore their octal machine addresses will be changed. It is best to shut off garbage collection temporarily when depending on these numbers.

None of the p.r.'s beginning with a number sign can be read back in, nor, in general, can anything produced by instances, entities, and named structures. (Just what read accepts is the topic of the next section.) This can be a problem if, for example, you are printing a structure into a file with the intent of reading it in later. The following feature allows you to make sure that what you are printing may indeed be read with the reader.

Variable: si:print-readably
When si:print-readably is bound to t, the printer will signal an error if there is an attempt to print an object which cannot be interpreted by read. When the printer sends a :print-self or a :print message, it assumes that this error checking is done for it. Thus it is possible for these messages not to signal an error, if they see fit.

Macro: si:printing-random-object (object stream . keywords) &body body
The vast majority of objects which define :print-self messages have much in common. This macro is provided for convenience, so that users do not have to write out that repetitious code. It is also the preferred interface to si:print-readably. With no keywords, si:printing-random-object checks the value of si:print-readably and signals an error if it is not nil. It then prints a number sign and a less than sign, evaluates the forms in body, then prints a space, the octal machine address of the object and a greater-than sign. A typical use of this macro might look like:
 
(si:printing-random-object (ship stream)
  (princ (typep ship) stream)
  (tyo #\space stream)
  (prin1 (ship-name ship) stream))
This might print #<ship "ralph" 23655126>.

The following keywords may be used to modify the behaviour of si:printing-random-object:

.kitem :no-pointer This supresses printing of the octal address of the object. .kitem :typep This prints the result of (typep object) after the less-than sign. In the example above, this option could have been used instead of the first two forms in the body.

.setq customizing-the-printer section-page

If you want to control the printed representation of some object, usually the right way to do it is to make the object an array which is a named structure (see (named-structure)), or an instance of a flavor (see (flavor)). However, occasionally it is desirable to get control over all printing of objects, in order to change, in some way, how they are printed. If you need to do this, the best way to proceed is to customize the behavior of si:print-object (see (si:print-object-fun)), which is the main internal function of the printer. All of the printing functions, such as print and princ, as well as format, go through this function. The way to customize it is by using the "advice" facility (see (advise)).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2.2 "What The Reader Accepts"

.setq reader section-page The purpose of the reader is to accept characters, interpret them as the p.r. of a Lisp object, and return a corresponding Lisp object. The reader cannot accept everything that the printer produces; for example, the p.r.'s of arrays (other than strings), compiled code objects, closures, stack groups etc. cannot be read in. However, it has many features which are not seen in the printer at all, such as more flexibility, comments, and convenient abbreviations for frequently-used unwieldy constructs.

This section shows what kind of p.r.'s the reader understands, and explains the readtable, reader macros, and various features provided by read.

In general, the reader operates by recognizing tokens in the input stream. Tokens can be self-delimiting or can be separated by delimiters such as whitespace. A token is the p.r. of an atomic object such as a symbol or a number, or a special character such as a parenthesis. The reader reads one or more tokens until the complete p.r. of an object has been seen, and then constructs and returns that object.

The reader understands the p.r.'s of fixnums in a way more general than is employed by the printer. Here is a complete description of the format for fixnums.

Let a simple fixnum be a string of digits, optionally preceeded by a plus sign or a minus sign, and optionally followed by a trailing decimal point. A simple fixnum will be interpreted by read as a fixnum. If the trailing decimal point is present, the digits will be interpreted in decimal radix; otherwise, they will be considered as a number whose radix is the value of the variable ibase.

Variable: ibase
The value of ibase is a number which is the radix in which fixnums are read. The initial value of ibase is 8.

read will also understand a simple fixnum, followed by an underscore ("_") or a circumflex ("^"), followed by another simple fixnum. The two simple fixnums will be interpreted in the usual way, then the character in between indicates an operation to be performed on the two fixnums. The underscore indicates a binary "left shift"; that is, the fixnum to its left is doubled the number of times indicated by the fixnum to its right. The circumflex multiplies the fixnum to its left by ibase the number of times indicated by the fixnum to its right. (The second simple fixnum is not allowed to have a leading minus sign.) Examples: 645_6 means 64500 (in octal) and 645^3 means 645000. Here are some examples of valid representations of fixnums to be given to read:
 
4
23456.
-546
+45^+6
2_11

The syntax for bignums is identical to the syntax for fixnums. A number is a bignum rather than a fixnum if and only if it is too large to be represented as a fixnum. Here are some examples of valid representations of bignums:
 
72361356126536125376512375126535123712635
-123456789.
105_1000
105_1000.

.setq flonum-examples page The syntax for a flonum is an optional plus or minus sign, optionally some digits, a decimal point, and one or more digits. Such a flonum or a simple fixnum, followed by an "e" (or "E") and a simple fixnum, is also a flonum; the fixnum after the "e" is the exponent of 10 by which the number is to be scaled. (The exponent is not allowed to have a trailing decimal point.) If the exponent is introduced by "s" (or "S") rather than "e", the number is a small-flonum. Here are some examples of printed-representations that read as flonums:
 
0.0
1.5
14.0
0.01
.707
-.3
+3.14159
6.03e23
1E-9
1.e3

Here are some examples of printed-representations that read as small-flonums:
 
0s0
1.5s9
-42S3
1.s5

A string of letters, numbers, and "extended alphabetic" characters is recognized by the reader as a symbol, provided it cannot be interpreted as a number. Alphabetic case is ignored in symbols; lower-case letters are translated to upper-case. When the reader sees the p.r. of a symbol, it interns it on a package (see (package) for an explanation of interning and the package system). Symbols may start with digits; you could even have one named "-345T"; read will accept this as a symbol without complaint. If you want to put strange characters (such as lower-case letters, parentheses, or reader macro characters) inside the name of a symbol, put a slash before each strange character. If you want to have a symbol whose print-name looks like a number, put a slash before some character in the name. You can also enclose the name of a symbol in vertical bars, which quotes all characters inside, except vertical bars and slashes, which must be quoted with slash.
 
Examples of symbols:
foo
bar/(baz/)
34w23
|Frob Sale|

The reader will also recognize strings, which should be surrounded by double-quotes. If you want to put a double-quote or a slash inside a string, preceed it by a slash.
 
Examples of strings:
"This is a typical string."
"That is known as a /"cons cell/" in Lisp."

When read sees an open parenthesis, it knows that the p.r. of a cons is coming, and calls itself recursively to get the elements of the cons or the list that follows. Any of the following are valid:
 
(foo . bar)
(foo bar baz)
(foo . (bar . (baz . nil)))
(foo bar . quux)
The first is a cons, whose car and cdr are both symbols. The second is a list, and the third is exactly the same as the second (although print would never produce it). The fourth is a "dotted list"; the cdr of the last cons cell (the second one) is not nil, but quux.

Whenever the reader sees any of the above, it creates new cons cells; it never returns existing list structure. This contrasts with the case for symbols, as very often read returns symbols that it found interned in the package rather than creating new symbols itself. Symbols are the only thing that work this way.

The dot that separates the two elements of a dotted-pair p.r. for a cons is only recognized if it is surrounded by delimiters (typically spaces). Thus dot may be freely used within print-names of symbols and within numbers. This is not compatible with Maclisp; in Maclisp (a.b) reads as a cons of symbols a and b, whereas in Zetalisp it reads as a list of a symbol a.b.

If the circle-X (7"") character is encountered, it is an octal escape, which may be useful for including weird characters in the input. The next three characters are read and interpreted as an octal number, and the character whose code is that number replaces the circle-X and the digits in the input stream. This character is always taken to be an alphabetic character, just as if it had been preceded by a slash.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2.3 "Macro Characters"

Certain characters are defined to be macro characters. When the reader sees one of these, it calls a function associated with the character. This function reads whatever syntax it likes and returns the object represented by that syntax. Macro characters are always token delimiters; however, they are not recognized when quoted by slash or vertical bar, nor when inside a string. Macro characters are a syntax-extension mechanism available to the user. Lisp comes with several predefined macro characters:

Quote (') is an abbreviation to make it easier to put constants in programs. 'foo reads the same as (quote foo).

Semicolon (;) is used to enter comments. The semicolon and everything up through the next carriage return are ignored. Thus a comment can be put at the end of any line without affecting the reader.

Backquote (`) makes it easier to write programs to construct lists and trees by using a template. See (backquote) for details.

Comma (,) is part of the syntax of backquote and is invalid if used other than inside the body of a backquote. See (backquote) for details.

Sharp sign (#) introduces a number of other syntax extensions. See the following section. Unlike the preceding characters, sharp sign is not a delimiter. A sharp sign in the middle of a symbol is an ordinary character.

The function set-syntax-macro-char (see (set-syntax-macro-char-fun)) can be used to define your own macro characters.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2.4 "Sharp-sign Abbreviations"

The reader's syntax includes several abbreviations introduced by sharp sign (#). These take the general form of a sharp sign, a second character which identifies the syntax, and following arguments. Certain abbreviations allow a decimal number or certain special "modifier" characters between the sharp sign and the second character. Here are the currently-defined sharp sign constructs; more are likely to be added in the future.

.setq sharp-slash page
#/
#/x reads in as the number which is the character code for the character x. For example, #/a is equivalent to 141 but clearer in its intent. This is the recommended way to include character constants in your code. Note that the slash causes this construct to be parsed correctly by the editors, Emacs and Zwei.

As in strings, upper and lower-case letters are distinguished after #/. Any character works after #/, even those that are normally special to read, such as parentheses. Even non-printing characters may be used, although for them #\ is preferred.

The character can be modified with control and meta bits by inserting one or more special characters between the 7# and the 7/. This syntax is obsolete since it is not mnemonic and it generally unclear; it is superseded by the \# syntax (see below). However, it is used in some old programs, so here is how it is defined. 7#/x generates Control-x. 7#/x generates Meta-x. 7#/x generates Super-x. 7#(ctl-h)/x generates Hyper-x. These can be combined, for instance 7#/& generates Super-Meta-ampersand. Also, 7#/x is an abbreviation for 7#/x. When control bits are specified, and x is a lower-case alphabetic character, the character code for the upper-case version of the character is produced.

#\
#\name reads in as the number which is the character code for the non-printing character symbolized by name. A large number of character names are recognized; these are documented below ((xr-special-character-names)). For example, #\return reads in as a fixnum, being the character code for the "return" character in the Lisp Machine character set. In general, the names that are written on the keyboard keys are accepted. The abbreviations cr for return and sp for space are accepted and generally preferred, since these characters are used so frequently. The page separator character is called page, although form and clear-screen are also accepted since the keyboard has one of those legends on the page key. The rules for reading name are the same as those for symbols; thus upper and lower-case letters are not distinguished, and the name must be terminated by a delimiter such as a space, a carriage return, or a parenthesis.

When the system types out the name of a special character, it uses the same table as the #\ reader; therefore any character name typed out is acceptable as input.

#\ can also be used to read in the names of characters that have control and meta bits set. The syntax looks like #\control-meta-b to get a "B" character with the control and meta bits set. You can use any of the prefix bit names control, meta, hyper, and super. They may be in any order, and upper and lower-case letters are not distinguished. Also, control may be spelled ctrl as it is on the keyboards. The last hyphen may be followed by a single character, or by any of the special character names normally recognized by #\. If it is a single character, it is treated the same way the reader normally treats characters in symbols; if you want to use a lower-case character or a special character such as a parenthesis, you must preceed it by a slash character. Examples: #\Hyper-Super-A, \meta-hyper-roman-i, #\CTRL-META-/(.

The character can also be modified with control and meta bits by inserting special Greek characters as with 7#/, but this is less clear than spelling them out, and should be avoided in new programs.

#^
#^x is exactly like 7#/x if the input is being read by Zetalisp; it generates Control-x. In Maclisp x is converted to upper case and then exclusive-or'ed with 100 (octal). Thus #^x always generates the character returned by tyi if the user holds down the control key and types x. (In Maclisp 7#/x sets the bit set by the Control key when the TTY is open in fixnum mode.)

#'
#'foo is an abbreviation for (function foo). foo is the p.r. of any object. This abbreviation can be remembered by analogy with the ' macro-character, since the function and quote special forms are somewhat analogous.

#,
#,foo evaluates foo (the p.r. of a Lisp form) at read time, unless the compiler is doing the reading, in which case it is arranged that foo will be evaluated when the QFASL file is loaded. This is a way, for example, to include in your code complex list-structure constants which cannot be written with quote. Note that the reader does not put quote around the result of the evaluation. You must do this yourself if you want it, typically by using the ' macro-character. An example of a case where you do not want quote around it is when this object is an element of a constant list.

#.
#.foo evaluates foo (the p.r. of a lisp form) at read time, regardless of who is doing the reading.

#O
#O number reads number in octal regardless of the setting of ibase. Actually, any expression can be prefixed by #O; it will be read with ibase bound to 8.

#X
#X number reads number in radix 16. (hexadecimal) regardless of the setting of ibase. As with #O, any expression can be prefixed by #X. .br [Unfortunately #X does not completely work, currently, since it does not cause the letters A through F to be recognized as numbers. This does not seem to have bothered anyone yet.]

#R
#radixR number reads number in radix radix regardless of the setting of ibase. As with #O, any expression can be prefixed by #radixR; it will be read with ibase bound to radix. radix must consist of only digits, and it is read in decimal.

For example, #3R102 is another way of writing 11. and #11R32 is another way of writing 35. Bases larger than ten do not work completely, since there are only ten digit characters.

#Q
#Q foo reads as foo if the input is being read by Zetalisp, otherwise it reads as nothing (whitespace).

#M
#M foo reads as foo if the input is being read into Maclisp, otherwise it reads as nothing (whitespace).

#N
#N foo reads as foo if the input is being read into NIL or compiled to run in NIL, otherwise it reads as nothing (white space). Also, during the reading of foo, the reader temporarily defines various NIL-compatible sharp-sign abbreviations (such as #! and #") in order to parse the form correctly, even though its not going to be evaluated.

#+
@setq sharp-plus page This abbreviation provides a read-time conditionalization facility similar to, but more general than, that provided by #M, #N, and #Q. It is used as #+feature form. If feature is a symbol, then this is read as form if (status feature feature) is t. If (status feature feature) is nil, then this is read as whitespace. Alternately, feature may be a boolean expression composed of and, or, and not operators and symbols representing items which may appear on the (status features) list. (or lispm amber) represents evaluation of the predicate (or (status feature lispm) (status feature amber)) in the read-time environment.

For example, #+lispm form makes form exist if being read by Zetalisp, and is thus equivalent to #Q form. Similarly, #+maclisp form is equivalent to #M form. #+(or lispm nil) form will make form exist on either Zetalisp or in NIL. Note that items may be added to the (status features) list by means of (sstatus feature feature), thus allowing the user to selectively interpret or compile pieces of code by parameterizing this list. See (sstatus-fun).

#-
#-feature form is equivalent to #+(not feature) form.

#<
This is not legal reader syntax. It is used in the p.r. of objects which cannot be read back in. Attempting to read a #< will cause an error.

The function set-syntax-#-macro-char (see (set-syntax-#-macro-char-fun)) can be used to define your own sharp sign abbreviations.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2.5 Special Character Names

.setq xr-special-character-names section-page

The following are the recognized special character names, in alphabetical order except with synonyms together and linked with equal signs. These names can be used after a "#\" to get the character code for that character. Most of these characters type out as this name enclosed in a lozenge. First we list the special function keys.
 
abort		break		call		clear-input=clear
delete=vt		end		hand-down	hand-left
hand-right	hand-up		help		hold-output
roman-i		roman-ii		roman-iii		roman-iv
line=lf		macro=back-next	network
overstrike=backspace=bs		page=clear-screen=form
quote		resume		return=cr		rubout
space=sp		status		stop-output	system
tab		terminal=esc

These are printing characters which also have special names because they may be hard to type on a pdp-10.
 
altmode		circle-plus	delta		gamma
integral		lambda		plus-minus	uparrow

The following are special characters sometimes used to represent single and double mouse clicks. The buttons can be called either l, m, r or 1, 2, 3 depending on stylistic preference. These characters all contain the %%kbd-mouse bit.
 
mouse-l-1=mouse-1-1		mouse-l-2=mouse-1-2
mouse-m-1=mouse-2-1		mouse-m-2=mouse-2-2
mouse-r-1=mouse-3-1		mouse-r-2=mouse-3-2


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.2.6 "The Readtable"

.setq readtable section-page

There is a data structure called the readtable which is used to control the reader. It contains information about the syntax of each character. Initially it is set up to give the standard Lisp meanings to all the characters, but the user can change the meanings of characters to alter and customize the syntax of characters. It is also possible to have several readtables describing different syntaxes and to switch from one to another by binding the symbol readtable.

Variable: readtable
The value of readtable is the current readtable. This starts out as the initial standard readtable. You can bind this variable to temporarily change the readtable being used.

Variable: si:initial-readtable
The value of si:initial-readtable is the initial standard readtable. You should not ever change the contents of this readtable; only examine it, by using it as the from-readtable argument to copy-readtable or set-syntax-from-char.

The user can program the reader by changing the readtable in any of three ways. The syntax of a character can be set to one of several predefined possibilities. A character can be made into a macro character, whose interpretation is controlled by a user-supplied function which is called when the character is read. The user can create a completely new readtable, using the readtable compiler (sys: io; rtc) to define new kinds of syntax and to assign syntax classes to characters. Use of the readtable compiler is not documented here.

Function: copy-readtable &optional from-readtable to-readtable
from-readtable, which defaults to the current readtable, is copied. If to-readtable is unsupplied or nil, a fresh copy is made. Otherwise to-readtable is clobbered with the copy. Use copy-readtable to get a private readtable before using the following functions to change the syntax of characters in it. The value of readtable at the start of a Lisp Machine session is the initial standard readtable, which usually should not be modified.

Function: set-syntax-from-char to-char from-char &optional to-readtable from-readtable
Makes the syntax of to-char in to-readtable be the same as the syntax of from-char in from-readtable. to-readtable defaults to the current readtable, and from-readtable defaults to the initial standard readtable.

Function: set-character-translation from-char to-char &optional readtable
Changes readtable so that from-char will be translated to to-char upon read-in, when readtable is the current readtable. This is normally used only for translating lower case letters to upper case. Character translations are turned off by slash, string quotes, and vertical bars. readtable defaults to the current readtable.

Function: set-syntax-macro-char char function &optional readtable
Changes readtable so that char is a macro character. When char is read, function is called. readtable defaults to the current readtable.

function is called with two arguments: list-so-far and the input stream. When a list is being read, list-so-far is that list (nil if this is the first element). At the "top level" of read, list-so-far is the symbol :toplevel. After a dotted-pair dot, list-so-far is the symbol :after-dot. function may read any number of characters from the input stream and process them however it likes.

function should return three values, called thing, type, and splice-p. thing is the object read. If splice-p is nil, thing is the result. If splice-p is non-nil, then when reading a list thing replaces the list being read--often it will be list-so-far with something else nconc'ed onto the end. At top-level and after a dot if splice-p is non-nil the thing is ignored and the macro-character does not contribute anything to the result of read. type is a historical artifact and is not really used; nil is a safe value. Most macro character functions return just one value and let the other two default to nil.

function should not have any side-effects other than on the stream and list-so-far. Because of the way the rubout-handler works, function can be called several times during the reading of a single expression in which the macro character only appears once.

char is given the same syntax that single-quote, backquote, and comma have in the initial readtable (it is called :macro syntax).

Function: set-syntax-#-macro-char char function &optional readtable
Causes function to be called when #char is read. readtable defaults to the current readtable. The function's arguments and return values are the same as for normal macro characters, documented above. When function is called, the special variable si:xr-sharp-argument contains nil or a number which is the number or special bits between the # and char.

Function: set-syntax-from-description char description &optional readtable
Sets the syntax of char in readtable to be that described by the symbol description. The following descriptions are defined in the standard readtable:

si:alphabetic
An ordinary character such as "A".
si:break
A token separator such as "(". (Obviously left parenthesis has other properties besides being a break.
si:whitespace
A token separator which can be ignored, such as " ".
si:single
A self-delimiting single-character symbol. The initial readtable does not contain any of these.
si:slash
The character quoter. In the initial readtable this is "/".
si:verticalbar
The symbol print-name quoter. In the initial readtable this is "|".
si:doublequote
The string quoter. In the initial readtable this is `"'.
si:macro
A macro character. Don't use this, use set-syntax-macro-char.
si:circlecross
The octal escape for special characters. In the initial readtable this is "".

These symbols will probably be moved to the standard keyword package at some point. readtable defaults to the current readtable.

Function: setsyntax character arg2 arg3
This exists only for Maclisp compatibility. The above functions are preferred in new programs. The syntax of character is altered in the current readtable, according to arg2 and arg3. character can be a fixnum, a symbol, or a string, i.e. anything acceptable to the character function. arg2 is usually a keyword; it can be in any package since this is a Maclisp compatibility function. The following values are allowed for arg2:

.kitem :macro The character becomes a macro character. arg3 is the name of a function to be invoked when this character is read. The function takes no arguments, may tyi or read from standard-input (i.e. may call tyi or read without specifying a stream), and returns an object which is taken as the result of the read. .kitem :splicing Like :macro but the object returned by the macro function is a list which is nconced into the list being read. If the character is read not inside a list (at top level or after a dotted-pair dot), then it may return () which means it is ignored, or (obj) which means that obj is read. .kitem :single The character becomes a self-delimiting single-character symbol. If arg3 is a fixnum, the character is translated to that character.
nil
The syntax of the character is not changed, but if arg3 is a fixnum, the character is translated to that character.

a symbol
The syntax of the character is changed to be the same as that of the character arg2 in the standard initial readtable. arg2 is converted to a character by taking the first character of its print name. Also if arg3 is a fixnum, the character is translated to that character.

Function: setsyntax-sharp-macro character type function &optional readtable
This exists only for Maclisp compatibility. set-syntax-#-macro-char is preferred. If function is nil, #character is turned off, otherwise it becomes a macro which calls function. type can be :macro, :peek-macro, :splicing, or :peek-splicing. The splicing part controls whether function returns a single object or a list of objects. Specifying peek causes character to remain in the input stream when function is called; this is useful if character is something like a left parenthesis. function gets one argument, which is nil or the number between the # and the character.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.3 "Input Functions"

Most of these functions take optional arguments called stream and eof-option. stream is the stream from which the input is to be read; if unsupplied it defaults to the value of standard-input. The special pseudo-streams nil and t are also accepted, mainly for Maclisp compatibility. nil means the value of standard-input (i.e. the default) and t means the value of terminal-io (i.e. the interactive terminal). This is all more-or-less compatible with Maclisp, except that instead of the variable standard-input Maclisp has several variables and complicated rules. For detailed documentation of streams, refer to (streams).

eof-option controls what happens if input is from a file (or any other input source that has a definite end) and the end of the file is reached. If no eof-option argument is supplied, an error will be signalled. If there is an eof-option, it is the value to be returned. Note that an eof-option of nil means to return nil if the end of the file is reached; it is not equivalent to supplying no eof-option.

Functions such as read which read an "object" rather than a single character will always signal an error, regardless of eof-option, if the file ends in the middle of an object. For example, if a file does not contain enough right parentheses to balance the left parentheses in it, read will complain. If a file ends in a symbol or a number immediately followed by end-of-file, read will read the symbol or number successfully and when called again will see the end-of-file and obey eof-option. If a file contains ignorable text at the end, such as blank lines and comments, read will not consider it to end in the middle of an object and will obey eof-option.

These end-of-file conventions are not completely compatible with Maclisp. Maclisp's deviations from this are generally considered to be bugs rather than features.

The functions below that take stream and eof-option arguments can also be called with the stream and eof-option in the other order. This functionality is only for compatibility with old Maclisp programs, and should never be used in new programs. The functions attempt to figure out which way they were called by seeing whether each argument is a plausible stream. Unfortunately, there is an ambiguity with symbols: a symbol might be a stream and it might be an eof-option. If there are two arguments, one being a symbol and the other being something that is a valid stream, or only one argument, which is a symbol, then these functions will interpret the symbol as an eof-option instead of as a stream. To force them to interpret a symbol as a stream, give the symbol an si:io-stream-p property whose value is t.

Note that all of these functions will echo their input if used on an interactive stream (one which supports the :rubout-handler operation; see below.) The functions that input more than one character at a time (read, readline) allow the input to be edited using rubout. tyipeek echoes all of the characters that were skipped over if tyi would have echoed them; the character not removed from the stream is not echoed either.

Function: read &optional stream eof-option
read reads in the printed representation of a Lisp object from stream, builds a corresponding Lisp object, and returns the object. The details have been explained above. (This function can take its arguments in the other order, for Maclisp compatibility only; see the note above.)

Variable: read-preserve-delimiters
Certain printed representations given to read, notably those of symbols and numbers, require a delimiting character after them. (Lists do not, because the matching close parenthesis serves to mark the end of the list.) Normally read will throw away the delimiting character if it is "whitespace", but will preserve it (with a :untyi stream operation) if the character is syntactically meaningful, since it may be the start of the next expression.

If read-preserve-delimiters is bound to t around a call to read, no delimiting characters will be thrown away, even if they are whitespace. This may be useful for certain reader macros or special syntaxes.

Function: tyi &optional stream eof-option
tyi inputs one character from stream and returns it. The character is echoed if stream is interactive, except that Rubout is not echoed. The Control, Meta, etc. shifts echo as prefix alpha, beta, etc.

The :tyi stream operation is preferred over the tyi function for some purposes. Note that it does not echo. See (general-stream-ops).

(This function can take its arguments in the other order, for Maclisp compatibility only; see the note above.)

Function: read-for-top-level &optional stream eof-option
This is a slightly different version of read. It differs from read only in that it ignores close parentheses seen at top level, and it returns the symbol si:eof if the stream reaches end-of-file if you have not supplied an eof-option (instead of signalling an error as read would). This version of read is used in the system's "read-eval-print" loops.

(This function can take its arguments in the other order, for uniformity with read only; see the note above.)

Function: readline &optional stream eof-option options
readline reads in a line of text, terminated by a return. It returns the line as a character string, without the return character. This function is usually used to get a line of input from the user. If rubout processing is happening, then options is passed as the list of options to the rubout handler. One option that is particularly useful is the :do-not-echo option (see (:do-not-echo-option)), which you can use to make the return character that terminates the line not be echoed. (This function can take its arguments in the other order, for Maclisp compatibility only; see the note above.)

Function: readch &optional stream eof-option
This function is provided only for Maclisp compatibility, since in the Zetalisp characters are always represented as fixnums. readch is just like tyi, except that instead of returning a fixnum character, it returns a symbol whose print name is the character read in. The symbol is interned in the current package. This is just like a Maclisp "character object". (This function can take its arguments in the other order, for Maclisp compatibility only; see the note above.)

Function: tyipeek &optional peek-type stream eof-option
This function is provided mainly for Maclisp compatibility; the :tyipeek stream operation is usually clearer (see (:tyipeek-stream-operation)).

What tyipeek does depends on the peek-type, which defaults to nil. With a peek-type of nil, tyipeek returns the next character to be read from stream, without actually removing it from the input stream. The next time input is done from stream the character will still be there; in general, (= (tyipeek) (tyi)) is t. (See the description of the :tyipeek stream operation ((:tyipeek-stream-operation)) for details.)

If peek-type is a fixnum less than 1000 octal, then tyipeek reads characters from stream until it gets one equal to peek-type. That character is not removed from the input stream.

If peek-type is t, then tyipeek skips over input characters until the start of the printed representation of a Lisp object is reached. As above, the last character (the one that starts an object) is not removed from the input stream.

The form of tyipeek supported by Maclisp in which peek-type is a fixnum not less than 1000 octal is not supported, since the readtable formats of the Maclisp reader and the Zetalisp reader are quite different.

Characters passed over by tyipeek are echoed if stream is interactive.

The following functions are related functions which do not operate on streams. Most of the text at the beginning of this section does not apply to them.

Function: read-from-string string &optional eof-option (idx 0)
The characters of string are given successively to the reader, and the Lisp object built by the reader is returned. Macro characters and so on will all take effect. If string has a fill-pointer it controls how much can be read.

eof-option is what to return if the end of the string is reached, as with other reading functions. idx is the index in the string of the first character to be read.

read-from-string returns two values; the first is the object read and the second is the index of the first character in the string not read. If the entire string was read, this will be either the length of the string or 1 more than the length of the string.

 
Example:
(read-from-string "(a b c)") => (a b c) and 7

Function: readlist char-list
This function is provided mainly for Maclisp compatibility. char-list is a list of characters. The characters may be represented by anything that the function character accepts: fixnums, strings, or symbols. The characters are given successively to the reader, and the Lisp object built by the reader is returned. Macro characters and so on will all take effect.

If there are more characters in char-list beyond those needed to define an object, the extra characters are ignored. If there are not enough characters, an "eof in middle of object" error is signalled.

See also the with-input-from-string special form ((with-input-from-string-fun)).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.4 "Output Functions"

These functions all take an optional argument called stream, which is where to send the output. If unsupplied stream defaults to the value of standard-output. If stream is nil, the value of standard-output (i.e. the default) is used. If it is t, the value of terminal-io is used (i.e. the interactive terminal). If stream is a list of streams, then the output is performed to all of the streams (this is not implemented yet, and an error is signalled in this case). This is all more-or-less compatible with Maclisp, except that instead of the variable standard-output Maclisp has several variables and complicated rules. For detailed documentation of streams, refer to (streams).

Function: prin1 x &optional stream
prin1 outputs the printed representation of x to stream, with slashification (see (slashification)). x is returned.

Function: prin1-then-space x &optional stream
prin1-then-space is like prin1 except that output is followed by a space.

Function: print x &optional stream
print is just like prin1 except that output is preceeded by a carriage return and followed by a space. x is returned.

Function: princ x &optional stream
princ is just like prin1 except that the output is not slashified. x is returned.

Function: tyo char &optional stream
tyo outputs the character char to stream.

Function: terpri &optional stream
terpri outputs a carriage return character to stream.

The format function (see (format-fun)) is very useful for producing nicely formatted text. It can do anything any of the above functions can do, and it makes it easy to produce good looking messages and such. format can generate a string or output to a stream.

The grindef function (see (grindef-fun)) is useful for formatting Lisp programs.

See also the with-output-to-string special form ((with-output-to-string-fun)).

Function: stream-copy-until-eof from-stream to-stream &optional leader-size
stream-copy-until-eof inputs characters from from-stream and outputs them to to-stream, until it reaches the end-of-file on the from-stream. For example, if x is bound to a stream for a file opened for input, then (stream-copy-until-eof x terminal-io) will print the file on the console.

If from-stream supports the :line-in operation and to-stream supports the :line-out operation, then stream-copy-until-eof will use those operations instead of :tyi and :tyo, for greater efficiency. leader-size will be passed as the argument to the :line-in operation.

Function: beep &optional beep-type (stream terminal-io)
This function is intended to attract the user's attention by causing an audible beep, or flashing the screen, or something similar. If the stream supports the :beep operation, then this function sends it a :beep message, passing type along as an argument. Otherwise it just causes an audible beep on the terminal. type is a keyword selecting among several different beeping noises. The allowed types have not yet been defined; type is currently ignored and should always be nil. (The :beep message is described on (:beep-message).)

Function: cursorpos &rest args
This function exists primarily for Maclisp compatibility. Usually it is preferable to send the appropriate messages (see the window system documentation).

cursorpos normally operates on the standard-output stream; however, if the last argument is a stream or t (meaning terminal-io) then cursorpos uses that stream and ignores it when doing the operations described below. Note that cursorpos only works on streams which are capable of these operations, for instance windows. A stream is taken to be any argument which is not a number and not a symbol, or a symbol other than nil with a name more than one character long.

(cursorpos) => (line . column), the current cursor position.

(cursorpos line column) moves the cursor to that position. It returns t if it succeeds and nil if it doesn't.

(cursorpos op) performs a special operation coded by op, and returns t if it succeeds and nil if it doesn't. op is tested by string comparison, it is not a keyword symbol and may be in any package.

F
Moves one space to the right.
B
Moves one space to the left.
D
Moves one line down.
U
Moves one line up.
T
Homes up (moves to the top left corner). Note that t as the last argument to cursorpos is interpreted as a stream, so a stream must be specified if the T operation is used.
Z
Home down (moves to the bottom left corner).
A
Advances to a fresh line. See the :fresh-line stream operation.
C
Clears the window.
E
Clear from the cursor to the end of the window.
L
Clear from the cursor to the end of the line.
K
Clear the character position at the cursor.
X
B then K.

Function: exploden x
exploden returns a list of characters (as fixnums) which are the characters that would be typed out by (princ x) (i.e. the unslashified printed representation of x).
 
Example:
(exploden '(+ /12 3)) => (50 53 40 61 62 40 63 51)

Function: explodec x
explodec returns a list of characters represented by symbols which are the characters that would be typed out by (princ x) (i.e. the unslashified printed representation of x).
 
Example:
(explodec '(+ /12 3)) => ( /( + /  /1 /2 /  /3 /) )
(Note that there are slashified spaces in the above list.)

Function: explode x
explode returns a list of characters represented by symbols which are the characters that would be typed out by (prin1 x) (i.e. the slashified printed representation of x).
 
Example:
(explode '(+ /12 3)) => ( /( + /  // /1 /2 /  /3 /) )
(Note that there are slashified spaces in the above list.)

Function: flatsize x
flatsize returns the number of characters in the slashified printed representation of x.

Function: flatc x
flatc returns the number of characters in the unslashified printed representation of x.

.insert lmman;stream >

.insert lmman;fd.fio >


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.5 "Rubout Handling"

.setq rubout-handler section-page .setq rubout-handling section-page

The rubout handler is a feature of all interactive streams, that is, streams which connect to terminals. Its purpose is to allow the user to edit minor mistakes in typein. At the same time, it is not supposed to get in the way; input is to be seen by Lisp as soon as a syntactically complete form has been typed. The definition of "syntactically complete form" depends on the function that is reading from the stream; for read, it is a Lisp expression.

Some interactive streams ("editing Lisp listeners") have a rubout handler which allows input to be edited with the full power of the Zwei editor. Other streams have a simple rubout handler which just allows rubbing out of single characters, and a few simple commands like clearing the screen and erasing the entire input typed so far. This section describes the general protocol used to deal with any rubout handler, and it also discusses the simple rubout handler and what commands it deals with.

The tricky thing about the rubout handler is the need for it to figure out when you are all done. The idea of a rubout handler is that you can type in characters, and they are saved up in a buffer so that if you change your mind, you can rub them out and type different characters. However, at some point, the rubout handler has to decide that the time has come to stop putting characters into the buffer, and let the function, such as read, start processing the characters. This is called "activating". The right time to activate depends on the function calling the rubout handler, and may be very complicated (if the function is read, figuring out when one Lisp expression has been typed requires knowledge of all the various printed representations, what all currently-defined reader macros do, and so on). Rubout handlers should not have to know how to parse the characters in the buffer to figure out what the caller is reading and when to activate; only the caller should have to know this. The rubout handler interface is organized so that the calling function can do all the parsing, while the rubout handler does all the handling of rubouts, and the two are kept completely separate.

The basic way that the rubout handler works is as follows. When an input function that reads an "object", such as read or readline (but not tyi), is called to read from a stream which has :rubout-handler in its :which-operations list, that function "enters" the rubout handler. It then goes ahead :tyi'ing characters from the stream. Because control is inside the rubout handler, the stream will echo these characters so the user can see what he is typing. (Normally echoing is considered to be a higher-level function outside of the province of streams, but when the higher-level function tells the stream to enter the rubout handler it is also handing it the responsibility for echoing). The rubout handler is also saving all these characters in a buffer, for reasons disclosed in the following paragraph. When the function, read or whatever, decides it has enough input, it returns and control "leaves" the rubout handler. That was the easy case.

If the user types a rubout, a *throw is done, out of all recursive levels of read, reader macros, and so forth, back to the point where the rubout handler was entered. Also the rubout is echoed by erasing from the screen the character which was rubbed out. Now the read is tried over again, re-reading all the characters which had been typed and not rubbed out, not echoing them this time. When the saved characters have been exhausted, additional input is read from the user in the usual fashion.

The effect of this is a complete separation of the functions of rubout handling and parsing, while at the same time mingling the execution of these two functions in such a way that input is always "activated" at just the right time. It does mean that the parsing function (in the usual case, read and all macro-character definitions) must be prepared to be thrown through at any time and should not have non-trivial side-effects, since it may be called multiple times.

If an error occurs while inside the rubout handler, the error message is printed and then additional characters are read. When the user types a rubout, it rubs out the error message as well as the character that caused the error. The user can then proceed to type the corrected expression; the input will be reparsed from the beginning in the usual fashion.

The simple rubout handler also recognizes the special characters Clear-Input, Clear-Screen, and Delete. (These are Clear, Form, and VT on old keyboards.) Clear-Screen clears the screen and echoes back the buffered input. Clear-Input is like hitting enough rubouts to flush all the buffered input. Delete is like Clear-Screen in that it echoes back the input, but it does not clear the screen. [It should be moved to a different key, shouldn't it?]

If a character with control shifts (Control, Meta, Super, or Hyper) is typed at a rubout handler that does not support the full set of editing commands, such as the simple rubout handler, it beeps and ignores the character. These characters are reserved in this context for editing use. The rubout handler based on the Zwei editor interprets control characters in the usual Zwei way: as editing commands, allowing you to edit your buffered input. When not inside the rubout handler, and when typing at a program that uses control characters for its own purposes, control characters are treated the same as ordinary characters.

The following explanation tells you how to write your own function that invokes the rubout handler. The functions read and readline both work this way. You should use the readline1 example, below, as a template for writing your own function.

The way that the rubout handler is entered is complicated, since a *catch must be established. The variable rubout-handler is non-nil if the current process is inside the rubout handler. This is used to handle recursive calls to read from inside reader macros and the like. If rubout-handler is nil, and the stream being read from has :rubout-handler in its :which-operations, functions such as read send the :rubout-handler message to the stream with arguments of a list of options, the function, and its arguments. The rubout handler initializes itself and establishes its *catch, then calls back to the specified function with rubout-handler bound to t. User-written input reading functions should follow this same protocol, to get the same input editing benefits as read and readline.

Variable: rubout-handler
t if control is inside the rubout handler in this process.

As an example of how to use the rubout handler, here is a simplified version of the readline function. It doesn't bother about end-of-file handling, use of :line-in for efficiency, etc.
 
(defun readline1 (stream)
  ;; If stream does rubout handling, get inside rubout handler
  (cond ((and (not rubout-handler)
	      (memq ':rubout-handler
		    (funcall stream ':which-operations)))
	 (funcall stream ':rubout-handler '() #'readline1 stream))
	;; Accumulate characters until return
	(t (do ((ch (funcall stream ':tyi)
		    (funcall stream ':tyi))
		(len 100)
		(string (make-array 100 ':type 'art-string))
		(idx 0))
	       ((or (null ch) (= ch #\cr))
		(adjust-array-size string idx)
		string)
	     (if (= idx len)
		 (adjust-array-size string (setq len (+ len 40))))
	     (aset ch string idx)
	     (setq idx (1+ idx))))))

The first argument to the :rubout-handler message is a list of options. The second argument is the function that the rubout handler should call to do the reading, and the rest of the arguments are passed to that function. Note that in the example above, readline1 is sending the :rubout-handler message passing itself as the function, and its own arguments as the arguments. This is the usual thing to do. It isn't passing any options. The returned values of the message are normally the returned values of the function (except sometimes when the :full-rubout option is used; see below).

Each option in the list of options given as the first argument to the :rubout-handler message consists of a list whose first element is a keyword and whose remaining elements are "arguments" to that keyword. Note that this is not the same format as the arguments to a typical function that takes keyword arguments; rather this is an a-list of options. The standard options are:

(:full-rubout val)
If the user rubs out all the characters he typed, then control will be returned from the rubout handler immediately. Two values are returned; the first is nil and the second is val. (if the user doesn't rub out all the characters, then the rubout handler propagates multiple values back from the function that it calls, as usual.) In the absence of this option, the rubout handler would simply wait for more characters to be typed in, and would ignore any additional rubouts.

(:pass-through char1 char2...)
The characters char1, char2, etc. are not to be treated as special by the rubout handler. You can use this to override the default processing of characters such as Clear-Input and to receive control characters. Any function that reads input and uses non-printing characters for anything should list them in a :pass-through option. This way, if input is being rubout-handled by the editor, those non-printing characters will get their desired meaning rather than their meaning as editor commands.

(:prompt function)
(:reprompt function)
When it is time for the user to be prompted, function is called with two arguments. The first is a stream it may print on; the second is the character which caused the need for prompting, e.g. #\clear-input or #\clear-screen, or nil if the rubout handler was just entered.

The difference between :prompt and :reprompt is that the latter does not call the prompt function when the rubout handler is first entered, but only when the input is redisplayed (e.g. after a screen clear). If both options are specified then :reprompt overrides :prompt except when the rubout handler is first entered.

(:initial-input string)
Pretends that the user typed string. When the rubout handler is entered, string is typed out. The user can add more characters to it or rubout characters from it.

.setq :do-not-echo-option page

(:do-not-echo char-1 char-2...)
The characters char-1, char-2, etc. are not to be echoed when the user types them. The comparison is done with =, not char-equal. You can use this to suppress echoing of the return character that terminated a readline, for example.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.6 The :read and :print Stream Operations

A stream can specially handle the reading and printing of objects by handling the :read and :print stream operations. Note that these operations are optional and most streams do not support them.

If the read function is given a stream which has :read in its which-operations, then instead of reading in the normal way it sends the :read message to the stream with one argument, read's eof-option if it had one or a magic internal marker if it didn't. Whatever the stream returns is what read returns. If the stream wants to implement the :read operation by internally calling read, it must use a different stream which does not have :read in its which-operations.

If a stream has :print in its which-operations, it may intercept all object printing operations, including those due to the print, prin1, and princ functions, those due to format, and those used internally, for instance in printing the elements of a list. The stream receives the :print message with three arguments: the object being printed, the prindepth (for comparison against the prinlevel variable), and slashify-p (t for prin1, nil for princ). If the stream returns nil, then normal printing takes place as usual. If the stream returns non-nil, then print does nothing; the stream is assumed to have output an appropriate printed representation for the object. The two following functions are useful in this connection; however, they are in the system-internals package and may be changed without much notice.

Function: si:print-object object prindepth slashify-p stream &optional which-operations
Outputs the printed-representation of object to stream, as modified by prindepth and slashify-p. This is the internal guts of the Lisp printer. When a stream's :print handler calls this function, it should supply the list (:string-out) for which-operations, to prevent itself from being called recursively. Or it can supply nil if it does not want to receive :string-out messages.

If you want to customize the behavior of all printing of Lisp objects, advising (see (advise)) this function is the way to do it. See (customizing-the-printer).

Function: si:print-list list prindepth slashify-p stream which-operations
This is the part of the Lisp printer that prints lists. A stream's :print handler can call this function, passing along its own arguments and its own which-operations, to arrange for a list to be printed the normal way and the stream's :print hook to get a chance at each of the list's elements.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.7 "Accessing Files"

.setq file-stream section-page

The Lisp Machine can access files on a variety of remote file servers, which are typically (but not necessarily) accessed through the Chaosnet, as well as accessing files on the Lisp Machine itself, if the machine has its its own file system. This section tells you how to get a stream which reads or writes a given file, and what the device-dependent operations on that stream are. Files are named with pathnames. Since pathnames are quite complex they have their own chapter; see (pathname).

Special Form: with-open-file (stream pathname options...) body...
Evaluates the body forms with the variable stream bound to a stream which reads or writes the file named by the value of pathname. The options forms evaluate to the file-opening options to be used; see (file-opening-options).

When control leaves the body, either normally or abnormally (via *throw), the file is closed. If a new output file is being written, and control leaves abnormally, the file is aborted and it is as if it were never written. Because it always closes the file, even when an error exit is taken, with-open-file is preferred over open. Opening a large number of files and forgetting to close them tends to break some remote file servers, ITS's for example.

pathname is the name of the file to be opened; it can be a pathname object, a string, a symbol, or a Maclisp-compatible "namelist". It can be anything acceptable to fs:parse-pathname; the complete rules for parsing pathnames are explained in (pathname).

If an error, such as file not found, occurs the user is asked to supply an alternate pathname, unless this is overridden by options. At that point he can quit out or enter the error handler, if the error was not due to a misspelled pathname.

Function: open pathname &rest options
Returns a stream which is connected to the specified file. Unlike Maclisp, the open function only creates streams for files; streams for other devices are created by other functions. The pathname and options arguments are the same as in with-open-file; see above. If an error, such as file not found, occurs, the user is asked to supply an alternate pathname, unless this is overridden by options.

When the caller is finished with the stream, it should close the file by using the :close operation or the close function. The with-open-file special form does this automatically, and so is usually preferred. open should only be used when the control structure of the program necessitates opening and closing of a file in some way more complex than the simple way provided by with-open-file. Any program that uses open should set up unwind-protect handlers (see (unwind-protect-fun)) to close its files in the event of an abnormal exit.

Function: close stream
The close function simply sends the :close message to stream.

Function: renamef file new-name &optional (error-p t)
file can be a pathname or a stream which is open to a file. The specified file is renamed to new-name (a pathname). If error-p is t, then if an error occurs it will be signalled as a Lisp error. If error-p is nil and an error occurs, the error message will be returned as a string, otherwise t will be returned.

Function: deletef file &optional (error-p t)
file can be a pathname or a stream which is open to a file. The specified file is deleted. If error-p is t, then if an error occurs it will be signalled as a Lisp error. If error-p is nil and an error occurs, the error message will be returned as a string, otherwise t will be returned.

Function: probef pathname
Returns nil if there is no file named pathname, otherwise returns a pathname which is the true name of the file, which can be different from pathname because of file links, version numbers, etc.

Function: fs:close-all-files
Closes all open files. This is useful when a program has run wild opening files and not closing them. It closes all the files in :abort mode (see (close-message)), which means that files open for output will be deleted. Using this function is dangerous, because you may close files out from under various programs like Zmacs and Zmail; only use it if you have to and if you feel that you know what you're doing.

.setq file-opening-options page The options used when opening a file are normally alternating keywords and values, like any other function that takes keyword arguments. In addition, for compatibility with the Maclisp open function, if only a single option is specified it is either a keyword or a list of keywords (not alternating with values).

The file-opening options control things like whether the stream is for input from a existing file or output to a new file, whether the file is text or binary, etc.

The following option keywords are standardly recognized; additional keywords can be implemented by particular file system hosts.

[Are all these keywords supported by all file systems?]

:direction
The possible values are :input (the default), :output, and nil. The first two should be self-explanatory. nil means that this is a "probe" opening; no data are to be transferred, the file is only being opened to access or change its properties.

:characters
The possible values are t (the default), nil, which means that the file is a binary file, and :default, which means that the file system should decide whether the file contains characters or binary data and open it in the appropriate mode.

:byte-size
The possible values are nil (the default), a number, which is the number of bits per byte, and :default, which means that the file system should choose the byte size based on attributes of the file. If the file is being opened as characters, nil selects the appropriate system-dependent byte size for text files; it is usually not useful to use a different byte size. If the file is being opened as binary, nil selects the default byte size of 16 bits.

:error
The possible values are t (the default) and nil. If an error occurs, this option controls whether the error is signalled to the user (t) or a string containing an error message is returned instead of a stream (nil).

:new-file
If the value is t, the file system is allowed to create a new file. If the value is nil, an existing file must be opened. The default is t if :direction :output is specified, otherwise nil.

:new-version
This controls what happens if the version field of the pathname being opened is :newest. If the value is nil, the newest existing version of the file is found. If the value is t (the default when :direction :output is specified), then the next-higher-numbered version of the file is to be created.

:old-file
This keyword controls what happens if a file with the specified name already exists, when :direction :output is specified. Possible values are:

nil or :replace
The existing file is to be replaced when the new file is closed (providing :abort is not specified when closing.) This is the default if :new-file is specified as, or defaults to, t.

t or :rewrite
The existing file is to be clobbered with the new data. This is the default if :new-file is specified as nil.

:append
Append new data to the end of the file.

:error
Signal an error (file already exists).

:rename
The old file is to be renamed to some other name, to get it out of the way.

:rename-and-delete
The old file is renamed, and deleted when the new file is closed.

:new-version
Create a new version, instead of opening the version number specified in the pathname.

:inhibit-links
The default is nil. If the pathname is the name of a file-system link, and this option is t, the link itself is opened rather than the file it points to. This is only useful with probe openings, since links contain no data.

:deleted
The default is nil. If t is specified, and the file system has the concept of deleted but not expunged files, it is possible to open a deleted file. Otherwise deleted files are invisible.

:temporary
The default is nil. If t is specified, the file is marked as temporary, if the file system has that concept.

:preserve-dates
The default is nil. If t is specified, the file's reference and modification dates are not updated.

:flavor
This controls the kind of file to be opened. The default is nil, a normal file. Other possible values are :directory and :link.

:link-to
When creating a file with :flavor :link, this keyword must be specified; its value is a pathname which becomes the target of the link.

:estimated-size
The value may be nil (the default), which means there is no estimated size, or a number of bytes. Some file systems use this to optimize disk allocation.

:physical-volume
The value may be nil (the default), or a string which is the name of a physical volume on which the file is to be stored. This is not meaningful for all file systems.

:logical-volume
The value may be nil (the default), or a string which is the name of a logical volume on which the file is to be stored. This is not meaningful for all file systems.

:incremental-update
The value may be nil (the default), or t to cause the file system to take extra pains to write data onto the disk more often.

:super-image
The value may be nil (the default), or t which disables the special treatment of rubout in ascii files. Normally rubout is an escape which causes the following character to be interpreted specially, allowing all characters from 0 through 376 to be stored. This applies to pdp-10 file servers only.

:raw
The value may be nil (the default), or t which disables all character set translation in ascii files. This applies to pdp-10 file servers only.

In the Maclisp compatibility mode, there is only one option, and it is either a symbol or a list of symbols. These symbols are recognized no matter what package they are in, since Maclisp does not have packages. The following symbols are recognized:

in, read
Select opening for input (the default).

out, write, print
Select opening for output; a new file is to be created.

binary, fixnum
Select binary mode, otherwise character mode is used. Note that fixnum mode uses 16-bit binary words and is not compatible with Maclisp fixnum mode which uses 36-bit words. On the pdp-10, fixnum files are stored with two 16-bit words per pdp-10 word, left-justified and in pdp-10 byte order.

character, ascii
The opposite of fixnum. This is the default.

single, block
Ignored for compatibility with the Maclisp open function.

byte-size
Must be followed by a number in the options list, and must be used in combination with fixnum. The number is the number of bits per byte, which can be from 1 to 16. On a pdp-10 file server these bytes will be packed into words in the standard way defined by the ILDB instruction. The :tyi stream operation will (of course) return the bytes one at a time.

probe, error, noerror, raw, super-image, deleted, temporary
These are not available in Maclisp. The corresponding keywords in the normal form of file-opening options are preferred over these.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.7.1 Loading Files

To load a file is to read through the file, evaluating each form in it. Programs are typically stored in files; the expressions in the file are mostly special forms such as defun and defvar which define the functions and variables of the program.

Loading a compiled (or QFASL) file is similar, except that the file does not contain text but rather pre-digested expressions created by the compiler which can be loaded more quickly.

These functions are for loading single files. There is a system for keeping track of programs which consist of more than one file; for further information refer to (system-system).

Function: load pathname &optional pkg nonexistent-ok dont-set-default
This function loads the file named by pathname into the Lisp environment. If the file is a QFASL file, it calls fasload; otherwise it calls readfile. Normally the file is read into its "home" package, but if pkg is supplied it is the package in which the file is to be read. pkg can be either a package or the name of a package as a string or a symbol. If pkg is not specified, load prints a message saying what package the file is being loaded into. If nonexistent-ok is specified, load just returns if the file cannot be opened.

pathname can be anything acceptable to fs:parse-pathname; pathnames and the complete rules for parsing them are explained in (pathname). pathname is defaulted from fs:load-pathname-defaults (see (fs:load-pathname-defaults-var)), which is the set of defaults used by load, qc-file, and similar functions. Normally load updates the pathname defaults from pathname, but if dont-set-default is specified this is suppressed.

If pathname contains an FN1 but no FN2, load will first look for the file with an FN2 of QFASL, then it will look for an FN2 of >. For non-ITS file systems, this generalizes to: if pathname specifies a type and/or a version, load loads that file. Otherwise it first looks for a type-QFASL file, then a type-LISP file, in both cases looking for the newest version.

Function: readfile pathname &optional pkg no-msg-p
readfile is the version of load for text files. It reads and evaluates each expression in the file. As with load, pkg can specify what package to read the file into. Unless no-msg-p is t, a message is printed indicating what file is being read into what package. The defaulting of pathname is the same as in load.

Function: fasload pathname &optional pkg no-msg-p
fasload is the version of load for QFASL files. It defines functions and performs other actions as directed by the specifications inserted in the file by the compiler. As with load, pkg can specify what package to read the file into. Unless no-msg-p is t, a message is printed indicating what file is being read into what package. The defaulting of pathname is the same as in load.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.7.2 File Property Lists

.setq file-property-list section-page

Any text file can contain a "property list" which specifies several attributes of the file. The above loading functions, the compiler, and the editor look at this property list. File property lists are especially useful in program source files, i.e. a file that is intended to be loaded (or compiled and then loaded).

If the first non-blank line in the file contains the three characters 7"-*-", some text, and 7"-*-" again, the text is recognized as the file's property list. Each property consists of the property name, a colon, and the property value. If there is more than one property they are separated by semicolons. An example of such a property list is:
 
; -*- Mode:Lisp; Package:Cellophane; Base:10 -*-
The semicolon makes this line look like a comment rather than a Lisp expression. This defines three properties: mode, package, and base. Another example is:
 
.c This is part of the Lisp machine manual.  -*- Mode:Bolio -*-

A property name is made up of letters, numbers, and otherwise-undefined punctuation characters such as hyphens. A property value can be such a name, or a decimal number, or several such items separated by commas. Spaces may be used freely to separate tokens. Upper and lower-case letters are not distinguished. There is no quoting convention for special characters such as colons and semicolons. Thus file property lists are similar in spirit to Lisp property lists.

The file property list format actually has nothing to do with Lisp; it is just a convention for placing some information into a file that is easy for a program to interpret. The Emacs editor on the pdp-10 knows how to interpret these property lists (primarily in order to look at the Mode property).

Within the Lisp Machine, there exists a parser for file property lists that creates some Lisp data structure that corresponds to the file property list. When a file property list is read in and given to the parser (the fs:file-read-property-list function, see below), it is converted into Lisp objects as follows: Property names are interpreted as Lisp symbols, and interned on the keyword package. Numbers are interpreted as Lisp fixnums, and are read in decimal. If a property value contains any commas, then the commas separate several expressions which are formed into a list.

When a file is edited, loaded, or compiled, its file property list is read in and the properties are stored on the property list of the generic pathname (see (generic-pathname)) for that file, where they can be retrieved with the :get and :plist messages. So the way you examine the properties of a file is usually to use messages to a pathname object that represents the generic pathname of a file. Note that there other properties there, too. The function fs:file-read-property-list (see below) reads the file property list of a file and sets up the properties on the generic pathname; editing, loading, or compiling a file will call this function, but you can call it yourself if you want to examine the properties of an arbitrary file.

If the property list text contains no colons, it is an old Emacs format, containing only the value of the Mode property.

The following are some of the property names allowed and what they mean.

Mode
The editor major mode to be used when editing this file. This is typically the name of the language in which the file is written. The most common values are Lisp and Text.

Package
The name of the package into which the file is to be loaded. See (package) for information about packages.

Base
The number base in which the file is written. This affects both ibase and base, since it is confusing to have the input and output bases be different. The most common values are 8 and 10.

Lowercase
If the property value is not nil, the file is written in lower-case letters and the editor does not translate to upper case. (The editor does not translate to upper case by default unless the user selects "Electric Shift Lock" mode.)

Fonts
The property value is a list of font names, separated by commas. The editor uses this for files which are written in more than one font.

Backspace
If the property value is not nil, the file may contain backspaces which cause characters to overprint on each other. The default is to disallow overprinting and display backspaces the way other special function keys are displayed. This default is to prevent the confusion that can be engendered by overstruck text.

Patch-File
If the property value is not nil, the file is a "patch file". When it is loaded the system will not complain about function redefinitions. Furthermore, the remembered source file names for functions defined in this file will not be changed to this file, but will be left as whatever file the function came from originally. In a patch file, the defvar special-form turns into defconst; thus patch files will always reinitialize variables.

You are free to define additional file properties of your own. Howver, you should choose names that are different from all the names above, and from any names likely to be defined by anybody else's programs, to avoid accidental name conflicts.

The following function is the parser for file property lists.

Function: fs:file-read-property-list pathname stream
pathname should be a pathname object (not a string or namelist, but an actual pathname); usually it is a generic pathname (see (generic-pathname)). stream should be a stream that has been opened and is pointing to the beginning of the file whose file property list is to be parsed. This function reads from the stream until it gets the file property list, parses it, puts corresponding properties onto the property list of pathname, and finally sets the stream back to the beginning of the file by using the :set-pointer file stream operation (see (:set-pointer-message)).

[Is the above function really supposed to be called FS:READ-SYNTAX-PLIST?]

The fundamental way that programs in the Lisp Machine react to the presence of properties on a file's file property list is to examine the property list in the generic pathname. However, there is another way that is more convenient for some applications. File properties can cause special variables to be bound whenever Lisp expressions are being read from the file--when the file is being loaded, when it is being compiled, when it is being read from by the editor, and when its QFASL file is being loaded. This is how the Package and Base properties work. You can also deal with properties this way, by using the following function:

Function: fs:file-property-bindings pathname
This function examines the property list of pathname, and finds all those property names that have fs:file-property-bindings properties. Each such property name specifies a set of variables to bind, and a set of values to which to bind them. This function returns two values: a list of all the variables, and a list of all the corresponding values. Usually you use this function by calling it on a generic pathname what has had fs:file-read-property-list done on it, and then you use the two returned values as the first two subforms to a progv special form (see (progv-fun)). Inside the body of the progv the specified bindings will be in effect.

Usually pathname is a generic pathname. It can also be a locative, in which case it is interpreted to be the property list itself.

Of the standard property names, the following ones have fs:file-property-bindings, with the following effects. Package binds the variable package (see (package-var)) to the package. Base binds the variables base (see (base-var)) and ibase (see (ibase-var)) to the value. Patch-file binds fs:this-is-a-patch-file to the value.

Any properties whose names do not have a fs:file-property-bindings property are ignored completely.

You can also add your own property names that affect bindings. If an indicator symbol has an fs:file-property-bindings property, the value of that property is a function which is called when a file with a file property of that name is going to be read from. The function is given three arguments: the file pathname, the property name, and the property value. It must return two values: a list of variables to be bound and a list of values to bind them to. The function for the Base keyword could have been defined by:
 
(defun (:base file-property-bindings) (file ignore bse)
  (if (not (and (typep bse 'fixnum)
	 (> bse 1)
	 (< bse 37.)))
      (ferror nil "File ~A has an illegal -*- Base:~s -*-"
	          file bse))
  (values (list 'base 'ibase) (list bse bse)))


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.7.3 File Stream Operations

.setq file-stream-operations-section section-page

The following messages may be sent to file streams, in addition to the normal I/O messages which work on all streams. Note that several of these messages are useful to send to a file stream which has been closed. Some of these messages use pathnames; refer to (pathname) for an explanation of pathnames.

.defmessage :pathname Returns the pathname that was opened to get this stream. This may not be identical to the argument to open, since missing components will have been filled in from defaults, and the pathname may have been replaced wholesale if an error occurred in the attempt to open the original pathname. .end_defmessage

.defmessage :truename Returns the pathname of the file actually open on this stream. This can be different from what :pathname returns because of file links, logical devices, mapping of "newest" version to a particular version number, etc. For an output stream the truename is not meaningful until after the stream has been closed, at least when the file server is an ITS. .end_defmessage

.defmessage :qfaslp Returns t if the file has a magic flag at the front that says it is a QFASL file, nil if it is an ordinary file. .end_defmessage

.defmessage :length Returns the length of the file, in bytes or characters. For text files on pdp-10 file servers, this is the number of pdp-10 characters, not Lisp Machine characters. The numbers are different because of character-set translation; see (character-set-differences) for a full explanation. For an output stream the length is not meaningful until after the stream has been closed, at least when the file server is an ITS. .end_defmessage

.defmessage :creation-date Returns the creation date of the file, as a number which is a universal time. See the chapter on the time package ((time)). .end_defmessage

.defmessage :info Returns a string which contains the version number and creation date of the file. This can be used to tell if the file has been modified between two opens. For an output stream the info is not meaningful until after the stream has been closed, at least when the file server is an ITS. .end_defmessage

.defmessage :set-byte-size new-byte-size This is only allowed on binary ("fixnum mode") file streams. The byte size can be changed to any number of bits from 1 to 16. .end_defmessage

.defmessage :delete &optional (error-p t) Deletes the file open on this stream. For the meaning of error-p, see the deletef function. The file doesn't really go away until the stream is closed. .end_defmessage

.defmessage :rename new-name &optional (error-p t) Renames the file open on this stream. For the meaning of error-p, see the renamef function. .end_defmessage

File output streams implement the :finish and :force-output messages.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

33.8 Accessing Directories

To understand the functions in this section, it helps to have read the following chapter, on pathnames.

Function: fs:directory-list pathname &rest options
Finds all the files that match pathname and returns a list with one element for each file. Each element is a list whose car is the pathname of the file and whose cdr is a list of the properties of the file; thus the element is a "disembodied" property list and get may be used to access the file's properties. The car of one element is nil; the properties in this element are properties of the file system as a whole rather than of a specific file.

The matching is done using both host-independent and host-dependent conventions. Any component of pathname which is :wild matches anything; all files that match the remaining components of pathname will be listed, regardless of their value for the wild component. In addition, there is host-dependent matching. Typically this uses the asterisk character (*) as a wild-card character. A pathname component that consists of just a * matches any value of that component (the same as :wild). A pathname component that contains * and other characters matches any character (on ITS) or any string of characters (on TOPS-20) in the starred positions and requires the specified characters otherwise. Other hosts will follow similar but not necessarily identical conventions.

The options are keywords which modify the operation. The following options are currently defined:

:noerror
If a file-system error (such as no such directory) occurs during the operation, normally an error will be signalled and the user will be asked to supply a new pathname. However, if :noerror is specified then in the event of an error a string describing the error will be returned as the result of fs:directory-list. This is identical to the :noerror option to open.

:deleted
This is for TOPS-20 file servers. It specifies that deleted (but not yet expunged) files are to be included in the directory listing.

The properties that may appear in the list of property lists returned by fs:directory-list are host-dependent to some extent. The following properties are those that are defined for both ITS and TOPS-20 file servers. This set of properties is likely to be extended or changed in the future.

:length-in-bytes
The length of the file expressed in terms of the basic units in which it is written (characters in the case of a text file).
:byte-size
The number of bits in one of those units.
:length-in-blocks
The length of the file in terms of the file system's unit of storage allocation.
:block-size
The number of bits in one of those units.
:creation-date
The date the file was created, as a universal time. See (time).
:reference-date
The most recent date that the file was used, as a universal time.
:author
The name of the person who created the file, as a string.
:not-backed-up
t if the file exists only on disk, nil if it has been backed up on magnetic tape.

Function: fs:change-file-properties pathname error-p &rest properties
Some of the properties of a file may be changed; for instance, its creation date or its author. Exactly which properties may be changed depends on the host file system; a list of the changeable property names is the :settable-properties property of the file system as a whole, returned by fs:directory-list as explained above.

fs:change-file-properties changes one or more properties of a file. pathname names the file. The properties arguments are alternating keywords and values. The error-p argument is the same as with renamef; if an error occurs and it is nil a string describing the error will be returned; if it is t a Lisp error will be signalled. If no error occurs, fs:change-file-properties returns t.

Function: fs:file-properties pathname &optional (error-p t)
Returns a disembodied property list for a single file (compare this to fs:directory-list). The car of the returned list is the truename of the file and the cdr is an alternating list of indicators and values. The error-p argument is the same as with renamef; if an error occurs and it is nil a string describing the error will be returned; if it is t (the default) a Lisp error will be signalled.

Function: fs:complete-pathname defaults string type version &rest options
string is a partially-specified file name. (Presumably it was typed in by a user and terminated with the altmode key or the END key to request completion.) fs:complete-pathname looks in the file system on the appropriate host and returns a new, possibly more specific string. Any unambiguous abbreviations are expanded out in a host-dependent fashion.

defaults, type, and version are the arguments that will be given to fs:merge-pathname-defaults (see (fs:merge-pathname-defaults-fun)) when the user's input is eventually parsed and defaulted.

options are keywords (without following values) which control how the completion will be performed. The following option keywords are allowed:

.kitem :deleted Look for files which have been deleted but not yet expunged.
:read or :in
The file is going to be read. This is the default.

:print or :write or :out
The file is going to be written (i.e. a new version is going to be created).

.kitem :old Look only for files that already exist. This is the default.

.kitem :new-ok Allow either a file that already exists, or a file that does not yet exist. An example of the use of this is the c-X c-F (Find File) command in the editor.

The first value returned is always a string containing a file name; either the original string, or a new, more specific string. The second value returned indicates the success or failure status of the completion. It is nil if an error occurred. One possible error is that the file is on a file system that does not support completion, in which case the original string will be returned unchanged. Other possible second values are :old, which means that the string completed to the name of a file that exists, :new, which means that the string completed to the name of a file which could be created, and nil again, which means that there is no possible completion.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Brad Parker on June, 13 2006 using texi2html