|
|
@@ -1497,7 +1497,7 @@ END EmStoreInd ;
|
|
|
|
|
|
PROCEDURE EmFileIo (reading : BOOLEAN ; fileLocal : BOOLEAN ; fileOff : CARDINAL ;
|
|
|
addrKind : CARDINAL ; addrLocal : BOOLEAN ;
|
|
|
- addrOff, count : CARDINAL) ;
|
|
|
+ addrOff, count : CARDINAL ; stringArg : BOOLEAN) ;
|
|
|
(* Typed-file block I/O: read/write `count' bytes at the data argument to the
|
|
|
open file in the file variable.
|
|
|
|
|
|
@@ -1512,23 +1512,54 @@ PROCEDURE EmFileIo (reading : BOOLEAN ; fileLocal : BOOLEAN ; fileOff : CARDINAL
|
|
|
per call site and the compiler's code budget is the loose one. *)
|
|
|
BEGIN
|
|
|
IF addrKind = 5 THEN
|
|
|
- Ebyte (89H) ; Ebyte (0FAH) (* MOV DX,DI *)
|
|
|
+ (* DI already holds a kind-5 element's address. *)
|
|
|
+ ELSIF addrKind = 4 THEN
|
|
|
+ EmLeaDi (FALSE, addrOff) (* a code-resident blob *)
|
|
|
ELSIF addrKind = 1 THEN
|
|
|
- EmLeaDi (addrLocal, addrOff) ;
|
|
|
- Ebyte (89H) ; Ebyte (0FAH) (* MOV DX,DI *)
|
|
|
+ EmLeaDi (addrLocal, addrOff)
|
|
|
ELSE
|
|
|
Err (ETypeErr) ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
+ Ebyte (89H) ; Ebyte (0FAH) ; (* MOV DX,DI *)
|
|
|
+ IF stringArg THEN
|
|
|
+ (* DX points at the characters, CX = the length byte at [DI]. *)
|
|
|
+ Ebyte (42H) ; (* INC DX *)
|
|
|
+ EmLdAlDi () ;
|
|
|
+ EmMovClAl () ;
|
|
|
+ Ebyte (30H) ; Ebyte (0EDH) (* XOR CH,CH *)
|
|
|
+ ELSE
|
|
|
+ EmMovCxi (count)
|
|
|
+ END ;
|
|
|
EmLoadVar (fileLocal, fileOff, 2) ; (* AX := the DOS handle *)
|
|
|
Ebyte (89H) ; Ebyte (0C3H) ; (* MOV BX,AX *)
|
|
|
- EmMovCxi (count) ;
|
|
|
Ebyte (0B4H) ; (* MOV AH,3Fh/40h *)
|
|
|
IF reading THEN Ebyte (3FH) ELSE Ebyte (40H) END ;
|
|
|
Ebyte (0CDH) ; Ebyte (21H) ; (* INT 21h *)
|
|
|
DropC (EmCall (TU_IoStore))
|
|
|
END EmFileIo ;
|
|
|
|
|
|
+PROCEDURE EmInlineCh (ch : CARDINAL) : CARDINAL ;
|
|
|
+(* Emit a one-character string literal behind a JMP and return the image
|
|
|
+ offset of its length byte. Used by text-file Write(File, ' '). *)
|
|
|
+VAR here : CARDINAL ;
|
|
|
+BEGIN
|
|
|
+ Ebyte (0EBH) ; Ebyte (2) ;
|
|
|
+ here := pc ;
|
|
|
+ Ebyte (1) ; Ebyte (VAL (BYTE, ch)) ;
|
|
|
+ RETURN here
|
|
|
+END EmInlineCh ;
|
|
|
+
|
|
|
+PROCEDURE EmInlineCrLf () : CARDINAL ;
|
|
|
+(* The CR LF pair every text-file Writeln emits. *)
|
|
|
+VAR here : CARDINAL ;
|
|
|
+BEGIN
|
|
|
+ Ebyte (0EBH) ; Ebyte (3) ;
|
|
|
+ here := pc ;
|
|
|
+ Ebyte (2) ; Ebyte (13) ; Ebyte (10) ;
|
|
|
+ RETURN here
|
|
|
+END EmInlineCrLf ;
|
|
|
+
|
|
|
PROCEDURE EmSubSp (n : CARDINAL) ;
|
|
|
BEGIN
|
|
|
Ebyte (81H) ; Ebyte (0ECH) ; Eword (n MOD 10000H)
|
|
|
@@ -5066,18 +5097,65 @@ BEGIN
|
|
|
(* A leading TEXT file argument. KBD is the console keyboard
|
|
|
and this runtime's read entries already read the console, so
|
|
|
the file is dropped and the rest of the argument list is read
|
|
|
- exactly as without it. Other text-file I/O is the next file
|
|
|
- increment and stays loud rather than reading the file
|
|
|
- variable as a data argument. *)
|
|
|
+ exactly as without it. *)
|
|
|
IF reading AND (arg.kind = 1) AND symtab [arg.idx].isKbd THEN
|
|
|
IF NOT MatchDelim (',') THEN
|
|
|
Err (ENoSemi) ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
skipArg := TRUE
|
|
|
- ELSE
|
|
|
+ ELSIF reading THEN
|
|
|
+ (* Text-file Read/Readln is the next increment. *)
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
+ ELSE
|
|
|
+ (* Text-file output: Writeln(File) is CRLF, Write(File, C)
|
|
|
+ is one CHAR, and writeln(File, S) is S followed by CRLF.
|
|
|
+ Write each byte range with DOS AH=40h; a string argument
|
|
|
+ carries its own length byte, a one-CHAR literal becomes a
|
|
|
+ tiny code-resident <1><char>. *)
|
|
|
+ IF (arg.kind # 1) OR (symtab [arg.idx].cls # TText) THEN
|
|
|
+ Err (ETypeErr) ;
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ IF MatchDelim (',') THEN
|
|
|
+ ParseExpr (dummy) ;
|
|
|
+ IF NOT OK () THEN
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ IF dummy.cls = TString THEN
|
|
|
+ IF dummy.kind = 1 THEN
|
|
|
+ EmFileIo (FALSE, symtab [arg.idx].local,
|
|
|
+ symtab [arg.idx].off, 1,
|
|
|
+ symtab [dummy.idx].local,
|
|
|
+ (symtab [dummy.idx].off + dummy.boff)
|
|
|
+ MOD 10000H,
|
|
|
+ 0, TRUE)
|
|
|
+ ELSIF dummy.kind = 3 THEN
|
|
|
+ EmFileIo (FALSE, symtab [arg.idx].local,
|
|
|
+ symtab [arg.idx].off, 4, FALSE,
|
|
|
+ EmStrBlob (dummy), 0, TRUE)
|
|
|
+ ELSE
|
|
|
+ Err (ENoLib) ;
|
|
|
+ RETURN
|
|
|
+ END
|
|
|
+ ELSIF (dummy.cls = TScalar) AND dummy.chr THEN
|
|
|
+ EmFileIo (FALSE, symtab [arg.idx].local,
|
|
|
+ symtab [arg.idx].off, 4, FALSE,
|
|
|
+ EmInlineCh (VAL (CARDINAL, dummy.imm)),
|
|
|
+ 0, TRUE)
|
|
|
+ ELSE
|
|
|
+ Err (ENoLib) ;
|
|
|
+ RETURN
|
|
|
+ END
|
|
|
+ END ;
|
|
|
+ IF which = BI_WriteLn THEN
|
|
|
+ EmFileIo (FALSE, symtab [arg.idx].local,
|
|
|
+ symtab [arg.idx].off, 4, FALSE,
|
|
|
+ EmInlineCrLf (), 0, TRUE)
|
|
|
+ END ;
|
|
|
+ ExpectDelim (')', ENoSemi) ;
|
|
|
+ RETURN
|
|
|
END
|
|
|
ELSIF (nArgs = 0) AND (arg.cls = TFile) THEN
|
|
|
(* Typed-file block I/O: `write(MCfile, Sheet[I,J])' and the
|
|
|
@@ -5102,12 +5180,13 @@ BEGIN
|
|
|
END ;
|
|
|
IF dummy.kind = 5 THEN
|
|
|
EmFileIo (reading, symtab [arg.idx].local,
|
|
|
- symtab [arg.idx].off, 5, FALSE, 0, VarSize (dummy))
|
|
|
+ symtab [arg.idx].off, 5, FALSE, 0, VarSize (dummy),
|
|
|
+ FALSE)
|
|
|
ELSE
|
|
|
EmFileIo (reading, symtab [arg.idx].local,
|
|
|
symtab [arg.idx].off, 1, symtab [dummy.idx].local,
|
|
|
(symtab [dummy.idx].off + dummy.boff) MOD 10000H,
|
|
|
- VarSize (dummy))
|
|
|
+ VarSize (dummy), FALSE)
|
|
|
END ;
|
|
|
ExpectDelim (')', ENoSemi) ;
|
|
|
RETURN
|