text: /* Buffered file I/O - swapping
  
     Warning:  Either CATRTNS or CATSWAP MUST be libraried before FILEIO!
  */
  
  _library(":-xpl:libs:fileswap")
  /*
  .  This module handles buffered file input and output.
  .
  .  WARNING:  These routines assume the logical end-of-file occurs within
  .            the last 256-sector block of the file.  This means that a
  .            256-sector file that has a word length of zero will be
  .            considered to be zero words long rather than 65536 words long.
  .            A 65536-word file is represented by a sector length of 257
  .            and a word length of zero.
  .
  .  FOpen (Filename, Access):  Opens a file by the given filename and access.
  .               Returns a file pointer or NULLF if it fails.  Access must
  .               must be one of the following (presently unused):
  .                  'r':  Read only (disallow all PUTs & SHUFFLE)
  .                  'w':  Write only (disallow all GETs); truncate if there, create if not
  .                  'a':  Append (disallow all GETs); position to end if there, create if not
  .                  'r+': Update - file MUST be there
  .                  'w+': Update - truncate if there, create if not
  .                  'a+': Update - position to end if there, create if not
  .
  .  FClose (F):  Closes file F, where F is a file pointer returned by a
  .               previous call to FOPEN.  Returns zero if it works,
  .               EOF_MARK otherwise.
  .
  .  SetBuf (F, BufPtr, BufMed, Size):  Sets the buffer used for the file
  .               just opened by FOPEN to the buffer with the given SIZE
  .               pointed to by BUFPTR/BUFMED where BUFMED is zero for
  .               internal memory, one for external, and two for poly.
  .               This routine can only be called immediately after a call
  .               to FOPEN.  Returns zero if it works, EOF_MARK otherwise.
  .   
  .  FFlush (F):  Flush file F's buffer.
  .
  .  FEOF (F):    Returns TRUE if at EOF of file F.
  .
  .  GetC (F):    Gets the next character from file F.  GETC returns
  .               either a character or an end of file (EOF) mark.
  .
  .  GetW (F):    Gets the next word from file F.  It returns either a
  .               word or EOF_MARK.
  .
  .               NOTE:  There is a potential confusion due to the fact
  .               that EOF_MARK is defined as -1, which is a perfectly
  .               valid next word.  FGETS suffers from this problem as well.
  .               Use FEOF before the GETW or FGETS call to be certain.
  .
  .  FGetS (Line, Max, F):  Gets the next line from file F and its line number.
  .               When the end of the file is reached, EOF_MARK is returned 
  .               instead of the line number.
  .
  .  PutC (C, F): Write character C to file F at the current file position.
  .               EOF_MARK is returned if at the end of file.
  .
  .  PutW (W, F): Write word W to file F at the current file position.
  .               EOF_MARK is returned if at the end of file.
  .
  .  FPutS (Line, Number, F):  Write line LINE with line number NUMBER to
  .               file F at the current file position.  EOF_MARK is
  .               returned if at the end of file.
  .
  .  FFull (Bytes, FPutS, F):  See if writing BYTES bytes to file F will
  .               cause its file buffer to be flushed.  This is useful
  .               when a program needs to know when time will be lost
  .               to disk I/O.  FFULL is TRUE if these bytes form a line
  .               to be passed to FPUTS.
  .
  .  FRead (Buf, Size, Number, F):  Read NUMBER records of SIZE bytes into
  .               BUF from file F starting at the current file position.
  .               The number of records actually read is returned.
  .
  .  FWrite (Buf, Size, Number, F):  Write NUMBER records of SIZE bytes from
  .               BUF to file F starting at the current file position.
  .               The number of records actually written is returned.
  .
  .  Seek (F, Offset, Origin):  Reset the file position of file F to character
  .               position OFFSET based on the mode specified in ORIGIN.  The
  .               new file position is returned.  ORIGIN must be one of these:
  .                  0: seek from start of file
  .                  1: seek from current position
  .                  2: seek from end of file
  .                3-5: same as 0-2, but treat OFFSET as a sector offset
  .
  .  Shuffle (F, Source, Destination, Length):  Move sectors SOURCE through
  .               SOURCE + LENGTH - 1 of file F to DESTINATION in file F.
  .               Returns EOF_MARK if the combination of SOURCE, DESTINATION,
  .               and LENGTH would cause a shuffle past the physical end of
  .               file or if SOURCE or DESTINATION is beyond the logical
  .               end of file.  SHUFFLE will change the logical length of
  .               file F if the shuffle caused said length to change.
  .               After SHUFFLE returns, the file position will be zero.
  */
  
  #define	file				fixed										// file type (returned by FOPEN and expected by all the others)
  #define	eof_mark			-1											// end-of-file mark
  #define	nullf				-1											// null file pointer - returned by FOPEN if it fails
  
  
  /* File errors (returned in FILE_ERROR) */
  
  #define	f_okay				0											// no errors
  #define	f_no_file			1											// file does not exist
  #define	f_bad_file			2											// invalid file descriptor
  #define	f_no_buffer			3											// no buffer assigned to the file
  #define	f_bad_arg			4											// invalid argument or improper operation requested
  #define	f_too_many			5											// too many files open
  #define	f_bad_access		6											// invalid access request
  #define	f_too_big			7											// file is too large to process - files are limited to 32 Mbytes
  
  extern	file	fopen(fixed[], fixed[]);								// open file with specified name
  extern	fixed	fclose(file);											// close specified file
  extern	fixed	setbuf(file, pointer, fixed, fixed);					// set opened file's buffer
  extern	fixed	fflush(file);											// flush specified file's buffer
  extern	boolean	feof(file);												// return TRUE if at end-of-file
  extern	fixed	getc(file);												// get next character from specified file
  extern	fixed	getw(file);												// get next word from specified file
  extern	fixed	fgets(fixed[], fixed, file);							// get next line (and line #) from specified file
  extern	fixed	putc(fixed, file);										// put specified character in specified file
  extern	fixed	putw(fixed, file);										// put specified word in specified file
  extern	fixed	fputs(fixed[], fixed, file);							// put specified line (and line #) in specified file
  extern	boolean	ffull(fixed, boolean, file);							// see if this many bytes fills the file's buffer
  extern	fixed	fread(fixed[], fixed, fixed, file);						// read one or more records from specified file
  extern	fixed	fwrite(fixed[], fixed, fixed, file);					// write one or more records to specified file
  extern	fixed	seek(file, fixed, fixed);								// seek to given file position in specified file
  extern	fixed	shuffle(file, fixed, fixed, fixed);						// shuffle file
  
  extern	fixed	file_error;												// global file error indicator
  extern	void	fileio_main();
  extern	fixed	setbuf(file	f, fixed buf, fixed	med, fixed siz);
  