home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / draco / draco-1.ark / DRIO.REF < prev    next >
Text File  |  1986-11-12  |  12KB  |  231 lines

  1. XIV. The Draco I/O System
  2.  
  3.     Draco now has a formal I/O system based on new 'read' and 'write' 
  4.     constructs added to the language. These constructs are modelled on 
  5.     those of Pascal, but that language's problems with error handling and 
  6.     interactive I/O have been overcome. Simple output to the terminal is 
  7.     done using the 'write' and 'writeln' statements. 'writeln' is identical 
  8.     to 'write' except that it finishes one "line" of output and starts the 
  9.     next. On line-oriented systems such as MTS, the destinction between
  10.     'write' and 'writeln' is much more significant. 
  11.  
  12.     'write' takes each one of it's arguments and writes them on the 
  13.     terminal in text form. The following types can be output in this way: 
  14.     all numeric values, character values, single dimension arrays of 
  15.     characters, pointer to character ('chars') strings, and I/O channels 
  16.     (the associated file name, if any, is written). Numeric output by 
  17.     default uses as few characters as possible to output the value - there 
  18.     are no leading or trailing spaces. Numeric output can be signed, or 
  19.     unsigned in decimal, hexadecimal, octal or binary format. 8 bit values 
  20.     are supported directly, i.e. they are not converted to 16 bit values 
  21.     before output. 
  22.  
  23.     The default format for numeric values is signed decimal for signed 
  24.     values, and unsigned decimal for unsigned values. A different format 
  25.     can be specified by following the numeric expression with a colon and a 
  26.     format specifier (i for signed, u for unsigned decimal, x for 
  27.     hexadecimal, o for octal or b for binary). A fixed field width can be 
  28.     specified by appending a colon and a numeric expression after the value 
  29.     or after the format specification. In case of ambiguity (e.g. variable 
  30.     'i' contains the desired field length), the length can be in 
  31.     parentheses. The output will be right justified in a field of the 
  32.     required length. If the length is negative, the field will be filled 
  33.     with leading zeros instead of spaces. 
  34.  
  35.     For example, assuming the values
  36.  
  37.         i : 123
  38.         j : 12
  39.         n : 60528
  40.         w : 0xabc
  41.  
  42.     the write statement
  43.  
  44.         write(i, n : u, ' ', w:x:-4, i:j)
  45.  
  46.     will produce the following output: (blanks are represented by '_'s)
  47.  
  48.         12360528_0abc_________123
  49.  
  50.     Input is done using the 'read' and 'readln' constructs. No field width 
  51.     specification is allowed, however (fixed format input is for the stone 
  52.     ages). When reading numerics, spaces and tabs are skipped as necessary. 
  53.     Reading continues with all digits which are valid for the base being 
  54.     used. Either lower case or upper case is accepted for hexadecimal 
  55.     digits. If the current input line does not contain the required data, 
  56.     the next input line will NOT be automatically read; instead, the input 
  57.     channel will be flagged as having an error (more on that later). 
  58.  
  59.     When reading arrays of characters, single characters will be read from 
  60.     the input as needed until the entire array is filled or the end of the 
  61.     line is reached. If the end of the line is reached, the remainder of 
  62.     the array is filled with blanks. When reading a character pointer 
  63.     value ('chars' value), the remainder of the current input line (if any) 
  64.     is read into the pointed-to region and is terminated by a '\e'. The 
  65.     input region is assumed to be long enough. Thus, reading a 'chars' 
  66.     value after doing a 'readln' will read the entire next input line. 
  67.  
  68.     I/O defaults to the user's terminal, but can be to/from other places 
  69.     through the use of channels. A channel is strictly typed as either 
  70.     input or output and either text or binary. Channels are a new data type 
  71.     in Draco and can be used as all other types. A channel type consists of 
  72.     the word 'channel', followed by one of 'input' or 'output', followed by 
  73.     one of 'text' or 'binary'. Such channels can be used with read/write by 
  74.     giving a channel expression (usually just the name of a declared 
  75.     channel variable) followed by a semicolon, before any of the values to 
  76.     be read/written. One of the sources/destinations is a file. Files 
  77.     consist of some data structures used by the I/O routines, and a buffer 
  78.     whose size is specified by the programmer. A file type consists of the 
  79.     word 'file' followed by a parenthesized value giving the size in 
  80.     characters (bytes) of the desired buffer. The actual size will be 
  81.     rounded up as required by the host operating system (to the nearest 128 
  82.     for CP/M). If no value is given within the parentheses, a minimum 
  83.     default value will be used. Each file variable can be used as either an 
  84.     input source or an output sink, but not as both at the same time. 
  85.  
  86.     Text channels convert internal representations to/from character form 
  87.     and can only be used with the types given earlier. Binary channels can 
  88.     be used with any type, and do no conversions whatever on the values 
  89.     read or written. Note that transitory values such as pointers, channels 
  90.     and files cannot normally be properly saved and restored between runs. 
  91.  
  92.     Channels must be initialized with the 'open' construct before they can
  93.     be used. There are different forms of 'open' for different kinds of 
  94.     channels. The open construct consists of the word 'open'; followed by a 
  95.     left parenthesis; an expression giving the channel to be opened; and 
  96.     0, 1 or 2 additional parameters, all separated by commas; and a closing 
  97.     right parenthesis. A corresponding 'close' construct is passed only the 
  98.     channel to be closed, all other information has been preserved within 
  99.     the channel itself. All channels that a program opens must be closed by
  100.     that program. (Closing input channels isn't necessary on some systems,
  101.     but it doesn't hurt, and it aids porting to systems that do care.)
  102.  
  103.     If no additional parameters are given to 'open', then the channel is 
  104.     connected to the user's terminal (this provides a way to get normal 
  105.     I/O, but through an explicit channel). A channel can be connected to a 
  106.     memory buffer by providing a character pointer ('chars' value) as a 
  107.     second parameter. The pointed-to buffer is then considered to be a file 
  108.     of text and may contain several lines, separated by carriage-returns 
  109.     and/or linefeeds. Such a buffer used for output is assumed to be large 
  110.     enough for whatever is output to it. When an output channel opened in
  111.     this way is closed, a '\e' is written to the end of the output buffer.
  112.     Only text channels can be connected to 'chars' values. 
  113.  
  114.     The second parameter to 'open' can be a procedure which is to be used 
  115.     to supply or consume the characters or bytes of data. A supplier 
  116.     procedure must have no parameters and must return a character for text 
  117.     input or a byte for binary input. A consumer procedure must have a 
  118.     single character parameter for text output or a single byte parameter 
  119.     for binary output. It must not return any result. Input text channels 
  120.     internally buffer one character, so it is not necessary to have a way 
  121.     to 'unread' a character. This buffering is done in such a way that 
  122.     further input lines are not read until an explicit 'readln' is done, 
  123.     thus allowing input from interactive terminals to operate correctly. As 
  124.     an example, when doing numeric output within a program which uses 
  125.     direct screen I/O through the 'CRT' library, a text output channel 
  126.     which uses the 'CRT_PutChar' routine could be used to position output 
  127.     on the screen. 
  128.  
  129.     If the second parameter to 'open' is a file expression, then the third 
  130.     parameter must be a 'chars' value supplying the name of the file to be 
  131.     opened for I/O. The details of the filename will vary from system to 
  132.     system. 
  133.  
  134.     All of the I/O constructs in Draco return a bool (true/false) value 
  135.     indicating whether or not they succeeded. In many cases (e.g. writing 
  136.     to a 'chars' buffer or through a procedure), success is guaranteed, but 
  137.     some cases provide opportunities for error. A channel which has had an 
  138.     error cannot be used for further I/O; attempts to do so will result in 
  139.     an error message from the I/O routines, and termination of the program. 
  140.     The bool value returned by the I/O constructs is special to the compiler.
  141.     It can be ignored without the compiler complaining. Thus, the I/O
  142.     constructs can be either statements or boolean expressions.
  143.  
  144.     The language construct 'ioerror' can be used to determine the nature of 
  145.     the error, and to reset the channel so that I/O can continue. The 
  146.     open construct will only fail if the channel was being opened on a 
  147.     file and the operating system could not open that file. The most common 
  148.     reason for failure is the end of the input data on a 'read'. This can 
  149.     mean the end of the phyical file when reading binary data, a logical or 
  150.     physical end of file when reading text data, or the end of the string 
  151.     when reading from a 'chars' value. The other common error is that of 
  152.     bad data when reading numeric values from a text channel. If 'ioerror' 
  153.     is given no parameter, then it returns/resets the error code of the 
  154.     default terminal input text channel. Include file 'util.g' contains 
  155.     definitions of the various values returned by 'ioerror', along with 
  156.     declarations of several useful procedures available in the run-time 
  157.     system. 
  158.  
  159.     The following example illustrates many of the ideas discussed. It is a 
  160.     small program which adds up 10 signed decimal integers entered from an 
  161.     interactive terminal. The input numbers can be spread over as many 
  162.     input lines as the user wishes. A prompt of '>' is given to the user. 
  163.  
  164.     \util.g
  165.  
  166.     proc main()void:
  167.         int n, sum, i;
  168.  
  169.         sum := 0;
  170.         write('>');
  171.         for i from 1 upto 10 do
  172.         while
  173.             if read(n) then
  174.             /* got a number! */
  175.             false
  176.             else
  177.             case ioerror()
  178.             incase CH_EOF:
  179.                 writeln("*** You're not done yet! ***");
  180.             incase CH_MISSING:
  181.                 /* nothing left on this line */
  182.                 ;
  183.             default:
  184.                 writeln("*** Invalid number - keep going. ***");
  185.             esac;
  186.             write('>');
  187.             readln();
  188.             true
  189.             fi
  190.         do
  191.         od;
  192.         sum := sum + n;
  193.         od;
  194.         writeln("Sum = ", sum);
  195.     corp;
  196.  
  197.     A slightly smarter program would give more details about what was wrong 
  198.     with the numbers (bad character - use character input to show it, 
  199.     overflow), and would tell the user how many numbers were left to input. 
  200.     The end-of-file condition can only be reset on terminal channels, 
  201.     since when reading from files, procedures, etc. the run-time system has 
  202.     no control over it. Input from a non-interactive source (e.g. a file) 
  203.     is much simpler, in that the run-time system will automatically abort 
  204.     the program on the next I/O request after an error. E.g. the following 
  205.     program writes 100 numbers to a file, then reads them back into an 
  206.     array; 
  207.  
  208.     proc main()void:
  209.         file() f;
  210.         channel input text chin;
  211.         channel output text chout;
  212.         int i;
  213.         [100] int array;
  214.  
  215.         open(chout, f, "NUMBERS.DAT");
  216.         for i from 1 upto 100 do
  217.         write(chout; i, ' ');
  218.         od;
  219.         close(chout);
  220.         open(chin, f, "NUMBERS.DAT");
  221.         for i from 0 upto 99 do
  222.         read(chin; array[i]);
  223.         od;
  224.         close(chin);
  225.     corp;
  226.  
  227.     Note that this program assumes that file "NUMBERS.DAT" exists. It also 
  228.     does not do any 'writeln', so the contents of the file will be one long 
  229.     line. Each 'write' and 'read' could have been changed to 'writeln' and 
  230.     'readln', forcing each number to a separate line. 
  231.