DEFINITION MODULE FileIO; (* This module attempts to provide several potentially non-portable facilities for Coco/R. (a) A general file input/output module, with all routines required for Coco/R itself, as well as several other that would be useful in Coco-generated applications. (b) Definition of the "LONGINT" type needed by Coco. (c) Some conversion functions to handle this long type. (d) Some "long" and other constant literals that may be problematic on some implementations. (e) Some string handling primitives needed to interface to a variety of known implementations. The intention is that the rest of the code of Coco and its generated parsers should be as portable as possible. Provided the definition module given, and the associated implementation, satisfy the specification given here, this should be almost 100% possible (with the exception of a few constants, avoid changing anything in this specification). FileIO is based on code by MB 1990/11/25; heavily modified and extended by PDT and others between 1992/1/6 and the present day. *) (* This is the ISO Gardens Point Modula (Linux/FreeBSD) version *) IMPORT SYSTEM, Strings; TYPE File; (* Preferably opaque *) INT32 = INTEGER; (* This may require a special import; on 32 bit systems INT32 = INTEGER may even suffice. *) CONST EOF = 0C; (* FileIO.Read returns EOF when eof is reached. *) EOL = 12C; (* FileIO.Read maps line marks onto EOL FileIO.Write maps EOL onto cr, lf, or cr/lf as appropriate for filing system. *) ESC = 33C; (* Standard ASCII escape. *) CR = 15C; (* Standard ASCII carriage return. *) LF = 12C; (* Standard ASCII line feed. *) BS = 10C; (* Standard ASCII backspace. *) DEL = 177C; (* Standard ASCII DEL (rub-out). *) BitSetSize = 16; (* number of bits actually used in BITSET type *) Long0 = VAL(INT32, 0); (* Some systems allow 0 or require 0L. *) Long1 = VAL(INT32, 1); (* Some systems allow 1 or require 1L. *) Long2 = VAL(INT32, 2); (* Some systems allow 2 or require 2L. *) FrmExt = ".frm"; (* supplied frame files have this extension. *) TxtExt = ".txt"; (* generated text files may have this extension. *) ErrExt = ".err"; (* generated error files may have this extension. *) DefExt = ".def"; (* generated definition modules have this extension. *) PasExt = ".pas"; (* generated Pascal units have this extension. *) ModExt = ".mod"; (* generated implementation/program modules have this extension. *) PathSep = ":"; (* separate components in path environment variables DOS = ";" UNIX = ":" *) DirSep = "/"; (* separate directory element of file specifiers DOS = "\" UNIX = "/" *) VAR Okay: BOOLEAN; (* Status of last I/O operation. *) con, err: File; (* Standard terminal and error channels. *) StdIn, StdOut: File; (* standard input/output - redirectable *) EOFChar: CHAR; (* Signal EOF interactively *) (* The following routines provide access to command line parameters and the environment. *) PROCEDURE NextParameter (VAR s: ARRAY OF CHAR); (* Extracts next parameter from command line. Returns empty string (s[0] = 0C) if no further parameter can be found. *) PROCEDURE GetEnv (envVar: ARRAY OF CHAR; VAR s: ARRAY OF CHAR); (* Returns s as the value of environment variable envVar, or empty string if that variable is not defined. *) (* The following routines provide a minimal set of file opening routines and closing routines. *) PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN); (* Opens file f whose full name is specified by fileName. Opening mode is specified by newFile: TRUE: the specified file is opened for output only. Any existing file with the same name is deleted. FALSE: the specified file is opened for input only. FileIO.Okay indicates whether the file f has been opened successfully. *) PROCEDURE SearchFile (VAR f: File; envVar, fileName: ARRAY OF CHAR; newFile: BOOLEAN); (* As for Open, but tries to open file of given fileName by searching each directory specified by the environment variable named by envVar. *) PROCEDURE Close (VAR f: File); (* Closes file f. f becomes NIL. If possible, Close should be called automatically for all files that remain open when the application terminates. This will be possible on implementations that provide some sort of termination or at-exit facility. *) PROCEDURE CloseAll; (* Closes all files opened by Open or SearchFile. On systems that allow this, CloseAll should be automatically installed as the termination (at-exit) procedure *) (* The following utility procedure is not used by Coco, but may be useful. However, some operating systems may not allow for its implementation. *) PROCEDURE Delete (VAR f: File); (* Deletes file f. f becomes NIL. *) (* The following routines provide a minimal set of file name manipulation routines. These are modelled after MS-DOS conventions, where a file specifier is of a form exemplified by D:\DIR\SUBDIR\PRIMARY.EXT Other conventions may be introduced; these routines are used by Coco to derive names for the generated modules from the grammar name and the directory in which the grammar specification is located. *) PROCEDURE ExtractDirectory (fullName: ARRAY OF CHAR; VAR directory: ARRAY OF CHAR); (* Extracts D:\DIRECTORY\ portion of fullName. *) PROCEDURE ExtractFileName (fullName: ARRAY OF CHAR; VAR fileName: ARRAY OF CHAR); (* Extracts PRIMARY.EXT portion of fullName. *) PROCEDURE AppendExtension (oldName, ext: ARRAY OF CHAR; VAR newName: ARRAY OF CHAR); (* Constructs newName as complete file name by appending ext to oldName if it doesn't end with "." Examples: (assume ext = "EXT") old.any ==> OLD.EXT old. ==> OLD. old ==> OLD.EXT This is not a file renaming facility, merely a string manipulation routine. *) PROCEDURE ChangeExtension (oldName, ext: ARRAY OF CHAR; VAR newName: ARRAY OF CHAR); (* Constructs newName as a complete file name by changing extension of oldName to ext. Examples: (assume ext = "EXT") old.any ==> OLD.EXT old. ==> OLD.EXT old ==> OLD.EXT This is not a file renaming facility, merely a string manipulation routine. *) (* The following routines provide a minimal set of file positioning routines. Others may be introduced, but at least these should be implemented. Success of each operation is recorded in FileIO.Okay. *) PROCEDURE Length (f: File): INT32; (* Returns length of file f. *) PROCEDURE GetPos (f: File): INT32; (* Returns the current read/write position in f. *) PROCEDURE SetPos (f: File; pos: INT32); (* Sets the current position for f to pos. *) (* The following routines provide a minimal set of file rewinding routines. These two are not currently used by Coco itself. Success of each operation is recorded in FileIO.Okay *) PROCEDURE Reset (f: File); (* Sets the read/write position to the start of the file *) PROCEDURE Rewrite (f: File); (* Truncates the file, leaving open for writing *) (* The following routines provide a minimal set of input routines. Others may be introduced, but at least these should be implemented. Success of each operation is recorded in FileIO.Okay. *) PROCEDURE EndOfLine (f: File): BOOLEAN; (* TRUE if f is currently at the end of a line, or at end of file. *) PROCEDURE EndOfFile (f: File): BOOLEAN; (* TRUE if f is currently at the end of file. *) PROCEDURE Read (f: File; VAR ch: CHAR); (* Reads a character ch from file f. Maps filing system line mark sequence to FileIO.EOL. *) PROCEDURE ReadAgain (f: File); (* Prepares to re-read the last character read from f. There is no buffer, so at most one character can be re-read. *) PROCEDURE ReadLn (f: File); (* Reads to start of next line on file f, or to end of file if no next line. Skips to, and consumes next line mark. *) PROCEDURE ReadString (f: File; VAR str: ARRAY OF CHAR); (* Reads a string of characters from file f. Leading blanks are skipped, and str is delimited by line mark. Line mark is not consumed. *) PROCEDURE ReadLine (f: File; VAR str: ARRAY OF CHAR); (* Reads a string of characters from file f. Leading blanks are not skipped, and str is terminated by line mark or control character, which is not consumed. *) PROCEDURE ReadToken (f: File; VAR str: ARRAY OF CHAR); (* Reads a string of characters from file f. Leading blanks and line feeds are skipped, and token is terminated by a character <= ' ', which is not consumed. *) PROCEDURE ReadInt (f: File; VAR i: INTEGER); (* Reads an integer value from file f. *) PROCEDURE ReadCard (f: File; VAR i: CARDINAL); (* Reads a cardinal value from file f. *) PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; VAR len: CARDINAL); (* Attempts to read len bytes from the current file position into buf. After the call, len contains the number of bytes actually read. *) (* The following routines provide a minimal set of output routines. Others may be introduced, but at least these should be implemented. *) PROCEDURE Write (f: File; ch: CHAR); (* Writes a character ch to file f. If ch = FileIO.EOL, writes line mark appropriate to filing system. *) PROCEDURE WriteLn (f: File); (* Skips to the start of the next line on file f. Writes line mark appropriate to filing system. *) PROCEDURE WriteString (f: File; str: ARRAY OF CHAR); (* Writes entire string str to file f. *) PROCEDURE WriteText (f: File; text: ARRAY OF CHAR; len: INTEGER); (* Writes text to file f. At most len characters are written. Trailing spaces are introduced if necessary (thus providing left justification). *) PROCEDURE WriteInt (f: File; int: INTEGER; wid: CARDINAL); (* Writes an INTEGER int into a field of wid characters width. If the number does not fit into wid characters, wid is expanded. If wid = 0, exactly one leading space is introduced. *) PROCEDURE WriteCard (f: File; card, wid: CARDINAL); (* Writes a CARDINAL card into a field of wid characters width. If the number does not fit into wid characters, wid is expanded. If wid = 0, exactly one leading space is introduced. *) PROCEDURE WriteBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; len: CARDINAL); (* Writes len bytes from buf to f at the current file position. *) (* The following procedures are not currently used by Coco, and may be safely omitted, or implemented as null procedures. They might be useful in measuring performance. *) PROCEDURE WriteDate (f: File); (* Write current date DD/MM/YYYY to file f. *) PROCEDURE WriteTime (f: File); (* Write time HH:MM:SS to file f. *) PROCEDURE WriteElapsedTime (f: File); (* Write elapsed time in seconds since last call of this procedure. *) PROCEDURE WriteExecutionTime (f: File); (* Write total execution time in seconds thus far to file f. *) (* The following procedures are a minimal set used within Coco for string manipulation. They almost follow the conventions of the ISO routines, and are provided here to interface onto whatever Strings library is available. On ISO compilers it should be possible to implement most of these with CONST declarations, and even replace SLENGTH with the pervasive function LENGTH at the points where it is called. CONST SLENGTH = Strings.Length; Assign = Strings.Assign; Extract = Strings.Extract; Concat = Strings.Concat; *) PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL; (* Returns number of characters in stringVal, not including nul *) PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR); (* Copies as much of source to destination as possible, truncating if too long, and nul terminating if shorter. Be careful - some libraries have the parameters reversed! *) PROCEDURE Extract (source: ARRAY OF CHAR; startIndex, numberToExtract: CARDINAL; VAR destination: ARRAY OF CHAR); (* Extracts at most numberToExtract characters from source[startIndex] to destination. If source is too short, fewer will be extracted, even zero perhaps *) PROCEDURE Concat (stringVal1, stringVal2: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR); (* Concatenates stringVal1 and stringVal2 to form destination. Nul terminated if concatenation is short enough, truncated if it is too long *) PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER; (* Returns -1, 0, 1 depending whether stringVal1 < = > stringVal2. This is not directly ISO compatible *) (* The following routines are for conversions to and from the INT32 type. Their names are modelled after the ISO pervasive routines that would achieve the same end. Where possible, replacing calls to these routines by the pervasives would improve performance markedly. As used in Coco, these routines should not give range problems. *) PROCEDURE ORDL (n: INT32): CARDINAL; (* Convert long integer n to corresponding (short) cardinal value. Potentially FileIO.ORDL(n) = VAL(CARDINAL, n) *) PROCEDURE INTL (n: INT32): INTEGER; (* Convert long integer n to corresponding short integer value. Potentially FileIO.INTL(n) = VAL(INTEGER, n) *) PROCEDURE INT (n: CARDINAL): INT32; (* Convert cardinal n to corresponding long integer value. Potentially FileIO.INT(n) = VAL(INT32, n) *) PROCEDURE QuitExecution; (* Close all files and halt execution. On some implementations QuitExecution will be simply implemented as HALT *) END FileIO.