| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923 |
- IMPLEMENTATION 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 generic WinTel version *)
- FROM SYSTEM IMPORT TSIZE;
- IMPORT FileSystem, Strings, InOut;
- FROM OS2DEF IMPORT APIRET;
- FROM OS2ARG IMPORT ArgCount, Arg, STRING, PSTRING,
- EnvCount, Env ;
- FROM DOSDATETIME IMPORT DATETIME, DosGetDateTime;
- FROM Storage IMPORT ALLOCATE, DEALLOCATE;
- CONST
- MaxFiles = BitSetSize;
- NameLength = 256;
- BufSize = 1024 ;
- TYPE Buftype = ARRAY [0..BufSize] OF CHAR;
- VAR
- Handles: BITSET;
- Opened: ARRAY [0 .. MaxFiles-1] OF File;
- FromKeyboard, ToScreen: BOOLEAN;
- Param: LONGCARD;
- Continue: PROC;
- TYPE CommandType = POINTER TO ARRAY [0..255] OF CHAR;
- File = POINTER TO FileRec;
- FileRec = RECORD
- ref: FileSystem.File;
- self: File;
- handle: CARDINAL;
- savedCh: CHAR;
- textOK, eof, eol, noOutput, noInput, haveCh: BOOLEAN;
- name: ARRAY [0 .. NameLength] OF CHAR;
- END;
- PROCEDURE NextParameter (VAR s: ARRAY OF CHAR);
- VAR P : PSTRING;
- BEGIN
- INC(Param);
- IF Param <= ArgCount()
- THEN P := Arg ( Param );
- IF P # NIL THEN Assign ( P^, s);END;
- ELSE s[0] := 0C
- END
- END NextParameter;
- PROCEDURE GetEnv ( envVar : ARRAY OF CHAR; VAR s : ARRAY OF CHAR );
- VAR pos, index, idxmax : LONGCARD;
- match : BOOLEAN;
- ct : CommandType;
- i,j : LONGCARD;
- c : CHAR;
- BEGIN
- match := FALSE;
- s [ 0 ] := CHR(0);
- j := Strings.Length (envVar);
- FOR i := 0 TO j DO envVar[i] := CAP(envVar[i]) END;
- idxmax := EnvCount();
- INC (idxmax);
- index := 0;
- WHILE (index < idxmax) AND (NOT match) DO
- ct := CommandType( Env (index));
- IF ct # NIL THEN
- pos := Strings.Pos ( envVar, ct^ );
- match := ( pos = 0)
- END; (* if ct # *)
- INC (index);
- END; (* While *)
- IF match THEN
- i:=0;
- REPEAT c := ct^[i]; INC (i) UNTIL c = '=';
- c := ct^[i];
- WHILE ct^[i] = ' ' DO INC(i) END;
- j := 0;
- REPEAT
- c := ct^[i];
- s[j] := c ;
- INC(i); INC(j);
- UNTIL ( c = CHR(0)) OR (j = HIGH(s)) ;
- END;
- END GetEnv ;
- PROCEDURE ASCIIZ (VAR s1, s2: ARRAY OF CHAR);
- (* Convert s2 to a nul terminated string in s1 *)
- VAR i: CARDINAL;
- BEGIN
- i := 0;
- WHILE (i <= HIGH(s2)) & (s2[i] # 0C) DO
- s1[i] := s2[i]; INC(i)
- END;
- s1[i] := 0C
- END ASCIIZ;
- PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN);
- VAR
- i: CARDINAL;
- NoWrite: BOOLEAN;
- name: ARRAY [0 .. NameLength] OF CHAR;
- BEGIN
- ExtractFileName(fileName, name);
- FOR i := 0 TO NameLength - 1 DO name[i] := CAP(name[i]) END;
- IF (name[0] = 0C) OR (Strings.Compare(name, "CON") = 0) THEN
- (* con already opened, but reset it *)
- Okay := TRUE; f := con;
- f^.savedCh := 0C; f^.haveCh := FALSE;
- f^.eof := FALSE; f^.eol := FALSE; f^.name := "CON";
- RETURN
- ELSIF Strings.Compare(name, "ERR") = 0 THEN
- Okay := TRUE; f := err; RETURN
- ELSE
- ALLOCATE(f, SIZE(FileRec));
- NoWrite := FALSE;
- IF newFile
- THEN FileSystem.Create( f^.ref, fileName)
- ELSE
- FileSystem.Lookup(f^.ref, fileName, FALSE );
- END;
- Okay := f^.ref.res = 0;
- IF ~ Okay
- THEN
- DEALLOCATE(f, SIZE(FileRec)); f := NIL
- ELSE
- (* textOK below may have to be altered according to implementation *)
- f^.savedCh := 0C; f^.haveCh := FALSE; f^.textOK := TRUE;
- f^.eof := newFile; f^.eol := newFile; f^.self := f;
- f^.noInput := newFile; f^.noOutput := ~ newFile OR NoWrite;
- ASCIIZ(f^.name, fileName);
- i := 0 (* find next available filehandle *);
- WHILE (i IN Handles) & (i < MaxFiles) DO INC(i) END;
- IF i < MaxFiles
- THEN f^.handle := i; INCL(Handles, i); Opened[i] := f
- ELSE (* WriteString(err, "Too many files"); Okay := FALSE *)
- END;
- (* IF Okay THEN FIO.AssignBuffer(f^.ref, f^.buffer) END; *)
- END
- END
- END Open;
- PROCEDURE NotRead (f: File): BOOLEAN;
- BEGIN
- RETURN (f = NIL) OR (f^.self # f) OR (f^.noInput);
- END NotRead;
- PROCEDURE NotWrite (f: File): BOOLEAN;
- BEGIN
- RETURN (f = NIL) OR (f^.self # f) OR (f^.noOutput);
- END NotWrite;
- PROCEDURE NotFile (f: File): BOOLEAN;
- BEGIN
- IF (f = NIL) THEN RETURN TRUE END;
- IF (f^.self # f) OR (File(f) = con) OR (File(f) = err)
- THEN RETURN TRUE END;
- IF (File(f) = StdIn) & FromKeyboard
- THEN RETURN TRUE END;
- IF (File(f) = StdOut) & ToScreen
- THEN RETURN TRUE END;
- RETURN FALSE
- END NotFile;
- PROCEDURE Close (VAR f: File);
- BEGIN
- (* IF f = NIL THEN RETURN END;*)
- IF NotFile(f) OR (File(f) = StdIn) OR (File(f) = StdOut)
- THEN Okay := FALSE
- ELSE
- EXCL(Handles, f^.handle);
- FileSystem.Close(f^.ref);
- Okay := f^.ref.res = 0;
- IF Okay THEN DEALLOCATE(f, TSIZE(FileRec)) END;
- f := NIL
- END
- END Close;
- PROCEDURE CloseAll;
- VAR
- handle: CARDINAL;
- BEGIN
- FOR handle := 0 TO MaxFiles - 1 DO
- IF handle IN Handles THEN Close(Opened[handle]) END
- END;
- IF ~ ToScreen THEN FileSystem.Close(StdOut^.ref) END;
- Continue;
- END CloseAll;
- PROCEDURE Delete (VAR f: File);
- BEGIN
- IF NotFile(f) OR (File(f) = StdIn) OR (File(f) = StdOut)
- THEN Okay := FALSE
- ELSE
- EXCL(Handles, f^.handle);
- FileSystem.Close (f^.ref);
- FileSystem.Delete(f^.ref);
- Okay := f^.ref.res = 0;
- IF Okay THEN DEALLOCATE(f, TSIZE(FileRec)) END;
- f := NIL
- END
- END Delete;
- PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL;
- BEGIN
- RETURN CARDINAL ( Strings.Length(stringVal) )
- END SLENGTH;
- PROCEDURE Concat (string1, string2: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
- BEGIN
- Strings.Concat( string1, string2,destination );
- END Concat;
- PROCEDURE Assign ( source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
- BEGIN
- Strings.Assign ( source, destination )
- END Assign;
- PROCEDURE Extract (source: ARRAY OF CHAR; startIndex: CARDINAL;
- numberToExtract: CARDINAL; VAR destination: ARRAY OF CHAR);
- BEGIN
- Strings.Copy (source, startIndex, numberToExtract, destination )
- END Extract;
- PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER;
- BEGIN
- RETURN Strings.Compare(stringVal1, stringVal2)
- END Compare;
- PROCEDURE SearchFile (VAR f: File; envVar, fileName: ARRAY OF CHAR;
- newFile: BOOLEAN);
- VAR
- i, j: INTEGER;
- k : CARDINAL;
- c: CHAR;
- fname: ARRAY [0 .. NameLength] OF CHAR;
- path: ARRAY [0 .. NameLength] OF CHAR;
- BEGIN
- FOR k := 0 TO CARDINAL ( HIGH(envVar) ) DO envVar[k] := CAP(envVar[k]) END;
- GetEnv(envVar, path);
- i := 0;
- REPEAT
- j := 0;
- REPEAT
- c := path[i]; fname[j] := c; INC(i); INC(j)
- UNTIL (c = PathSep) OR (c = 0C);
- IF (j > 1) & (fname[j-2] = DirSep) THEN DEC(j) ELSE fname[j-1] := DirSep END;
- fname[j] := 0C; Concat(fname, fileName, fname);
- Open(f, fname, newFile);
- UNTIL (c = 0C) OR Okay
- END SearchFile;
- PROCEDURE ExtractFileName (fullName : ARRAY OF CHAR; VAR fileName : ARRAY OF CHAR );
- VAR i, l, start: CARDINAL;
- BEGIN
- start := 0; l := 0;
- WHILE (l <= HIGH(fullName)) & (fullName[l] # 0C) DO
- IF (fullName[l] = ":") OR (fullName[l] = DirSep) THEN start := l + 1 END;
- INC(l)
- END;
- i := 0;
- WHILE (start < l) & (i <= HIGH(fileName)) DO
- fileName[i] := fullName[start]; INC(start); INC(i)
- END;
- IF i <= HIGH(fileName) THEN fileName[i] := 0C END
- END ExtractFileName;
- PROCEDURE ExtractDirectory (fullName : ARRAY OF CHAR; VAR directory : ARRAY OF CHAR );
- VAR i, start: CARDINAL;
- BEGIN
- start := 0; i := 0;
- WHILE (i <= HIGH(fullName)) & (fullName[i] # 0C) DO
- IF i <= HIGH(directory) THEN directory[i] := fullName[i] END;
- IF (fullName[i] = ":") OR (fullName[i] = DirSep) THEN start := i + 1 END;
- INC(i)
- END;
- IF start <= HIGH(directory) THEN directory[start] := 0C END
- END ExtractDirectory ;
- PROCEDURE AppendExtension (oldName, ext: ARRAY OF CHAR; VAR newName: ARRAY OF CHAR);
- VAR i, j: CARDINAL;
- fn: ARRAY [0 .. NameLength] OF CHAR;
- BEGIN
- ExtractDirectory(oldName, newName);
- ExtractFileName(oldName, fn);
- i := 0; j := 0;
- WHILE (i <= NameLength) & (fn[i] # 0C) DO
- IF fn[i] = "." THEN j := i + 1 END;
- INC(i)
- END;
- IF (j # i) (* then name did not end with "." *) OR (i = 0)
- THEN IF j # 0 THEN i := j - 1 END;
- IF (ext[0] # ".") & (ext[0] # 0C) THEN
- IF i <= NameLength THEN fn[i] := "."; INC(i) END
- END;
- j := 0;
- WHILE (j <= HIGH(ext)) & (ext[j] # 0C) & (i <= NameLength) DO
- fn[i] := ext[j]; INC(i); INC(j)
- END
- END;
- IF i <= NameLength THEN fn[i] := 0C END;
- Strings.Concat(newName, fn, newName)
- END AppendExtension;
- PROCEDURE ChangeExtension (oldName, ext: ARRAY OF CHAR; VAR newName: ARRAY OF CHAR);
- VAR i, j: CARDINAL;
- fn: ARRAY [0 .. NameLength] OF CHAR;
- BEGIN
- ExtractDirectory(oldName, newName);
- ExtractFileName(oldName, fn);
- i := 0; j := 0;
- WHILE (i <= NameLength) & (fn[i] # 0C) DO
- IF fn[i] = "." THEN j := i + 1 END;
- INC(i)
- END;
- IF j # 0 THEN i := j - 1 END;
- IF (ext[0] # ".") & (ext[0] # 0C)
- THEN IF i <= NameLength THEN fn[i] := "."; INC(i) END
- END;
- j := 0;
- WHILE (j <= HIGH(ext)) & (ext[j] # 0C) & (i <= NameLength) DO
- fn[i] := ext[j]; INC(i); INC(j)
- END;
- IF i <= NameLength THEN fn[i] := 0C END;
- Strings.Concat(newName, fn, newName)
- END ChangeExtension;
- PROCEDURE Length (f: File): INT32;
- VAR result: LONGCARD;
- BEGIN
- IF NotFile(f)
- THEN Okay := FALSE; RETURN 0
- ELSE FileSystem.LongLength (f^.ref, result );
- Okay := f^.ref.res = 0;
- RETURN INT32(result)
- END
- END Length;
- PROCEDURE GetPos (f: File): INT32;
- VAR pos: LONGCARD;
- BEGIN
- IF NotFile(f)
- THEN Okay := FALSE; RETURN Long0
- ELSE FileSystem.GetLongPos(f^.ref, pos );
- Okay := f^.ref.res = 0;
- RETURN pos
- END
- END GetPos;
- PROCEDURE SetPos (f: File; pos: INT32);
- BEGIN
- IF NotFile(f)
- THEN Okay := FALSE
- ELSE FileSystem.SetLongPos(f^.ref, LONGCARD(pos) );
- Okay := f^.ref.res = 0; f^.haveCh := FALSE
- END
- END SetPos;
- PROCEDURE Reset (f: File);
- BEGIN
- IF NotFile(f)
- THEN Okay := FALSE
- ELSE SetPos(f, 0);
- IF Okay
- THEN f^.haveCh := FALSE;
- f^.eof := f^.noInput;
- f^.eol := f^.noInput
- END
- END
- END Reset;
- PROCEDURE Rewrite (f: File);
- VAR c: CHAR;
- BEGIN
- IF NotFile(f)
- THEN Okay := FALSE
- ELSE SetPos(f, 0);
- IF Okay
- THEN WriteBytes(f, c, 0);
- f^.haveCh := FALSE;
- f^.savedCh := 0C;
- f^.eof := FALSE;
- f^.eol := FALSE
- END
- END
- END Rewrite;
- PROCEDURE EndOfLine (f: File): BOOLEAN;
- BEGIN
- IF NotRead(f)
- THEN Okay := FALSE;
- RETURN TRUE
- ELSE Okay := TRUE;
- RETURN f^.eol OR f^.eof
- END
- END EndOfLine;
- PROCEDURE EndOfFile (f: File): BOOLEAN;
- BEGIN
- IF NotRead(f)
- THEN Okay := FALSE;
- RETURN TRUE
- ELSE Okay := TRUE;
- RETURN f^.eof
- END
- END EndOfFile;
- PROCEDURE ErrWrite (ch: CHAR);
- CONST StdErr = DOSFILEMGR.STDERR;
- VAR c : ARRAY [0..0] OF CHAR;
- res,n : LONGCARD;
- BEGIN
- c[0] := ch;
- res := LONGCARD( DOSFILEMGR.DosWrite (StdErr,c,1,n))
- END ErrWrite;
- (* --------------A VERIFIER ------>>>> redirection *)
- PROCEDURE ConRead (VAR ch: CHAR);
- BEGIN
- InOut.Read ( ch )
- END ConRead;
- PROCEDURE ConWrite ( ch : CHAR );
- BEGIN
- InOut.Write (ch );
- END ConWrite;
- (*------------------------------------------------*)
- PROCEDURE Read (f: File; VAR ch: CHAR);
- BEGIN
- IF NotRead(f) THEN Okay := FALSE; ch := 0C; RETURN END;
- IF f^.haveCh OR f^.eof
- THEN ch := f^.savedCh;
- Okay := ch # 0C;
- ELSE
- IF (File(f) = con) OR (File(f) = StdIn) & FromKeyboard
- THEN ConRead(ch);
- Write(con, ch);
- IF ch = BS
- THEN ConWrite(" ");
- ConWrite(BS)
- END;
- Okay := ch # EOFChar;
- ELSE FileSystem.ReadChar(f^.ref, ch);
- IF ch = CR THEN FileSystem.ReadChar(f^.ref, ch); ch := EOL END;
- Okay := f^.ref.res = 0;
- IF ch = EOFChar THEN Okay := FALSE END;
- END;
- END;
- IF ~ Okay THEN ch := 0C END;
- f^.savedCh := ch; f^.haveCh := ~ Okay;
- f^.eof := ch = 0C; f^.eol := f^.eof OR (ch = EOL);
- END Read;
- PROCEDURE ReadAgain (f: File);
- BEGIN
- IF NotRead(f)
- THEN Okay := FALSE
- ELSE f^.haveCh := TRUE
- END
- END ReadAgain;
- PROCEDURE ReadLn (f: File);
- VAR ch: CHAR;
- BEGIN
- IF NotRead(f) THEN Okay := FALSE; RETURN END;
- WHILE ~ f^.eol DO Read(f, ch) END;
- f^.haveCh := FALSE; f^.eol := FALSE;
- END ReadLn;
- PROCEDURE ReadString (f: File; VAR str: ARRAY OF CHAR);
- VAR j: CARDINAL;
- ch: CHAR;
- BEGIN
- str[0] := 0C; j := 0;
- IF NotRead(f) THEN Okay := FALSE; RETURN END;
- REPEAT Read(f, ch) UNTIL (ch # " ") OR ~ Okay;
- IF Okay THEN
- WHILE ch >= " " DO
- IF j <= HIGH(str) THEN str[j] := ch END; INC(j);
- Read(f, ch);
- WHILE (ch = BS) OR (ch = DEL) DO
- IF j > 0 THEN DEC(j) END; Read(f, ch) END
- END;
- IF j <= HIGH(str) THEN str[j] := 0C END;
- Okay := j > 0; f^.haveCh := TRUE; f^.savedCh := ch;
- END
- END ReadString;
- PROCEDURE ReadLine (f: File; VAR str: ARRAY OF CHAR);
- VAR j: CARDINAL;
- ch: CHAR;
- BEGIN
- str[0] := 0C; j := 0;
- IF NotRead(f) THEN Okay := FALSE; RETURN END;
- Read(f, ch);
- IF Okay
- THEN WHILE ch >= " " DO
- IF j <= HIGH(str) THEN str[j] := ch END; INC(j);
- Read(f, ch);
- WHILE (ch = BS) OR (ch = DEL) DO
- IF j > 0 THEN DEC(j) END; Read(f, ch)
- END
- END;
- IF j <= HIGH(str) THEN str[j] := 0C END;
- Okay := j > 0; f^.haveCh := TRUE; f^.savedCh := ch;
- END
- END ReadLine;
- PROCEDURE ReadToken (f: File; VAR str: ARRAY OF CHAR);
- VAR j: CARDINAL;
- ch: CHAR;
- BEGIN
- str[0] := 0C; j := 0;
- IF NotRead(f) THEN Okay := FALSE; RETURN END;
- REPEAT Read(f, ch) UNTIL (ch > " ") OR ~ Okay;
- IF Okay
- THEN WHILE ch > " " DO
- IF j <= HIGH(str) THEN str[j] := ch END; INC(j);
- Read(f, ch);
- WHILE (ch = BS) OR (ch = DEL) DO
- IF j > 0 THEN DEC(j) END; Read(f, ch)
- END
- END;
- IF j <= HIGH(str) THEN str[j] := 0C END;
- Okay := j > 0; f^.haveCh := TRUE; f^.savedCh := ch;
- END
- END ReadToken;
- PROCEDURE ReadInt (f: File; VAR i: INTEGER);
- VAR
- Digit: INTEGER;
- j: CARDINAL;
- Negative: BOOLEAN;
- s: ARRAY [0 .. 80] OF CHAR;
- BEGIN
- i := 0; j := 0;
- IF NotRead(f) THEN Okay := FALSE; RETURN END;
- ReadToken(f, s);
- IF s[0] = "-" (* deal with sign *)
- THEN Negative := TRUE; INC(j)
- ELSE Negative := FALSE; IF s[0] = "+" THEN INC(j) END
- END;
- IF (s[j] < "0") OR (s[j] > "9") THEN Okay := FALSE END;
- WHILE (j <= 80) & (s[j] >= "0") & (s[j] <= "9") DO
- Digit := VAL(INTEGER, ORD(s[j]) - ORD("0"));
- IF i <= (MAX(INTEGER) - Digit) DIV 10
- THEN i := 10 * i + Digit
- ELSE Okay := FALSE
- END;
- INC(j)
- END;
- IF Negative THEN i := -i END;
- IF (j > 80) OR (s[j] # 0C) THEN Okay := FALSE END;
- IF ~ Okay THEN i := 0 END;
- END ReadInt;
- PROCEDURE ReadCard (f: File; VAR i: CARDINAL);
- VAR
- Digit: CARDINAL;
- j: CARDINAL;
- s: ARRAY [0 .. 80] OF CHAR;
- BEGIN
- i := 0; j := 0;
- IF NotRead(f) THEN Okay := FALSE; RETURN END;
- ReadToken(f, s);
- WHILE (j <= 80) & (s[j] >= "0") & (s[j] <= "9") DO
- Digit := ORD(s[j]) - ORD("0");
- IF i <= (MAX(CARDINAL) - Digit) DIV 10
- THEN i := 10 * i + Digit
- ELSE Okay := FALSE
- END;
- INC(j)
- END;
- IF (j > 80) OR (s[j] # 0C) THEN Okay := FALSE END;
- IF ~ Okay THEN i := 0 END;
- END ReadCard;
- PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; VAR len: CARDINAL);
- VAR TooMany: BOOLEAN;
- Wanted : LONGCARD;
- BEGIN
- IF NotRead(f) OR (File(f) = con)
- THEN Okay := FALSE; len := 0;
- ELSE
- IF len = 0 THEN Okay := TRUE; RETURN END;
- TooMany := len - 1 > HIGH(buf);
- IF TooMany THEN Wanted := HIGH(buf) + 1 ELSE Wanted := len END;
- f^.ref.res := LONGCARD ( DOSFILEMGR.DosRead( f^.ref.id, buf, HIGH(buf)+1, Wanted ));
- Okay := f^.ref.res = 0;
- IF len # Wanted THEN Okay := FALSE END;
- END;
- IF ~ Okay THEN f^.eof := TRUE END;
- IF TooMany THEN Okay := FALSE END;
- END ReadBytes;
- PROCEDURE Write (f: File; ch: CHAR);
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- IF (File(f) = con) OR (File(f) = StdOut) & ToScreen
- THEN
- IF ch = EOL
- THEN ConWrite(CR); ConWrite(LF)
- ELSE ConWrite(ch)
- END;
- Okay := TRUE;
- ELSIF File(f) = err
- THEN
- IF ch = EOL
- THEN ErrWrite(CR); ErrWrite(LF)
- ELSE ErrWrite(ch)
- END;
- Okay := TRUE;
- ELSE
- IF ch = EOL
- THEN FileSystem.WriteLn(f^.ref)
- ELSE FileSystem.WriteChar(f^.ref, ch)
- END;
- Okay := f^.ref.res = 0;
- END;
- END Write;
- PROCEDURE WriteLn (f: File);
- BEGIN
- IF NotWrite(f)
- THEN Okay := FALSE;
- ELSE Write(f, EOL)
- END
- END WriteLn;
- PROCEDURE WriteString (f: File; str: ARRAY OF CHAR);
- VAR
- pos: CARDINAL;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- pos := 0;
- WHILE (pos <= HIGH(str)) & (str[pos] # 0C) DO
- Write(f, str[pos]); INC(pos)
- END
- END WriteString;
- PROCEDURE WriteText (f: File; text: ARRAY OF CHAR; len: INTEGER);
- VAR i,j, slen : LONGCARD;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- IF len > 0 THEN j := LONGCARD(len - 1) ELSE j := 0 END;
- slen := Strings.Length(text);
- FOR i := 0 TO j DO
- IF i < slen THEN Write(f, text[i]) ELSE Write(f, " ") END;
- END
- END WriteText;
- PROCEDURE WriteInt (f: File; n: INTEGER; wid: CARDINAL);
- VAR
- l, d: CARDINAL;
- x: INTEGER;
- t: ARRAY [1 .. 25] OF CHAR;
- sign: CHAR;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- IF n < 0
- THEN sign := "-"; x := - n;
- ELSE sign := " "; x := n;
- END;
- l := 0;
- REPEAT
- d := x MOD 10; x := x DIV 10;
- INC(l); t[l] := CHR(ORD("0") + d);
- UNTIL x = 0;
- IF wid = 0 THEN Write(f, " ") END;
- WHILE wid > l + 1 DO Write(f, " "); DEC(wid); END;
- IF (sign = "-") OR (wid > l) THEN Write(f, sign); END;
- WHILE l > 0 DO Write(f, t[l]); DEC(l); END;
- END WriteInt;
- PROCEDURE WriteCard (f: File; n, wid: CARDINAL);
- VAR
- l, d: CARDINAL;
- t: ARRAY [1 .. 25] OF CHAR;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- l := 0;
- REPEAT
- d := n MOD 10; n := n DIV 10;
- INC(l); t[l] := CHR(ORD("0") + d);
- UNTIL n = 0;
- IF wid = 0 THEN Write(f, " ") END;
- WHILE wid > l DO Write(f, " "); DEC(wid); END;
- WHILE l > 0 DO Write(f, t[l]); DEC(l); END;
- END WriteCard;
- PROCEDURE WriteBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; len: CARDINAL);
- VAR
- TooMany: BOOLEAN;
- len2 : LONGCARD;
- BEGIN
- TooMany := (len > 0) & (len - 1 > HIGH(buf));
- IF NotWrite(f) OR (File(f) = con) OR (File(f) = err)
- THEN
- Okay := FALSE
- ELSE
- IF TooMany THEN len := CARDINAL ( HIGH(buf) + 1 ) END;
- len2 := LONGCARD (len);
- f^.ref.res := LONGCARD ( DOSFILEMGR.DosRead( f^.ref.id, buf, HIGH(buf)+1, len2 ));
- Okay := f^.ref.res = 0;
- END;
- IF TooMany THEN Okay := FALSE END;
- END WriteBytes;
- PROCEDURE Write2 (f: File; i: SHORTCARD);
- BEGIN
- Write(f, CHR(i DIV 10 + ORD("0")));
- Write(f, CHR(i MOD 10 + ORD("0")));
- END Write2;
- PROCEDURE WriteDate (f: File);
- VAR
- dt : DATETIME;
- r : APIRET;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- r := DosGetDateTime (dt);
- WITH dt DO
- Write2(f, day); Write(f, "/"); Write2(f, month); Write(f, "/");
- WriteCard(f, year, 4)
- END;
- END WriteDate;
- PROCEDURE WriteTime (f: File);
- VAR
- dt : DATETIME;
- r : APIRET;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- r := DosGetDateTime ( dt);
- WITH dt DO
- Write2(f, hours); Write(f, ":"); Write2(f, minutes); Write(f, ":");
- Write2(f, seconds)
- END;
- END WriteTime;
- VAR
- Hrs0, Mins0, Secs0, Hsecs0: SHORTCARD;
- Hrs1, Mins1, Secs1, Hsecs1: SHORTCARD;
- PROCEDURE GetInitTime();
- VAR dt : DATETIME;
- r : APIRET;
- BEGIN
- r := DosGetDateTime ( dt );
- WITH dt DO
- Hrs0 := hours; Mins0 := minutes;
- Secs0 := seconds; Hsecs0 := hundredths;
- END;
- END GetInitTime;
- PROCEDURE WriteElapsedTime (f: File);
- VAR dt : DATETIME;
- r : APIRET;
- s : CARDINAL;
- hs : SHORTCARD;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- r:= DosGetDateTime( dt );
- WriteString(f, "Elapsed time: ");
- WITH dt DO
- IF hours >= Hrs1
- THEN s := (hours - Hrs1) * 3600 + (minutes - Mins1) * 60 + seconds - Secs1
- ELSE s := (hours + 24 - Hrs1) * 3600 + (minutes - Mins1) * 60 + seconds - Secs1
- END;
- IF hundredths >= Hsecs1
- THEN hs := hundredths - Hsecs1
- ELSE hs := (hundredths + 100) - Hsecs1; DEC(s);
- END;
- WriteCard(f, s, 1); Write(f, ".");
- Write2(f, hs); WriteString(f, " s"); WriteLn(f);
- Hrs1 := hours; Mins1 := minutes; Secs1 := seconds; Hsecs1 := hundredths;
- END;
- END WriteElapsedTime;
- PROCEDURE WriteExecutionTime (f: File);
- VAR dt : DATETIME;
- r : APIRET;
- s : CARDINAL;
- hs : SHORTCARD;
- BEGIN
- IF NotWrite(f) THEN Okay := FALSE; RETURN END;
- r:= DosGetDateTime( dt );
- WriteString(f, "Execution time: ");
- WITH dt DO
- IF hours >= Hrs0
- THEN s := (hours - Hrs0) * 3600 + (minutes - Mins0) * 60 + seconds - Secs0
- ELSE s := (hours + 24 - Hrs0) * 3600 + (minutes - Mins0) * 60 + seconds - Secs0
- END;
- IF hundredths >= Hsecs0
- THEN hs := hundredths - Hsecs0
- ELSE hs := (hundredths + 100) - Hsecs0; DEC(s);
- END;
- WriteCard(f, s, 1); Write(f, ".");
- Write2(f, hs); WriteString(f, " s"); WriteLn(f);
- END;
- END WriteExecutionTime;
- PROCEDURE INTL (n: INT32): INTEGER;
- BEGIN
- RETURN VAL(INTEGER, n)
- END INTL;
- PROCEDURE INT (n: CARDINAL): INT32;
- BEGIN
- RETURN VAL(INT32, n)
- END INT;
- PROCEDURE ORDL (n: INT32): CARDINAL;
- BEGIN
- RETURN VAL(CARDINAL, n)
- END ORDL;
- PROCEDURE QuitExecution;
- BEGIN
- HALT
- END QuitExecution;
- (* OS2 Std Channels *)
- PROCEDURE InitStdChannels();
- BEGIN
- WITH StdOut^.ref DO
- id := DOSFILEMGR.STDOUT;
- eof := FALSE;
- tmp := FALSE;
- name := "SCREEN$";
- END;
- WITH StdIn^.ref DO
- id := DOSFILEMGR.STDIN;
- eof := FALSE;
- tmp := FALSE;
- name := "KBD$";
- END;
- END InitStdChannels;
- BEGIN
- Handles := BITSET{};
- Okay := FALSE; EOFChar := 32C;
- Param := 0;
- GetInitTime();
- Hrs1 := Hrs0; Mins1 := Mins0; Secs1 := Secs0; Hsecs1 := Hsecs0;
- ALLOCATE(con, SYSTEM.TSIZE(FileRec));
- con^.ref := InOut.out;
- con^.savedCh := 0C; con^.haveCh := FALSE; con^.self := con;
- con^.noOutput := FALSE; con^.noInput := FALSE; con^.textOK := TRUE;
- con^.eof := FALSE; con^.eol := FALSE;
- IF FromKeyboard
- THEN ALLOCATE(StdIn, SYSTEM.TSIZE(FileRec));
- ELSE ALLOCATE(StdIn, SYSTEM.TSIZE(FileRec));
- END;
- StdIn^.ref := InOut.in;
- StdIn^.savedCh := 0C; StdIn^.haveCh := FALSE; StdIn^.self := StdIn;
- StdIn^.noOutput := TRUE; StdIn^.noInput := FALSE; StdIn^.textOK := TRUE;
- StdIn^.eof := FALSE; StdIn^.eol := FALSE;
- IF ToScreen
- THEN ALLOCATE(StdOut, SYSTEM.TSIZE(FileRec));
- ELSE ALLOCATE(StdOut, SYSTEM.TSIZE(FileRec));
- END;
- StdOut^.ref := InOut.out;
- StdOut^.savedCh := 0C; StdOut^.haveCh := FALSE; StdOut^.self := StdOut;
- StdOut^.noOutput := FALSE; StdOut^.noInput := TRUE; StdOut^.textOK := TRUE;
- StdOut^.eof := TRUE; StdOut^.eol := TRUE;
- InitStdChannels();
- END FileIO .
|