REF CHARIO John Gibson Jul 1993 COPYRIGHT University of Sussex 1993. All Rights Reserved. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<< CHARACTER STREAM >>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<< INPUT AND OUTPUT >>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Character stream input and output is the simplest form of I/O in Poplog. This REF file details the procedures, etc, associated with standard character repeaters and consumers, and the creation of new repeaters and consumers. CONTENTS - (Use <ENTER> g to access required sections) 1 Introduction 2 Standard Character Repeaters 3 Standard Character Consumers 4 Raw Mode Repeaters/Consumers 5 Creating New Repeaters/Consumers --------------- 1 Introduction --------------- Character streams are the simplest form of input/output in Poplog. They are used by many parts of the system, including the Pop-11 compiler and printing utilities. For more complex I/O facilities using device records, see REF * SYSIO Character stream I/O is performed using character repeater and consumer procedures. A character repeater is a procedure which each time it is called returns the next character from an input stream; a character consumer takes a character as argument and writes it to an output stream. Character streams are terminated by the special item <termin> (the value of the constant termin); a character repeater will return <termin> when an input stream is exhausted, and giving <termin> to a character consumer will close its output stream. See also REF * ITEMISE, which describes the procedure incharitem for turning character repeaters into item repeaters. REF * POPCOMPILE explains how a text item stream is created from a character stream for the Pop11 compilation process. ------------------------------- 2 Standard Character Repeaters ------------------------------- charin() -> char [procedure] This is a character repeater for the current standard input channel, i.e. it reads characters from the device pop_charin_device (normally in interactive mode this is a system device that inputs from the user's terminal/window etc, but when in Ved interactive mode, it is a pseudo `user' device which reads input from the current Ved input buffer). The prompt string output by charin is determined by popprompt (see REF * popprompt). If the character read in is `\^G` (CTRL-G) then charin invokes setpop (This mechanism may be withdrawn, as it is a relic of earlier versions of Pop-2). If the last character read in was a newline character (poplastchar == `\n`), and the next character read in is char, charin checks to see whether char is in the list pop_charin_escapes, in which case it will spawn a DCL process (in VMS) or Shell process (in Unix) and hand the rest of the line as a command to be run by that process, using sysobey. The character char is given to sysobey as its second argument. When sysobey returns, charin assigns the newline character to char. Before finally returning, charin assigns char to poplastchar then checks whether poplogfile is a procedure, in which case it is applied to char. This provides a simple logging mechanism. REF * ITEMISE explains how an "item-repeater" can be created from a character repeater like charin, and REF * POPCOMPILE explains how program text read in from the standard input is compiled. HELP * IM explains how charin is made to read from the Ved buffer. The character returned by charin is normally an ASCII character code, but if the "end of file" character was typed at the terminal, or if the device has been "emptied" then it returns the special object <termin>, as explained in the Overview, above. (Note that before reading a character from pop_charin_device, charin first calls the trap procedure pop_chario_trap with the device and true as arguments, i.e. pop_chario_trap(pop_charin_device, true) See pop_chario_trap below.) pop_charin_escapes -> list [variable] list -> pop_charin_escapes This list is examined by charin as explained above, whenever a character is read in immediately after a newline character. If the new character is a member of pop_charin_escapes then charin uses sysobey to spawn a sub-process given the rest of the input line as a command. In VMS the list pop_charin_escapes defaults to [`$`] and on Unix to [ `%` `$` `!`], i.e. the characters that can be given as second argument to sysobey. The procedure vedsetpop sets pop_charin_escapes locally to [], so that the mechanism will not be triggered accidentially in Ved immediate in mode (See HELP * IM) or in processes that compile from the Ved buffer (See HELP * LMR). (Ved allows an alternative mechanism for spawning sub-processes from the command line, as described in HELP VEDCOMMS) poplastchar -> char [variable] char -> poplastchar Always contains the last character read by charin. poplinenum -> int [protected variable] This integer variable is incremented whenever a newline character is read by charin or a character repeater created by discin. poplinenum is local to pop11_compile where it is initialised to 1: hence it records the number of newline characters read in since the beginning of the call of pop11_compile (and is used by * sys_pr_message in printing mishap and warning messages). poplogfile -> char_cons_or_false [variable] false_or_char_cons -> poplogfile This variable may contain a character consumer procedure or false. In the former case every character read by charin, or output by charout is also given to poplogfile (including prompts). This can be used to record terminal interactions (for an example of which, see LIB * RECORD). (Default value false) termin -> <termin> [constant] termin_key -> key [constant] The value of termin is the unique item <termin>, used as an end-of-file marker for character/item stream I/O (and also for dynamic list streams, see REF * LISTS). termin_key is a constant holding the key structure of the unique item <termin> (see REF * KEYS). pop_chario_trap(dev, is_input) [protected procedure variable] The procedure in this variable is called by charin, charout and charerr before doing anything; it is redefined in various contexts, e.g. in Ved, and is intended for system use only. (If a new trap procedure trap_p is to be added, it must be concatenated onto the existing value, i.e. trap_p <> pop_chario_trap -> pop_chario_trap; where trap_p is defined as trap_p(dev, is_input) -> (dev, is_input); that is, passes on the arguments given to it to the next procedure in the chain.) ------------------------------- 3 Standard Character Consumers ------------------------------- charout(char) [procedure] charerr(char) [procedure] These are character consumers for the current standard output and error output channels respectively, i.e. characters are output via the devices pop_charout_device and pop_charerr_device respectively (normally in interactive mode these are system devices that output to the user's terminal/window etc, but when in Ved interactive mode, they are pseudo `user' devices which output to the current Ved output buffer). (Note that before writing a character to pop_charX_device, these procedures first call the trap procedure pop_chario_trap with the device and false as arguments, i.e. pop_chario_trap(pop_charX_device, false) See pop_chario_trap above.) pop_charout_col -> int [variable] int -> pop_charout_col pop_charerr_col -> int [variable] int -> pop_charerr_col These variables contain integers representing the number of columns filled by charout and charerr respectively in their current lines, where tab characters count as vedindentstep columns if in Ved or 8 otherwise, control characters (i.e. ASCII value < 32) count as none, and all other characters count as 1. These values are reset to 0 on outputting a newline character. poplinewidth -> int [variable] int -> poplinewidth poplinemax -> int [variable] int -> poplinemax When poplinewidth is an integer, these two variables together control the breaking of long lines by charout and charerr. If on outputting a character with charX, pop_charX_col is greater than or equal to poplinewidth, and either the current character for output is a space or tab, OR the column count is already greater than or equal to poplinemax, then an automatic linebreak is inserted before printing the character. (In other words, lines are broken at the next whitespace character after poplinewidth columns, or failing that after poplinemax columns. Note that if a line is broken at a space or tab, that character is NOT output.) A linebreak consists of a newline followed by any continuation-line prefix characters specified by * poplineprefix (qv). If poplinewidth is not an integer, linebreaks are not inserted. poplinewidth defaults to 70, and poplinemax to 78. poplineprefix -> pair_or_false [variable] pair_or_false -> poplineprefix This variable enables automatic prefixing of lines output via charout and charerr. It may be false, or a pair whose front or back are each either a string or false. If poplineprefix is a pair whose front is a string, that string is output at the beginning of every line (that is, when charX is called with pop_charX_col = 0). If poplineprefix is a pair whose back is a string, that string is output instead at the beginning of every continuation line, i.e. after an automatic newline inserted by the poplinewidth mechanism. If poplineprefix is not a pair, or the back is not a string, automatic newlines are followed by any 'every-line' prefix specified, plus a single tab character. cucharout(char) [procedure variable] cucharerr(char) [procedure variable] These procedure variables contain the current character consumers for standard output and error output. All printing utilities in Poplog use cucharout to produce output, and all error printing is done via cucharerr. The standard values of these variables are charout and charerr respectively. cuchartrace -> char_cons [variable] char_cons -> cuchartrace If this variable is false then cucharout is used for tracing output. Otherwise the character consumer cuchartrace contains is used instead. Assigning a character consumer to this variable enables trace printing to be separated from normal printout. pop_buffer_charout -> bool [variable] bool -> pop_buffer_charout This boolean variable controls whether normal-mode character output to terminals is buffered within each line; if false, each character is output immediately (it therefore affects charout and charerr when these reference terminals). See REF * SYSIO ------------------------------- 4 Raw Mode Repeaters/Consumers ------------------------------- rawcharin() -> char [procedure] This repeater reads characters from the device poprawdevin (giving 'raw mode' input from the terminal). See REF * SYSIO rawcharout(char_or_string) [procedure] This consumer writes characters to the device poprawdevout (giving buffered 'raw mode' output to the terminal). It can take either a single character or a byte vector. See REF * SYSIO rawsubstringout(string, index, num); [procedure] Just like rawcharout, but outputs num characters, starting at index, from string. See REF * SYSIO rawoutflush() [procedure] Flushes poprawdevout, i.e. writes out any outstanding characters in the buffer. Same as sysflush(poprawdevout). charin_timeout(hsecs) -> char [procedure] Returns the first character read from the terminal with rawcharin during the time-span hsecs, or false if none were available. hsecs is measured in hundredths of a second (but rounded to the nearest whole second). (This procedure is implemented in terms of pop_timeout_secs and pop_timeout, see REF * SYSIO). ----------------------------------- 5 Creating New Repeaters/Consumers ----------------------------------- bits_out(filename, n, signed) -> int_consumer [procedure] bits_in(filename, n, signed) -> int_repeater [procedure] The bits_in/bits_out mechanism facilitates compact storage of a series of integers. For example, the data for a binary array could be stored using 1/8 the space used by simply printing the numbers to disk. For both procedures, the argument filename may be a file name string, or a device. The n argument specifies the bitsize of the integers; if the boolean argument signed is true, the integers are signed, otherwise unsigned. bits_out returns an 'integer consumer' procedure int_consumer for the specified file. Successive calls of int_consumer write n-bit integers to the file, i.e. int_consumer(int_or_termin); bits_in returns an 'integer repeater' procedure int_repeater linked to the specified file (normally, one created with bits_out). Successive calls of int_repeater read n-bit integers from the file, i.e. int_repeater() -> int_or_termin discin(filename) -> char_rep [procedure] Returns a character repeater for the filename filename, which may be a string or word -- if a word then pop_default_type is appended to the name (see below). Note that, despite the name of this procedure, filename is not restricted to being a disk file; it may be any suitable operating system device. (The device is opened using sysopen(filename, 0, false, `N`) -> dev; i.e. a disk file is assumed to be a text file. See the description of the third argument to sysopen in REF * SYSIO.) A mishap will result if the specified file cannot be opened. filename may also be a device record open for reading, e.g. a device created by sysopen or syspipe (in Unix) or sysmailbox (in VMS). In that case a character repeater for the device is returned. This technique can be used for 'binary' disk files, e.g. sysopen(filename, 0, true, `N`) -> dev; discin(dev) -> char_rep; discout(filename) -> char_cons [procedure] Returns a character consumer for the filename filename (which is as for discin). If filename is a disk file, then a new file is created, otherwise the file is simply opened. (The device is created using syscreate(filename, 1, false) -> dev; i.e. a disk file is assumed to be a text file. See the description of the third argument to syscreate in REF * SYSIO.) A mishap will result if the specified file cannot be created or opened. filename may also be a device record open for writing, in which case a character consumer for that device is returned. As with discin, this technique can be used for 'binary' disk files, e.g. syscreate(filename, 1, true) -> dev; discout(dev) -> char_cons; discappend(filename) -> char_cons [procedure] Opens an existing file, and returns a character consumer char_cons that will append characters to the file (i.e. will actually update an existing disk file). filename is as for discin. discin_device(char_rep) -> dev [procedure] discin_device(char_rep, mishap) -> dev_or_false Given a character repeater procedure char_rep, returns the device record dev associated with it. If char_rep was not created by discin, a mishap occurs unless the optional boolean argument mishap is supplied and is false (in which case false is returned). discout_device(char_cons) -> dev [procedure] Returns the device record dev associated with the character consumer procedure char_cons. An error is signalled if char_cons was not created by discout. pop_default_type -> string [variable] string -> pop_default_type The string in this variable (default value '.p') is used as the default file type/extension by discin, discout and discappend, and is concatenated onto a word argument given to these procedures (but not onto a string argument). sysisprogfile(filename) -> bool [procedure] Where filename is a string, returns true if filename has the file type/extension given by pop_default_type, false otherwise. stringin(string) -> char_rep [procedure] Returns a character repeater for the string string, i.e. a procedure which each time it is called produces the next character from the string, and <termin> when the string is exhausted. isclosed(item, mishap) -> bool [procedure] isclosed(item) -> bool For item a device, this procedure returns true if the device is closed, false if it is still open. For item a character repeater produced by discin or stringin, it returns true if the repeater is exhausted (i.e. would return <termin> if called), or false if it still has characters available. For a character consumer produced by discout, it returns true if <termin> has been given to the consumer. The mishap argument is a boolean controlling what happens if item is not one of the above: if false, the procedure returns "undef", otherwise a mishap occurs. The mishap argument defaults to true if omitted. +-+ C.all/ref/chario +-+ Copyright University of Sussex 1993. All rights reserved.