home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / LANGUAGS / PASCAL / PASCALIO.DOC < prev    next >
Text File  |  2000-06-30  |  10KB  |  169 lines

  1. This  is  an explanation of the action of Pascal I/O,  as applied  to  text
  2. files.   A system meeting the ISO and ANSI standards is assumed.  This does
  3. not apply to Turbo Pascal exactly, because Turbo omits some of the standard
  4. abilities and functions,  especially for console input.   UCSD Pascal fails
  5. in console i/o, but other operations  are implemented.   PascalP  functions
  6. exactly as described below.
  7.  
  8. Any  Pascal file is conceptually a single stream,  with a file buffer  var-
  9. iable.   If we always refer to the file variable itself as "f",  the buffer
  10. variable is "f^".   If f is declared as "f  : FILE OF thing", then f^ is of
  11. type  "thing",  and may be used as such a variable at any time the file  is
  12. open (i.e. after the file has been reset or rewritten).
  13.  
  14. A Pascal text file is equivalent to "PACKED FILE OF char", and additionally
  15. specifies that the eoln, readln, writeln procedures may be used.  THESE MAY
  16. NOT BE USED ON A NON-TEXT FILE.
  17.  
  18. For  reading,  a file at any time consists of two ordered arrays of  items.
  19. The first is the portion that has already been input, and the second is the
  20. portion  that has not been input yet.   The buffer variable f^ always  con-
  21. tains the last single item input (consisting of characters,  an eoln  mark,
  22. and  an eof mark for text files).   The eoln mark always appears as a space
  23. in f^, and may only be detected by the eoln procedure.  The eof mark in any
  24. non-empty text file must immediately follow an eoln mark (specified by  the
  25. standard).   (Thus  any  good system will automatically append an  eoln  on
  26. closing  a  file,  if and only if it is not already present.)   The  second
  27. portion of the file is unlimited, and unknown as yet to the Pascal program.
  28.  
  29. When  a file is "reset" the file is actually opened,  and the first char is
  30. placed in f^ (this may be the eof or eoln mark,  checked by eof/eoln  func-
  31. tions).  This first char is removed from the second portion.
  32.  
  33. From  here  on,  the  action of the "get(f)" procedure is  to  advance  one
  34. further  character  in the source file,  discarding the old f^  value,  and
  35. replacing it with the next char.   It should always be an error to do  this
  36. when eof is true.
  37.  
  38. Note  that  nothing  has yet affected any variable in the  Pascal  program,
  39. except  the  f^ buffer.   These are the underlying functions of  the  input
  40. system.   The program may use the file by such actions as "ch := f^" at any
  41. time.
  42.  
  43. The syntax of "read(f,  ch)" is STRICTLY defined as "ch := f^; get(f)", and
  44. the  eoln and eof functions examine the non-visible characteristics of  the
  45. last  input character.   If "f" is omitted,  as in "read(ch)" the  standard
  46. file "input" is assumed, and the buffer variable is "input^".
  47.  
  48. For  most  CPM or MSDOS systems the file actually contains a <cr>  to  mark
  49. eoln,  and  a <^Z> to mark eof.   The value of f^ when eof is true  is  not
  50. defined by the standards, but when eoln is true it should be a space.  Thus
  51. the  <cr>  character can not appear (unless the system defines eoln as  the
  52. <cr,lf>  pair.   Some  systems always discard any <lf>,  so that  the  file
  53. action  remains  the same when input from a keyboard as when input  from  a
  54. disk file.
  55.  
  56. The  syntax  of  "read(f,  ch1,  ch2,  ..)"  is  defined  as  "read(f,ch1);
  57. read(f,ch2); .... ", and is simply a shorthand.  If the object read-into is
  58. an integer,  or a real,  then automatic conversion is performed from a text
  59. string,  and at completion f^ holds the terminating character (space,  non-
  60. numeric,  etc).   Such a read causes a run-time error when no valid integer
  61. etc.  is  found  before a terminator,  but leading blanks (and  eolns)  are
  62. skipped over.
  63.  
  64. Notice that nothing so far controls any flushing of input lines,  to ensure
  65. that  a  read  starts on the next physical  line.   This  is  performed  by
  66. "readln(f)",  which  is defined as "WHILE NOT eoln(f) DO  get(f);  get(f)".
  67. NOTE  the final get.   This always leave f^ holding the first character  of
  68. the next line (which is a space if the next line is empty, i.e. consists of
  69. eoln alone), or possibly an eof mark.  Again, an omitted "f" implies input.
  70.  
  71. The  syntax  of  "readln(f,   item1,   item2,  ..  itemn)"  is  defined  as
  72. "read(f,item1);  read(f,item2); ... read(f,itemn); readln(f)", and is again
  73. just a convenient shorthand.
  74.  
  75. This brings up the great bugaboo of Pascal text i/o:   When a file is reset
  76. it MUST place the first character in f^.  If that file is interactive (i.e.
  77. the  keyboard)  the first character must be typed at that time.   Thus  the
  78. natural sequence "reset(f);  write('prompt message'); read(f, ch)" to get a
  79. reply  to a prompt requires that the answer be typed before the  prompt  is
  80. made.  The problem also reappears after any readln, because the first "get"
  81. from the next line is performed. (see below for why f^ is filled at all)
  82.  
  83. This  is normally cured by a special driver for text files.   Whenever  the
  84. "get"  is executed it simply sets a flag somehere (totally invisible to the
  85. application program) which says "a get is pending".  (If get finds the flag
  86. set it must perform the pending get,  and then again set the  flag).   Note
  87. that the "get" may be implied by a reset,  read,  or readln operation.  Now
  88. the  system must again intercept any use of eoln,  eof,  or the f^ variable
  89. and,  before actually executing them, check the "get_pending" flag.  If set
  90. the actual get must be performed,  the flag reset,  and then the eoln, eof,
  91. f^  references may be made.   This prevents the early  physical  read,  and
  92. allows natural programming.   However the programmer should always remember
  93. that any reference to eof,  eoln, or f^ will cause the physical read.  Thus
  94. the  sequence  "reset(f);   IF  eof(f)  THEN  something;   write('prompt');
  95. read(f,ch)" will cause the physical read to be too early.
  96.  
  97. Some  systems  do not follow the ANSI/ISO standard,  and define  a  special
  98. interactive  file type where read(f, ch) is defined as "get(f);  ch := f^".
  99. This causes all sorts of problems,  because the programmer must always know
  100. that  this file is interactive,  and programs cannot use the standard input
  101. and disk files interchangably.
  102.  
  103. The  "get" is normally executed on reset (or readln) so that the  value  of
  104. eoln  and eof is available after using a character (by read),  and so  that
  105. the program can look ahead to the next character.  This allows decisions to
  106. be made,  i.e.  is the following character numeric.. then read a number; or
  107. is  it alpha ..  then read a char;  or is it a special ..  then read a user
  108. command etc.  Thus a file copy program such as:
  109.  
  110.        WHILE NOT eof DO BEGIN
  111.          WHILE NOT eoln DO BEGIN
  112.            read(ch); write(ch); END;
  113.          readln; writeln; END;
  114.  
  115. works naturally.  The read/write line can be replaced by
  116.  
  117.            write(input^); get(input); END
  118.  
  119. or by some sort of filter such as
  120.  
  121.            IF input^ <> ' ' THEN write(input^);
  122.            get(input); END;
  123.                               to strip out all blanks.
  124.  
  125. with the same action and no auxiliary variable.   Such a fragment can  copy
  126. the  standard  input to standard output,  and works correctly with any  i/o
  127. redirection applied.
  128.  
  129. NOTE  that "reset(input)" is always automatically performed when a  program
  130. begins  running,  and similarly "rewrite(output)".   Thus  such  statements
  131. should normally not appear in a program.
  132.  
  133. Think  of  readln  as  a line-flushing procedure,  but bear  in  mind  that
  134. "readln(item)" is always equivalent to "read(item); readln".
  135.  
  136. For output, write(f, item1, item2, .. itemn) is defined as "write(f,item1);
  137. write(f, item2); ... write(f, itemn)", and "writeln(f, item)" is defined as
  138. "write(f,  item);  writeln(f)".   Both of these are again  shorthand.   The
  139. writeln  procedure alone (i.e.  writeln(f) ) simply puts an eoln mark  into
  140. the file being written.   If the "f" specification is omitted the write  is
  141. shipped to "output" file by default.
  142.  
  143. Again,  the  fundamental  writing procedure is "put(f)",  which causes  the
  144. content of f^ to be appended to the end of the file f.   "write(f, item) is
  145. STRICTLY defined as "f^ := item;  put(f)",  and should be unable to  create
  146. the  eoln  mark  in  a text file (reserved for  writeln).   The  action  of
  147. "rewrite(f)" is to empty any old version of f,  and leave f^ undefined.  f^
  148. is  also undefined after any write operation.   Thus doing  nothing  except
  149. "rewrite(f)" in a program should leave f as an empty file, but existing.
  150.  
  151. All  Pascal files should be automatically closed when the defining  program
  152. (or procedure for a local file) is exited.   Some systems provide a "close"
  153. procedure  to  force  an early close for one reason  or  another  (e.g.  to
  154. release a locked file to another user in a multi-process environment).   If
  155. a file was open for write (via rewrite), and is later "reset", an automatic
  156. close is done.   These closings of a written file append the eof mark,  and
  157. force any system buffers to be flushed.   Some systems are incomplete,  and
  158. actually  require that a specific call to "close" be made.   This procedure
  159. is non-standard, and such programs will not be portable.
  160.  
  161. Again,  this  is how it should work according to international  (and  ANSI)
  162. standards.  Some systems do not meet the standards - beware.
  163.  
  164. For Turbo Pascal users,  I have written a set of includable procedures (see
  165. TURBOFIX.LBR) which make Turbo meet these standards, although you will have
  166. to use non-standard procedure names.
  167.  
  168. I hope this clears up some confusion.  C.B. Falconer 85/9/11, 87/2/12
  169. P