{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}