|
|
@@ -140,7 +140,7 @@ CONST
|
|
|
the later Reset/Rewrite. IOResult is an expression; EndOfFile is the
|
|
|
next file increment. *)
|
|
|
BI_Assign = 16 ; BI_Reset = 17 ; BI_Rewrite = 18 ;
|
|
|
- BI_Close = 19 ; BI_IoResult = 20 ; BI_Chr = 21 ;
|
|
|
+ BI_Close = 19 ; BI_IoResult = 20 ; BI_Chr = 21 ; BI_Str = 22 ;
|
|
|
(* the sub-codes EmCrtSeq takes *)
|
|
|
CrtClr = 0 ; CrtDl = 1 ; CrtDh = 2 ; CrtCaret = 3 ; CrtEol = 4 ;
|
|
|
CrtLow = 5 ; CrtNorm = 6 ; CrtDelay = 7 ; CrtKey = 8 ;
|
|
|
@@ -386,7 +386,8 @@ VAR
|
|
|
TU_StackChk : CARDINAL ;
|
|
|
TU_WrInt : CARDINAL ; TU_WrIntW : CARDINAL ;
|
|
|
TU_WrChar : CARDINAL ; TU_WrBool : CARDINAL ;
|
|
|
- TU_WrReal : CARDINAL ; TU_RealWrite : CARDINAL ; TU_WrLn : CARDINAL ;
|
|
|
+ TU_WrReal : CARDINAL ; TU_RealWrite : CARDINAL ; TU_RealFmt : CARDINAL ;
|
|
|
+ TU_WrLn : CARDINAL ;
|
|
|
TU_RdInt : CARDINAL ; TU_RdChar : CARDINAL ; TU_RdBool : CARDINAL ;
|
|
|
TU_RdLn : CARDINAL ; TU_Halt : CARDINAL ;
|
|
|
TU_RdByte : CARDINAL ; (* one-byte variable reads; see IoCall *)
|
|
|
@@ -1040,6 +1041,21 @@ BEGIN
|
|
|
Ebyte (58H) (* POP AX *)
|
|
|
END EmPopAx ;
|
|
|
|
|
|
+PROCEDURE EmPushBx () ;
|
|
|
+BEGIN Ebyte (53H) END EmPushBx ;
|
|
|
+
|
|
|
+PROCEDURE EmPopBx () ;
|
|
|
+BEGIN Ebyte (5BH) END EmPopBx ;
|
|
|
+
|
|
|
+PROCEDURE EmMovAxCx () ;
|
|
|
+BEGIN Ebyte (89H) ; Ebyte (0C8H) END EmMovAxCx ; (* MOV AX,CX *)
|
|
|
+
|
|
|
+PROCEDURE EmMovChAl () ;
|
|
|
+BEGIN Ebyte (88H) ; Ebyte (0C5H) END EmMovChAl ; (* MOV CH,AL *)
|
|
|
+
|
|
|
+PROCEDURE EmMovChImm (v : CARDINAL) ;
|
|
|
+BEGIN Ebyte (0B5H) ; Ebyte (VAL (BYTE, v MOD 256)) END EmMovChImm ;
|
|
|
+
|
|
|
(* 91 = XCHG AX,CX, and NOT 93. LoadPair hands the operator the left
|
|
|
operand in CX and the right in AX (in the original, and still the
|
|
|
commonest, shape: it pushes the left, loads the right, then pops the
|
|
|
@@ -5000,6 +5016,78 @@ BEGIN
|
|
|
END ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
+ IF which = BI_Str THEN
|
|
|
+ (* Str(Value[:FW[:DEC]], S): format a REAL into a string variable.
|
|
|
+ The source address is pushed first and parked on the stack while the
|
|
|
+ width/decimals expressions and the destination are parsed; the two
|
|
|
+ stack words are then swapped to real_fmt's order (source at [BP+4],
|
|
|
+ destination at [BP+6]). CX carries (decimals << 8) | width; it is
|
|
|
+ parked in tmpA across the destination parse, which may clobber CX.
|
|
|
+ Defaults match TPSRC8 pstdef1/pstdef3: width 18, decimals FFFFh. *)
|
|
|
+ IF NOT MatchDelim ('(') THEN
|
|
|
+ Err (ENoSemi) ;
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ ParseExpr (arg) ;
|
|
|
+ IF OK () AND (arg.cls = TReal) AND
|
|
|
+ ((arg.kind = 1) OR (arg.kind = 5)) THEN
|
|
|
+ IF arg.kind = 5 THEN
|
|
|
+ EmPushDi ()
|
|
|
+ ELSE
|
|
|
+ EmPushVarAddr (symtab [arg.idx].local,
|
|
|
+ (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ END ;
|
|
|
+ IF MatchDelim (':') THEN
|
|
|
+ ParseExpr (dummy) ;
|
|
|
+ IF OK () THEN
|
|
|
+ LoadAtom (dummy)
|
|
|
+ END ;
|
|
|
+ IF MatchDelim (':') THEN
|
|
|
+ EmPushAx () ;
|
|
|
+ ParseExpr (dummy) ;
|
|
|
+ IF OK () THEN
|
|
|
+ LoadAtom (dummy) ;
|
|
|
+ EmMovChAl () ;
|
|
|
+ EmPopAx () ;
|
|
|
+ EmMovClAl ()
|
|
|
+ END
|
|
|
+ ELSIF OK () THEN
|
|
|
+ EmMovClAl () ;
|
|
|
+ EmMovChImm (0FFH)
|
|
|
+ END
|
|
|
+ ELSE
|
|
|
+ EmMovCxi (0FF12H) (* width 18, decimals FFFFh *)
|
|
|
+ END ;
|
|
|
+ IF NOT OK () THEN
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ EmMovAxCx () ;
|
|
|
+ EmStoreVar (FALSE, symtab [tmpA].off, 2) ;
|
|
|
+ IF NOT MatchDelim (',') THEN
|
|
|
+ Err (ENoSemi) ;
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ ParseExpr (dummy) ;
|
|
|
+ IF OK () AND (dummy.cls = TString) AND
|
|
|
+ ((dummy.kind = 1) OR (dummy.kind = 5)) THEN
|
|
|
+ EmPushStrAddr (dummy) ;
|
|
|
+ EmPopAx () ; (* destination *)
|
|
|
+ EmPopBx () ; (* source *)
|
|
|
+ EmPushAx () ; (* destination at [BP+6] *)
|
|
|
+ EmPushBx () ; (* source at [BP+4] *)
|
|
|
+ EmLoadVar (FALSE, symtab [tmpA].off, 2) ;
|
|
|
+ EmXchgAxCx () ; (* CX := packed width/decimals *)
|
|
|
+ DropC (EmCall (TU_RealFmt)) ;
|
|
|
+ EmAddSp (4)
|
|
|
+ ELSIF OK () THEN
|
|
|
+ Err (ETypeErr)
|
|
|
+ END
|
|
|
+ ELSIF OK () THEN
|
|
|
+ Err (ETypeErr)
|
|
|
+ END ;
|
|
|
+ ExpectDelim (')', ENoSemi) ;
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
IF which = BI_Assign THEN
|
|
|
(* Assign(F, Name): the file variable's address and the counted
|
|
|
string's address. The runtime copies the characters into the file
|
|
|
@@ -6997,6 +7085,8 @@ BEGIN
|
|
|
symtab [i].defnd := TRUE ;
|
|
|
i := NewSym ("CHR", KBuiltin, BI_Chr, 0, 0, 0, 0, FALSE) ;
|
|
|
symtab [i].defnd := TRUE ;
|
|
|
+ i := NewSym ("STR", KBuiltin, BI_Str, 0, 0, 0, 0, FALSE) ;
|
|
|
+ symtab [i].defnd := TRUE ;
|
|
|
(* KBD: the console keyboard as a TEXT file. This runtime's read entries
|
|
|
already read the console, so `Read(Kbd, Ch)' drops the file argument and
|
|
|
reads a character exactly as `Read(Ch)' does. *)
|
|
|
@@ -7142,6 +7232,7 @@ BEGIN
|
|
|
TU_WrBool := RT_Entry (5) ;
|
|
|
TU_WrReal := RT_Entry (6) ;
|
|
|
TU_RealWrite := RT_Entry (30) ; (* fmtreal + padding + output *)
|
|
|
+ TU_RealFmt := RT_Entry (28) ; (* fmtreal into a string variable *)
|
|
|
TU_WrLn := RT_Entry (7) ;
|
|
|
TU_RdInt := RT_Entry (8) ;
|
|
|
TU_RdChar := RT_Entry (9) ;
|