DIRECTORY
Basics USING [LongNumber],
FS USING [AccessOptions, Error, ErrorDesc, StreamOpen],
IO USING [Close, EndOfStream, Error, GetByte, GetChar, PutByte, PutChar, STREAM],
PS USING [Error, File, NewFile, PopFile, PopInt, PopString, PushBool, PushFile, PushInt, PushString, Register, RegisterPrimitives, Root, RopeFromString, String, StringGet, StringGetInterval, StringIndex, StringPut],
Rope USING [Equal, ROPE];
 
Primitives
Pfile: 
PROC [self: Root] ~ {
string2: String ~ PopString[self];
string1: String ~ PopString[self];
PushFile[self, FileCreate[string1, string2]];
};
 
Pclosefile: 
PROC [self: Root] ~ {
file: File ~ PopFile[self];
IO.Close[file.stream];
};
 
Pread: 
PROC [self: Root] ~ {
file: File ~ PopFile[self];
int: INT;
IF file.access<readOnly THEN ERROR Error[invalidaccess];
int ← 
IO.GetByte[file.stream !
IO.EndOfStream => GOTO EndOfFile;
IO.Error => IF ec=StreamClosed THEN GOTO EndOfFile ELSE GOTO IOError;
];
 
PushInt[self, int];
PushBool[self, TRUE];
EXITS
EndOfFile => PushBool[self, FALSE];
IOError => ERROR Error[ioerror];
 
};
 
Pwrite: 
PROC [self: Root] ~ {
int: INT ~ PopInt[self];
file: File ~ PopFile[self];
IF file.access<unlimited THEN ERROR Error[invalidaccess];
IO.PutByte[file.stream, 
LOOPHOLE[int, Basics.LongNumber].ll !
IO.EndOfStream => GOTO IOError;
IO.Error => GOTO IOError;
];
 
EXITS
IOError => ERROR Error[ioerror];
 
};
 
Preadhexstring: 
PROC [self: Root] ~ {
string: String ~ PopString[self];
file: File ~ PopFile[self];
hi: [0..2] ← 0;
h: ARRAY [0..2) OF [0..16) ← ALL[0];
si: StringIndex ← 0;
IF file.access<readOnly THEN ERROR Error[invalidaccess];
WHILE si<string.length 
DO
char: 
CHAR ~ 
IO.GetChar[file.stream !
IO.EndOfStream => EXIT;
IO.Error => GOTO IOError;
];
 
SELECT char 
FROM
IN ['0..'9] => { h[hi] ← (char-'0); hi ← hi+1 };
IN ['A..'F] => { h[hi] ← 10+(char-'A); hi ← hi+1 };
IN ['a..'f] => { h[hi] ← 10+(char-'a); hi ← hi+1 };
ENDCASE;
 
IF hi=2 THEN { StringPut[string, si, VAL[h[0]*16+h[1]]]; si ← si+1; hi ← 0 };
ENDLOOP;
 
IF si=string.length THEN { PushString[self, string]; PushBool[self, TRUE] }
ELSE { PushString[self, StringGetInterval[string, 0, si]]; PushBool[self, FALSE] };
EXITS
IOError => ERROR Error[ioerror];
 
};
 
Pwritehexstring: 
PROC [self: Root] ~ {
string: String ~ PopString[self];
file: File ~ PopFile[self];
IF file.access<unlimited THEN ERROR Error[invalidaccess];
FOR si: StringIndex 
IN[0..string.length) 
DO
byte: BYTE ~ ORD[StringGet[string, si]];
Hex: 
PROC [h: [0..16)] 
RETURNS [
CHAR] ~ {
RETURN [IF h<10 THEN '0+h ELSE 'a+(h-10)];
};
 
IO.PutChar[file.stream, Hex[byte/16] !
IO.Error => GOTO IOError;
];
 
IO.PutChar[file.stream, Hex[byte 
MOD 16] !
IO.Error => GOTO IOError;
];
 
ENDLOOP;
 
EXITS
IOError => ERROR Error[ioerror];
 
};
 
Preadstring: 
PROC [self: Root] ~ {
string: String ~ PopString[self];
file: File ~ PopFile[self];
si: StringIndex ← 0;
IF file.access<readOnly THEN ERROR Error[invalidaccess];
WHILE si<string.length 
DO
char: 
CHAR ~ 
IO.GetChar[file.stream !
IO.EndOfStream => EXIT;
IO.Error => GOTO IOError;
];
 
StringPut[string, si, char];
si ← si+1;
ENDLOOP;
 
IF si=string.length THEN { PushString[self, string]; PushBool[self, TRUE] }
ELSE { PushString[self, StringGetInterval[string, 0, si]]; PushBool[self, FALSE] };
EXITS
IOError => ERROR Error[ioerror];
 
};
 
Pwritestring: 
PROC [self: Root] ~ {
string: String ~ PopString[self];
file: File ~ PopFile[self];
WriteString[file, string];
};
 
Preadline: 
PROC [self: Root] ~ {
};
 
Pbytesavailable: 
PROC [self: Root] ~ {
};
 
Pflush: 
PROC [self: Root] ~ {
};
 
Pflushfile: 
PROC [self: Root] ~ {
};
 
Presetfile: 
PROC [self: Root] ~ {
};
 
Pstatus: 
PROC [self: Root] ~ {
};
 
Prun: 
PROC [self: Root] ~ {
};
 
Pcurrentfile: 
PROC [self: Root] ~ {
};
 
Pprint: 
PROC [self: Root] ~ {
string: String ~ PopString[self];
WriteString[self.stdout, string];
};
 
Pecho: 
PROC [self: Root] ~ {
};
 
FilePrimitives: 
PROC [self: Root] ~ {
Register[self, "file", Pfile];
Register[self, "closefile", Pclosefile];
Register[self, "read", Pread];
Register[self, "write", Pwrite];
Register[self, "readhexstring", Preadhexstring];
Register[self, "writehexstring", Pwritehexstring];
Register[self, "readstring", Preadstring];
Register[self, "writestring", Pwritestring];
Register[self, "readline", Preadline];
Register[self, "bytesavailable", Pbytesavailable];
Register[self, "flush", Pflush];
Register[self, "flushfile", Pflushfile];
Register[self, "resetfile", Presetfile];
Register[self, "status", Pstatus];
Register[self, "run", Prun];
Register[self, "currentfile", Pcurrentfile];
Register[self, "print", Pprint];
Register[self, "echo", Pecho];
};
 
RegisterPrimitives[FilePrimitives];