{Begin SubSec Input Functions}
{Title Input Functions}
{Text

{index *PRIMARY* Input functions}

While the functions described below can take input from any stream, some special actions occur when the input is from the terminal{index Terminal Streams}{index T (Terminal stream)} (the  {lisp T} input stream, see {PageRef Term Terminal streams}).  When reading from the terminal, the input is buffered a line at a time, unless buffering has been inhibited by {fn CONTROL} ({PageRef Fn CONTROL}) or the input is being read by {fn READC} or {fn PEEKC} ({PageRef Fn READC}).  Using specified editing characters, the user can erase a character at a time, a word at a time, or the whole line.  The keys that perform these editing functions are assignable via {fn SETSYNTAX} ({PageRef Fn SETSYNTAX}), with the initial settings chosen to be those most natural for the given operating system.  In Interlisp-D, the initial settings are as follows: characters are deleted one at a time by {index Backspace}Backspace; words are erased by {index control-W}control-W; the whole line is erased by {index control-Q}control-Q.

On the Interlisp-D display, deleting a character or a line causes the characters to be physically erased from the screen.  In Interlisp-10, the deleting action can be modified for various types of display terminals by using {fn DELETECONTROL} ({PageRef Fn DELETECONTROL}).

Unless otherwise indicated, when the end of file is encountered while reading from a file, all input functions generate an error, {index END OF FILE Error}{lisp END OF FILE}.  Note that this does not close the input file.  The {lisp ENDOFSTREAMOP} stream attribute ({PageRef (File Attribute) ENDOFSTREAMOP}) is useful for changing the behavior at end of file.

Most input functions have a {arg RDTBL} argument, which specifies the read table{index read tables} to be used for input (see {PageRef Term Read Tables}).   Unless otherwise specified, if {arg RDTBL} is {lisp NIL}, the primary read table is used.{index primary read table}

If the {arg FILE} or {arg STREAM} argument to an input function is {lisp NIL}, the {index Primary streams}primary input stream is used (see {PageRef Term Primary streams}).

{FnDef {FnName INPUT} {FnArgs FILE}
{Text
Sets {arg FILE} as the {index *PRIMARY* Primary input stream}primary input stream; returns the old primary input stream.  {arg FILE} must be open for input.

{lisp (INPUT)} returns the current primary input stream, which is not changed.

Note:  If the primary input stream is set to a file, the file's full name, rather than the stream itself, is returned.  See discussion on {PageRef Tag StreamFileNames}.
}}


{FnDef {FnName READ} {FnArgs FILE RDTBL FLG}
{Text
Reads one expression from {arg FILE}.  Atoms are delimited by the break and separator characters as defined in {arg RDTBL}.  To include a break or separator character in an atom, the character must be preceded by the character {lisp %},{index *PRIMARY* %} e.g., {lisp AB%(C} is the atom {lisp AB(C}, {lisp %%} is the atom {lisp %}, {lisp %}{it control-K} is the atom control-K.  For input from the terminal, an atom containing an interrupt character can be input by typing instead the corresponding alphabetic character preceded by control-V{index control-V}, e.g., {lisp ↑VD} for control-D.

Strings{index Strings} are delimited by double quotes.{index " (string delimiter)}  To input a string containing a double quote or a %, precede it by %,{index %} e.g., {lisp "AB%"C"} is the string {lisp AB"C}.  Note that % can always be typed even if next character is not "special", e.g., {lisp %A%B%C} is read as {lisp ABC}.

If an atom is interpretable as a number, {index READ FN}{fn READ} creates a number, e.g., {lisp 1E3}{index E (in a floating point number)} reads as a floating point number,{index floating point numbers} {lisp 1D3} as a literal atom, {lisp 1.0} as a number, {lisp 1,0} as a literal atom, etc.  {index Integer input syntax}An integer can be input in a non-decimal radix by using syntax such as {lisp 123Q}, {lisp |b10101}, {lisp |5r1234} (see {PageRef Term Integer input syntax}).  The function {index RADIX Fn}{fn RADIX} ({PageRef Fn RADIX}), sets the radix used to print integers.

When reading from the {index terminal input/output}terminal, all input is line-buffered{index line-buffering} to enable the action of the backspacing control characters, unless inhibited by {index CONTROL FN}{fn CONTROL} ({PageRef Fn CONTROL}).  Thus no characters are actually seen by the program until a carriage-return{index carriage-return} (actually the character with terminal syntax class {lisp EOL}, see {PageRef (Syntax Class) EOL}), is typed.  However, for reading by {fn READ}, when a matching right parenthesis is encountered,{index *PRIMARY* Parentheses counting by READ} the effect is the same as though a carriage-return were typed, i.e., the characters are transmitted.  To indicate this, Interlisp also prints a carriage-return line-feed on the terminal.  The line buffer is also transmitted to {fn READ} whenever an {lisp IMMEDIATE} read macro character is typed ({PageRef (Type of Read Macro) IMMEDIATE}).


{arg FLG}={lisp T} suppresses the carriage-return normally typed by {fn READ} following a matching right parenthesis.  (However, the characters are still given to {fn READ}; i.e., the user does not have to type the carriage-return.)
{note a peculiar feature--bvm}

}}{comment endfndef READ}




{FnDef {FnName RATOM} {FnArgs FILE RDTBL}
{Text
Reads in one atom from {arg FILE}.  Separation of atoms is defined by {arg RDTBL}.  {lisp %}{index %} is also defined for {fn RATOM}, and the remarks concerning line-buffering{index line-buffering} and editing control characters also apply.

If the characters comprising the atom would normally be interpreted as a number by {fn READ}, {index numbers}that number is returned by {fn RATOM}.  Note however that {fn RATOM} takes no special action for {lisp "}{index " (string delimiter)} whether or not it is a break character, i.e., {index RATOM FN}{fn RATOM} never makes a string.
}}


{FnDef {FnName RSTRING} {FnArgs FILE RDTBL}
{Text
Reads characters from {arg FILE} up to, but not including, the next break or separator
character, and returns them as a string.  Backspace, control-W, control-Q, control-V, and {lisp %} have the same effect as with {fn READ}.
}}


{index Break characters}
{index Separator characters}


Note that the break or separator character that terminates a call to {index RATOM FN}{fn RATOM} or {index RSTRING FN}{fn RSTRING} is {emphasize not} read by that call, but remains in the buffer to become the first character seen by the next reading function that is called.  If that function is {fn RSTRING}, it will return the null string.  This is a common source of program bugs.



{FnDef {FnName RATOMS} {FnArgs A FILE RDTBL}
{Text
Calls {fn RATOM} repeatedly until the atom {arg A} is read.  Returns a list of the atoms read, not including {arg A}.
}}


{FnDef {FnName RATEST} {FnArgs FLG}
{Text
If {arg FLG} = {lisp T}, {fn RATEST} returns {lisp T} if a separator was encountered immediately prior to the atom returned by the last {fn RATOM} or {fn READ}, {lisp NIL} otherwise.

If {arg FLG} = {lisp NIL}, {fn RATEST} returns {lisp T} if last atom read by {fn RATOM} or {fn READ} was a break character, {lisp NIL} otherwise.

If {arg FLG} = {lisp 1}, {fn RATEST} returns {lisp T} if last atom read (by {fn READ} or {fn RATOM}) contained a {lisp %} used to quote the next character (as in {lisp %[} or {lisp %A%B%C}), {lisp NIL} otherwise.

{note Does anyone ever use this bizarre function?  --bvm}
}}


{FnDef {FnName READC} {FnArgs FILE RDTBL}
{Text
Reads and returns the next character, including {lisp %}, {lisp "}, etc, i.e., is not affected by break or separator characters.  The action of {fn READC} is subject to line-buffering, i.e., {fn READC} does not return a value until the line has been terminated even if a character has been typed.  Thus, the editing control characters have their usual effect.  {arg RDTBL} does not directly affect the value returned, but is used as usual in line-buffering, e.g., determining when input has been terminated.  If {index CONTROL FN}{lisp (CONTROL T)} has been executed ({PageRef Fn CONTROL}), defeating line-buffering,{index line-buffering} the {arg RDTBL} argument is irrelevant, and {fn READC} returns a value as soon as a character is typed (even if the character typed is one of the editing characters, which ordinarily would never be seen in the input buffer).
}}


{FnDef {FnName PEEKC} {FnArgs FILE {anonarg}}
{Text
Returns the next character, but does not actually read it and remove it from the buffer.  If reading from the terminal, the character is echoed as soon as {fn PEEKC} reads it, even though it is then "put back" into the system buffer, where backspace, control-W, etc. could change it.  Thus it is possible for the value returned by {fn PEEKC} to "disagree" in the first character with a subsequent {fn READ}.

{note It appears that the second arg to PEEKC, FLG, is ignored in Interlisp-D --bvm
removed line: If FLG=NIL, PEEKC is not subject to line-buffering, i.e., it returns a value as soon as a character has been typed.  --mjs}
}}

{FnDef {FnName LASTC} {FnArgs FILE}
{Text
Returns the last character read from {arg FILE}.
}}


{FnDef {Name READCCODE} {Args FILE RDTBL}
{Text
Returns the next character {it code} from {arg STREAM}; thus, this operation is equivalent to, but more efficient than, {lisp (CHCON1 (READC {arg FILE} {arg RDTBL}))}.
}}


{FnDef {Name PEEKCCODE} {Args FILE {anonarg}}
{Text
Returns, without consuming, the next character {it code} from {arg STREAM}; thus, this operation is equivalent to, but more efficient than, {lisp (CHCON1 (PEEKC {arg FILE}))}.
}}


{FnDef {Name BIN} {Args STREAM}
{Text
Returns the next byte from {arg STREAM}.  This operation is useful for reading streams of binary, rather than character, data.
}}

Note:  {fn BIN} is similar to {fn READCCODE}, except that {fn BIN} always reads a single byte, whereas {fn READCCODE} reads a "character" that can consist of more than one byte, depending on the character and its encoding (see {index NS character I/O}{PageRef Term NS character I/O}).




{fn READ}, {fn RATOM}, {fn RATOMS}, {fn PEEKC}, {fn READC} all wait for input if there is none. The only way to test whether or not there is input is to use {fn READP}:


{FnDef {FnName READP} {FnArgs FILE FLG}
{Text
Returns {lisp T} if there is anything in the input buffer{index input buffer} of {arg FILE}, {lisp NIL} otherwise.  This operation is only interesting for streams whose source of data is dynamic, e.g., the terminal or a byte stream over a network; for other streams, such as to files, {lisp (READP {arg FILE})} is equivalent to {lisp (NOT (EOFP {arg FILE}))}.

Note that because of line-buffering,{index line-buffering} {fn READP} may return {lisp T}, indicating there is input in the buffer, but {fn READ} may still have to wait.

{note the following is an awful crock that we may want to fix or tone down some --bvm}

Frequently, the terminal's input buffer contains a single {lisp EOL} character left over from a previous input.  For most applications, this situation wants to be treated as though the buffer were empty, and so {fn READP} returns {lisp NIL} in this case.  However, if {arg FLG}={lisp T}, {fn READP} returns {lisp T} if there is {it any} character in the input buffer, including a single {lisp EOL}.  {arg FLG} is ignored for streams other than the terminal.
}}

{FnDef {FnName EOFP} {FnArgs FILE}
{Text
Returns true if {arg FILE} is at "end of file", i.e., the next call to an input function would cause an {lisp END OF FILE}{index END OF FILE Error} error; {lisp NIL} otherwise.  For randomly accessible files ({PageRef tag RandomIO}), this can also be thought of as the file pointer pointing beyond the last byte of the file.  {arg FILE} must be open for (at least) input, or an error is generated, {lisp FILE NOT OPEN}{index FILE NOT OPEN Error}.

Note that {fn EOFP} can return {lisp NIL} and yet the next call to {fn READ} might still cause an {lisp END OF FILE} error, because the only characters remaining in the input were separators or otherwise constituted an incomplete expression.  The function {fn SKIPSEPRS} ({PageRef Fn SKIPSEPRS}) is sometimes more useful as a way of detecting end of file when it is known that all the expressions in the file are well formed.
}}


{FnDef {FnName WAITFORINPUT} {FnArgs FILE}
{Text
Waits until input is available from {arg FILE} or from the terminal, i.e. from {lisp T}.  {fn WAITFORINPUT} is functionally equivalent to {lisp (until (OR (READP T) (READP FILE)) do NIL)}, except that it does not use up machine cycles while waiting.  Returns the device for which input is now available, i.e. {arg FILE} or {lisp T}.

{arg FILE} can also be an integer, in which case {fn WAITFORINPUT} waits until there is input available from the terminal, or until {arg FILE} milliseconds have elapsed. Value is {lisp T} if input is now available, {lisp NIL} in the case that {fn WAITFORINPUT} timed out.
}}



{note SKREAD was written by J. W. Goodwin.}

{FnDef {FnName SKREAD} {FnArgs FILE REREADSTRING RDTBL}
{Text
"Skip Read".  {fn SKREAD} consumes characters from {arg FILE} as if one call to {fn READ} had been performed, without paying the storage and compute cost to really read in the structure.  {arg REREADSTRING} is for the case where the caller has already performed some {fn READC}'s and {fn RATOM}'s before deciding to skip this expression.  In this case, {arg REREADSTRING} should be the material already read (as a string), and {fn SKREAD} operates as though it had seen that material first, thus setting up its parenthesis count, double-quote count, etc.

The read table {arg RDTBL} is used for reading from {arg FILE}.  If {arg RDTBL} is {lisp NIL}, it defaults to the value of {index FILERDTBL Var}{var FILERDTBL}.  {fn SKREAD} may have difficulties if unusual read macros ({PageRef Term Read macros}) are defined in {arg RDTBL}.  {fn SKREAD} does not recognize read macro characters in {arg REREADSTRING}, nor {lisp SPLICE} or {lisp INFIX} read macros.  This is only a problem if the read macros are defined to parse subsequent input in the stream that does not follow the normal parenthesis and string-quote conventions. 

{fn SKREAD} returns {lisp %)} if the read terminated on an unbalanced closing parenthesis; {lisp %]} if the read terminated on an unbalanced {lisp %]}, i.e., one which also would have closed any extant open left parentheses; otherwise {lisp NIL}.
}}


{FnDef {FnName SKIPSEPRS} {FnArgs FILE RDTBL}
{Text
Consumes characters from {arg FILE} until it encounters a non-separator character (as defined by {arg RDTBL}).  {fn SKIPSEPRS} returns, but does not consume, the terminating character, so that the next call to {fn READC} would return the same character.  If no non-separator character is found before the end of file is reached, {fn SKIPSEPRS} returns {lisp NIL} and leaves the stream at end of file.  This function is useful for skipping over "white space" when scanning a stream character by character, or for detecting end of file when reading expressions from a stream with no pre-arranged terminating expression. 
}}



}{End SubSec Input Functions}