CHAPTER 7 The Lisp Reader 7.1. Introduction The _r_e_a_d function is responsible for converting a stream of characters into a Lisp expression. _R_e_a_d is table driven and the table it uses is called a _r_e_a_d_t_- _a_b_l_e. The _p_r_i_n_t function does the inverse of _r_e_a_d; it converts a Lisp expression into a stream of charac- ters. Typically the conversion is done in such a way that if that stream of characters were read by _r_e_a_d, the result would be an expression equal to the one _p_r_i_n_t was given. _P_r_i_n_t must also refer to the readt- able in order to determine how to format its output. The _e_x_p_l_o_d_e function, which returns a list of charac- ters rather than printing them, must also refer to the readtable. A readtable is created with the _m_a_k_e_r_e_a_d_t_a_b_l_e function, modified with the _s_e_t_s_y_n_t_a_x function and interrogated with the _g_e_t_s_y_n_t_a_x function. The struc- ture of a readtable is hidden from the user - a readtable should only be manipulated with the three functions mentioned above. There is one distinguished readtable called the _c_u_r_r_e_n_t _r_e_a_d_t_a_b_l_e whose value determines what _r_e_a_d, _p_r_i_n_t and _e_x_p_l_o_d_e do. The current readtable is the value of the symbol _r_e_a_d_t_a_b_l_e. Thus it is possible to rapidly change the current syntax by lambda binding a different readtable to the symbol _r_e_a_d_t_a_b_l_e. When the binding is undone, the syntax reverts to its old form. 7.2. Syntax Classes The readtable describes how each of the 128 ascii characters should be treated by the reader and printer. Each character belongs to a _s_y_n_t_a_x _c_l_a_s_s which has three properties: character class - Tells what the reader should do when it sees this The Lisp Reader 7-1 The Lisp Reader 7-2 character. There are a large number of character classes. They are described below. separator - Most types of tokens the reader constructs are one character long. Four token types have an arbitrary length: number (1234), symbol print name (franz), escaped symbol print name (|franz|), and string ("franz"). The reader can easily determine when it has come to the end of one of the last two types: it just looks for the matching delimiter (| or "). When the reader is reading a number or symbol print name, it stops reading when it comes to a character with the _s_e_p_a_r_a_t_o_r property. The separator character is pushed back into the input stream and will be the first character read when the reader is called again. escape - Tells the printer when to put escapes in front of, or around, a symbol whose print name contains this character. There are three possibilities: always escape a symbol with this character in it, only escape a symbol if this is the only charac- ter in the symbol, and only escape a symbol if this is the first character in the symbol. [note: The printer will always escape a symbol which, if printed out, would look like a valid number.] When the Lisp system is built, Lisp code is added to a C-coded kernel and the result becomes the stan- dard lisp system. The readtable present in the C- coded kernel, called the _r_a_w _r_e_a_d_t_a_b_l_e, contains the bare necessities for reading in Lisp code. During the construction of the complete Lisp system, a copy is made of the raw readtable and then the copy is modi- fied by adding macro characters. The result is what is called the _s_t_a_n_d_a_r_d _r_e_a_d_t_a_b_l_e. When a new readt- able is created with _m_a_k_e_r_e_a_d_t_a_b_l_e, a copy is made of either the raw readtable or the current readtable (which is likely to be the standard readtable). 7.3. Reader Operations The reader has a very simple algorithm. It is either _s_c_a_n_n_i_n_g for a token, _c_o_l_l_e_c_t_i_n_g a token, or _p_r_o_c_e_s_s_i_n_g a token. Scanning involves reading charac- ters and throwing away those which don't start tokens (such as blanks and tabs). Collecting means gathering Printed: January 31, 1984 The Lisp Reader 7-3 the characters which make up a token into a buffer. Processing may involve creating symbols, strings, lists, fixnums, bignums or flonums or calling a user written function called a character macro. The components of the syntax class determine when the reader switches between the scanning, collecting and processing states. The reader will continue scan- ning as long as the character class of the characters it reads is _c_s_e_p_a_r_a_t_o_r. When it reads a character whose character class is not _c_s_e_p_a_r_a_t_o_r it stores that character in its buffer and begins the collecting phase. If the character class of that first character is _c_c_h_a_r_a_c_t_e_r, _c_n_u_m_b_e_r, _c_p_e_r_i_o_d, or _c_s_i_g_n. then it will continue collecting until it runs into a character whose syntax class has the _s_e_p_a_r_a_t_o_r property. (That last character will be pushed back into the input buffer and will be the first character read next time.) Now the reader goes into the processing phase, checking to see if the token it read is a number or symbol. It is important to note that after the first character is collected the component of the syntax class which tells the reader to stop collecting is the _s_e_p_a_r_a_t_o_r property, not the character class. If the character class of the character which stopped the scanning is not _c_c_h_a_r_a_c_t_e_r, _c_n_u_m_b_e_r, _c_p_e_r_i_o_d, or _c_s_i_g_n. then the reader processes that character immediately. The character classes _c_s_i_n_g_l_e-_m_a_c_r_o, _c_s_i_n_g_l_e-_s_p_l_i_c_i_n_g-_m_a_c_r_o, and _c_s_i_n_g_l_e- _i_n_f_i_x-_m_a_c_r_o will act like _c_c_h_a_r_a_c_t_e_r if the following token is not a _s_e_p_a_r_a_t_o_r. The processing which is done for a given character class is described in detail in the next section. 7.4. Character Classes _c_c_h_a_r_a_c_t_e_r raw readtable:A-Z a-z ^H !#$%&*,/:;<=>?@^_`{}~ standard readtable:A-Z a-z ^H !$%&*/:;<=>?@^_{}~ A normal character. _c_n_u_m_b_e_r raw readtable:0-9 standard readtable:0-9 This type is a digit. The syntax for an integer (fix- num or bignum) is a string of _c_n_u_m_b_e_r characters optionally followed by a _c_p_e_r_i_o_d. If the digits are not followed by a _c_p_e_r_i_o_d, then they are interpreted Printed: January 31, 1984 The Lisp Reader 7-4 in base _i_b_a_s_e which must be eight or ten. The syntax for a floating point number is either zero or more _c_n_u_m_b_e_r's followed by a _c_p_e_r_i_o_d and then followed by one or more _c_n_u_m_b_e_r's. A floating point number may also be an integer or floating point number followed by 'e' or 'd', an optional '+' or '-' and then zero or more _c_n_u_m_b_e_r's. _c_s_i_g_n raw readtable:+- standard readtable:+- A leading sign for a number. No other characters should be given this class. _c_l_e_f_t_-_p_a_r_e_n raw readtable:( standard readtable:( A left parenthesis. Tells the reader to begin forming a list. _c_r_i_g_h_t_-_p_a_r_e_n raw readtable:) standard readtable:) A right parenthesis. Tells the reader that it has reached the end of a list. _c_l_e_f_t_-_b_r_a_c_k_e_t raw readtable:[ standard readtable:[ A left bracket. Tells the reader that it should begin forming a list. See the description of _c_r_i_g_h_t-_b_r_a_c_k_e_t for the difference between cleft-bracket and cleft- paren. _c_r_i_g_h_t_-_b_r_a_c_k_e_t raw readtable:] standard readtable:] A right bracket. A _c_r_i_g_h_t-_b_r_a_c_k_e_t finishes the forma- tion of the current list and all enclosing lists until it finds one which begins with a _c_l_e_f_t-_b_r_a_c_k_e_t or until it reaches the top level list. _c_p_e_r_i_o_d raw readtable:. standard readtable:. The period is used to separate element of a cons cell [e.g. (a . (b . nil)) is the same as (a b)]. _c_p_e_r_i_o_d is also used in numbers as described above. _c_s_e_p_a_r_a_t_o_r raw readtable:^I-^M esc space standard readtable:^I-^M esc space Separates tokens. When the reader is scanning, these Printed: January 31, 1984 The Lisp Reader 7-5 character are passed over. Note: there is a differ- ence between the _c_s_e_p_a_r_a_t_o_r character class and the _s_e_p_a_r_a_t_o_r property of a syntax class. _c_s_i_n_g_l_e_-_q_u_o_t_e raw readtable:' standard readtable:' This causes _r_e_a_d to be called recursively and the list (quote ) to be returned. _c_s_y_m_b_o_l_-_d_e_l_i_m_i_t_e_r raw readtable:| standard readtable:| This causes the reader to begin collecting characters and to stop only when another identical _c_s_y_m_b_o_l- _d_e_l_i_m_i_t_e_r is seen. The only way to escape a _c_s_y_m_b_o_l- _d_e_l_i_m_i_t_e_r within a symbol name is with a _c_e_s_c_a_p_e char- acter. The collected characters are converted into a string which becomes the print name of a symbol. If a symbol with an identical print name already exists, then the allocation is not done, rather the existing symbol is used. _c_e_s_c_a_p_e raw readtable:\ standard readtable:\ This causes the next character to read in to be treated as a vcharacter. A character whose syntax class is vcharacter has a character class _c_c_h_a_r_a_c_t_e_r and does not have the _s_e_p_a_r_a_t_o_r property so it will not separate symbols. _c_s_t_r_i_n_g_-_d_e_l_i_m_i_t_e_r raw readtable:" standard readtable:" This is the same as _c_s_y_m_b_o_l-_d_e_l_i_m_i_t_e_r except the result is returned as a string instead of a symbol. _c_s_i_n_g_l_e_-_c_h_a_r_a_c_t_e_r_-_s_y_m_b_o_l raw readtable:none standard readtable:none This returns a symbol whose print name is the the sin- gle character which has been collected. _c_m_a_c_r_o raw readtable:none standard readtable:`, The reader calls the macro function associated with this character and the current readtable, passing it no arguments. The result of the macro is added to the structure the reader is building, just as if that form were directly read by the reader. More details on macros are provided below. Printed: January 31, 1984 The Lisp Reader 7-6 _c_s_p_l_i_c_i_n_g_-_m_a_c_r_o raw readtable:none standard readtable:#; A _c_s_p_l_i_c_i_n_g-_m_a_c_r_o differs from a _c_m_a_c_r_o in the way the result is incorporated in the structure the reader is building. A _c_s_p_l_i_c_i_n_g-_m_a_c_r_o must return a list of forms (possibly empty). The reader acts as if it read each element of the list itself without the surround- ing parenthesis. _c_s_i_n_g_l_e_-_m_a_c_r_o raw readtable:none standard readtable:none This causes to reader to check the next character. If it is a _c_s_e_p_a_r_a_t_o_r then this acts like a _c_m_a_c_r_o. Oth- erwise, it acts like a _c_c_h_a_r_a_c_t_e_r. _c_s_i_n_g_l_e_-_s_p_l_i_c_i_n_g_-_m_a_c_r_o raw readtable:none standard readtable:none This is triggered like a _c_s_i_n_g_l_e-_m_a_c_r_o however the result is spliced in like a _c_s_p_l_i_c_i_n_g-_m_a_c_r_o. _c_i_n_f_i_x_-_m_a_c_r_o raw readtable:none standard readtable:none This is differs from a _c_m_a_c_r_o in that the macro func- tion is passed a form representing what the reader has read so far. The result of the macro replaces what the reader had read so far. _c_s_i_n_g_l_e_-_i_n_f_i_x_-_m_a_c_r_o raw readtable:none standard readtable:none This differs from the _c_i_n_f_i_x-_m_a_c_r_o in that the macro will only be triggered if the character following the _c_s_i_n_g_l_e-_i_n_f_i_x-_m_a_c_r_o character is a _c_s_e_p_a_r_a_t_o_r. _c_i_l_l_e_g_a_l raw readtable:^@-^G^N-^Z^\-^_rubout standard readtable:^@-^G^N-^Z^\-^_rubout The characters cause the reader to signal an error if read. 7.5. Syntax Classes The readtable maps each character into a syntax class. The syntax class contains three pieces of information: the character class, whether this is a separator, and the escape properties. The first two properties are used by the reader, the last by the printer (and _e_x_p_l_o_d_e). The initial lisp system has Printed: January 31, 1984 The Lisp Reader 7-7 the following syntax classes defined. The user may add syntax classes with _a_d_d-_s_y_n_t_a_x-_c_l_a_s_s. For each syntax class, we list the properties of the class and which characters have this syntax class by default. More information about each syntax class can be found under the description of the syntax class's character class. vcharacter raw readtable:A-Z a-z ^H !#$%&*,/:;<=>?@^_`{}~ _c_c_h_a_r_a_c_t_e_r standard readtable:A-Z a-z ^H !$%&*/:;<=>?@^_{}~ vnumber raw readtable:0-9 _c_n_u_m_b_e_r standard readtable:0-9 vsign raw readtable:+- _c_s_i_g_n standard readtable:+- vleft-paren raw readtable:( _c_l_e_f_t_-_p_a_r_e_n standard readtable:( _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vright-paren raw readtable:) _c_r_i_g_h_t_-_p_a_r_e_n standard readtable:) _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vleft-bracket raw readtable:[ _c_l_e_f_t_-_b_r_a_c_k_e_t standard readtable:[ _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vright-bracket raw readtable:] _c_r_i_g_h_t_-_b_r_a_c_k_e_t standard readtable:] _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vperiod raw readtable:. _c_p_e_r_i_o_d standard readtable:. _e_s_c_a_p_e_-_w_h_e_n_-_u_n_i_q_u_e vseparator raw readtable:^I-^M esc space _c_s_e_p_a_r_a_t_o_r standard readtable:^I-^M esc space _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r 9 9 Printed: January 31, 1984 The Lisp Reader 7-8 vsingle-quote raw readtable:' _c_s_i_n_g_l_e_-_q_u_o_t_e standard readtable:' _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vsymbol-delimiter raw readtable:| _c_s_i_n_g_l_e_-_d_e_l_i_m_i_t_e_r standard readtable:| _e_s_c_a_p_e_-_a_l_w_a_y_s vescape raw readtable:\ _c_e_s_c_a_p_e standard readtable:\ _e_s_c_a_p_e_-_a_l_w_a_y_s vstring-delimiter raw readtable:" _c_s_t_r_i_n_g_-_d_e_l_i_m_i_t_e_r standard readtable:" _e_s_c_a_p_e_-_a_l_w_a_y_s vsingle-character-symbol raw readtable:none _c_s_i_n_g_l_e_-_c_h_a_r_a_c_t_e_r_-_s_y_m_b_o_l standard readtable:none _s_e_p_a_r_a_t_o_r vmacro raw readtable:none _c_m_a_c_r_o standard readtable:`, _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vsplicing-macro raw readtable:none _c_s_p_l_i_c_i_n_g_-_m_a_c_r_o standard readtable:#; _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vsingle-macro raw readtable:none _c_s_i_n_g_l_e_-_m_a_c_r_o standard readtable:none _e_s_c_a_p_e_-_w_h_e_n_-_u_n_i_q_u_e vsingle-splicing-macro raw readtable:none _c_s_i_n_g_l_e_-_s_p_l_i_c_i_n_g_-_m_a_c_r_o standard readtable:none _e_s_c_a_p_e_-_w_h_e_n_-_u_n_i_q_u_e vinfix-macro raw readtable:none _c_i_n_f_i_x_-_m_a_c_r_o standard readtable:none _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r vsingle-infix-macro raw readtable:none _c_s_i_n_g_l_e_-_i_n_f_i_x_-_m_a_c_r_o standard readtable:none _e_s_c_a_p_e_-_w_h_e_n_-_u_n_i_q_u_e Printed: January 31, 1984 The Lisp Reader 7-9 villegal raw readtable:^@-^G^N-^Z^\-^_rubout _c_i_l_l_e_g_a_l standard readtable:^@-^G^N-^Z^\-^_rubout _e_s_c_a_p_e_-_a_l_w_a_y_s _s_e_p_a_r_a_t_o_r 7.6. Character Macros Character macros are user written functions which are executed during the reading process. The value returned by a character macro may or may not be used by the reader, depending on the type of macro and the value returned. Character macros are always attached to a single character with the _s_e_t_s_y_n_t_a_x function. 7.6.1. Types There are three types of character macros: normal, splicing and infix. These types differ in the arguments they are given or in what is done with the result they return. 7.6.1.1. Normal A normal macro is passed no arguments. The value returned by a normal macro is simply used by the reader as if it had read the value itself. Here is an example of a macro which returns the abbreviation for a given state. ____________________________________________________ ->(_d_e_f_u_n _s_t_a_t_e_a_b_b_r_e_v _n_i_l (_c_d_r (_a_s_s_q (_r_e_a_d) '((_c_a_l_i_f_o_r_n_i_a . _c_a) (_p_e_n_n_s_y_l_v_a_n_i_a . _p_a))))) stateabbrev -> (_s_e_t_s_y_n_t_a_x '_\! '_v_m_a_c_r_o '_s_t_a_t_e_a_b_b_r_e_v) t -> '( ! _c_a_l_i_f_o_r_n_i_a ! _w_y_o_m_i_n_g ! _p_e_n_n_s_y_l_v_a_n_i_a) (ca nil pa) ____________________________________________________ Notice what happened to ! _w_y_o_m_i_n_g. Since it wasn't in the table, the associated function returned nil. The creator of the macro may have wanted to leave the list alone, in such a case, but couldn't Printed: January 31, 1984 The Lisp Reader 7-10 with this type of reader macro. The splicing macro, described next, allows a character macro function to return a value that is ignored. 7.6.1.2. Splicing The value returned from a splicing macro must be a list or nil. If the value is nil, then the value is ignored, otherwise the reader acts as if it read each object in the list. Usually the list only contains one element. If the reader is reading at the top level (i.e. not collecting elements of list), then it is illegal for a splicing macro to return more then one element in the list. The major advantage of a splicing macro over a normal macro is the abil- ity of the splicing macro to return nothing. The comment character (usually ;) is a splicing macro bound to a function which reads to the end of the line and always returns nil. Here is the previous example written as a splicing macro ____________________________________________________ -> (_d_e_f_u_n _s_t_a_t_e_a_b_b_r_e_v _n_i_l ((_l_a_m_b_d_a (_v_a_l_u_e) (_c_o_n_d (_v_a_l_u_e (_l_i_s_t _v_a_l_u_e)) (_t _n_i_l))) (_c_d_r (_a_s_s_q (_r_e_a_d) '((_c_a_l_i_f_o_r_n_i_a . _c_a) (_p_e_n_n_s_y_l_v_a_n_i_a . _p_a)))))) -> (_s_e_t_s_y_n_t_a_x '! '_v_s_p_l_i_c_i_n_g-_m_a_c_r_o '_s_t_a_t_e_a_b_b_r_e_v) -> '(!_p_e_n_n_s_y_l_v_a_n_i_a ! _f_o_o !_c_a_l_i_f_o_r_n_i_a) (pa ca) -> '!_f_o_o !_b_a_r !_p_e_n_n_s_y_l_v_a_n_i_a pa -> ____________________________________________________ 7.6.1.3. Infix Infix macros are passed a _c_o_n_c structure representing what has been read so far. Briefly, a tconc structure is a single list cell whose car points to a list and whose cdr points to the last list cell in that list. The interpretation by the reader of the value Printed: January 31, 1984 The Lisp Reader 7-11 returned by an infix macro depends on whether the macro is called while the reader is con- structing a list or whether it is called at the top level of the reader. If the macro is called while a list is being constructed, then the value returned should be a tconc structure. The car of that structure replaces the list of elements that the reader has been collecting. If the macro is called at top level, then it will be passed the value nil, and the value it returns should either be nil or a tconc struc- ture. If the macro returns nil, then the value is ignored and the reader continues to read. If the macro returns a tconc structure of one ele- ment (i.e. whose car is a list of one element), then that single element is returned as the value of _r_e_a_d. If the macro returns a tconc structure of more than one element, then that list of elements is returned as the value of read. ____________________________________________________ -> (_d_e_f_u_n _p_l_u_s_o_p (_x) (_c_o_n_d ((_n_u_l_l _x) (_t_c_o_n_c _n_i_l '_\+)) (_t (_l_c_o_n_c _n_i_l (_l_i_s_t '_p_l_u_s (_c_a_a_r _x) (_r_e_a_d)))))) plusop -> (_s_e_t_s_y_n_t_a_x '_\+ '_v_i_n_f_i_x-_m_a_c_r_o '_p_l_u_s_o_p) t -> '(_a + _b) (plus a b) -> '+ |+| -> ____________________________________________________ 7.6.2. Invocations There are three different circumstances in which you would like a macro function to be trig- gered. _A_l_w_a_y_s - Whenever the macro character is seen, the macro should be invoked. This is accomplished by using the character classes _c_m_a_c_r_o, Printed: January 31, 1984 The Lisp Reader 7-12 _c_s_p_l_i_c_i_n_g-_m_a_c_r_o, or _c_i_n_f_i_x-_m_a_c_r_o, and by using the _s_e_p_a_r_a_t_o_r property. The syntax classes vmacro, vsplicing-macro, and vsingle-macro are defined this way. _W_h_e_n _f_i_r_s_t - The macro should only be triggered when the macro character is the first character found after the scanning process. A syntax class for a _w_h_e_n _f_i_r_s_t macro would be defined using _c_m_a_c_r_o, _c_s_p_l_i_c_i_n_g-_m_a_c_r_o, or _c_i_n_f_i_x-_m_a_c_r_o and not including the _s_e_p_a_r_a_t_o_r property. _W_h_e_n _u_n_i_q_u_e - The macro should only be triggered when the macro character is the only character col- lected in the token collection phase of the reader, i.e the macro character is preceeded by zero or more _c_s_e_p_a_r_a_t_o_rs and followed by a _s_e_p_a_r_a_t_o_r. A syntax class for a _w_h_e_n _u_n_i_q_u_e macro would be defined using _c_s_i_n_g_l_e-_m_a_c_r_o, _c_s_i_n_g_l_e-_s_p_l_i_c_i_n_g-_m_a_c_r_o, or _c_s_i_n_g_l_e-_i_n_f_i_x-_m_a_c_r_o and not including the _s_e_p_a_r_a_t_o_r property. The syntax classes so defined are vsingle-macro, vsingle-splicing-macro, and vsingle-infix- macro. 7.7. Functions (setsyntax 's_symbol 's_synclass ['ls_func]) WHERE: ls_func is the name of a function or a lambda body. RETURNS: t SIDE EFFECT: S_symbol should be a symbol whose print name is only one character. The syntax class for that character is set to s_synclass in the current readtable. If s_synclass is a class that requires a character macro, then ls_func must be sup- plied. NOTE: The symbolic syntax codes are new to Opus 38. For compatibility, s_synclass can be one of the fixnum syntax codes which appeared in older ver- sions of the FRANZ LISP Manual. This compatibil- ity is only temporary: existing code which uses the fixnum syntax codes should be converted. 9 9 Printed: January 31, 1984 The Lisp Reader 7-13 (getsyntax 's_symbol) RETURNS: the syntax class of the first character of s_symbol's print name. s_symbol's print name must be exactly one character long. NOTE: This function is new to Opus 38. It supercedes (_s_t_a_t_u_s _s_y_n_t_a_x) which no longer exists. (add-syntax-class 's_synclass 'l_properties) RETURNS: s_synclass SIDE EFFECT: Defines the syntax class s_synclass to have properties l_properties. The list l_properties should contain a character classes mentioned above. l_properties may contain one of the escape properties: _e_s_c_a_p_e-_a_l_w_a_y_s, _e_s_c_a_p_e-_w_h_e_n-_u_n_i_q_u_e, or _e_s_c_a_p_e-_w_h_e_n-_f_i_r_s_t. l_properties may con- tain the _s_e_p_a_r_a_t_o_r property. After a syn- tax class has been defined with _a_d_d- _s_y_n_t_a_x-_c_l_a_s_s, the _s_e_t_s_y_n_t_a_x function can be used to give characters that syntax class. ____________________________________________________ ; Define a non-separating macro character. ; This type of macro character is used in UCI-Lisp, and ; it corresponds to a FIRST MACRO in Interlisp -> (_a_d_d-_s_y_n_t_a_x-_c_l_a_s_s '_v_u_c_i-_m_a_c_r_o '(_c_m_a_c_r_o _e_s_c_a_p_e-_w_h_e_n-_f_i_r_s_t)) vuci-macro -> ____________________________________________________ 9 9 Printed: January 31, 1984