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];