Browse Source

calc: Val(string, integer, error) (ladder 31758)

Val now converts a counted string to a signed integer.  val_int parses an
optional '-' followed by decimal digits, stores the value on success, and
writes 0 to the error variable.  On the first invalid character it leaves the
destination unchanged and writes the 1-based character position; an empty
string returns error 0 without changing the destination, matching TPSRC2's
valerr/valrt paths.  The compiler accepts a string variable, literal or
pointer-indexed element, and requires a two-byte integer destination and
error variable.

t96_valint covers positive, negative, an invalid character at position 3 and
the empty string; it runs under qemu and Exec86.

The CALC ladder moves 28074 -> 31758; the next blocker is a by-reference REAL
parameter (`var Value : Real` in Evaluate).

Verified: compile matrix 97/97, ladder 1/1, 88 .COM linked, 83 executed under
both qemu and Exec86, rt_exec 276/276, nonvacuity 121/121, run_all ALL PASS.
Eric Streit 5 ngày trước cách đây
mục cha
commit
9d4ab01044

+ 22 - 14
CALC-COMPILE.md

@@ -97,7 +97,7 @@ Current rung (measured today, normalised position):
 
 | position | blocker |
 |---|---|
-| **28074** | `Val(Buffer^[0],EndOfFile,ErrorResult)` — string-to-integer (`ERR 41`) |
+| **31758** | `var Value : Real` in `Evaluate` — by-reference REAL parameters (`ERR 102`) |
 
 Rungs behind it (now passed):
 
@@ -141,7 +141,8 @@ Rungs ahead:
 | 26924 | `Buffer : ^Pages` - pointer type - DONE |
 | 27648 | text-file `Eof`/`Readln` - DONE |
 | 27759 | `Str(count,st)` - integer Str - DONE |
-| 28074 | `Val(Buffer^[0],...)` - string-to-integer |
+| 28074 | `Val(Buffer^[0],...)` - string-to-integer - DONE |
+| 31758 | `var Value : Real` - by-reference REAL parameter |
 
 Corrections the measurements force, worth stating plainly because the stage list
 below was written before them:
@@ -350,7 +351,7 @@ recipe above regenerates them, and the numbers are what this document keeps.
    grow into the other. CALC's code is **16,560 bytes**, which the old fixed
    4 KiB window could not emit; that was a port artefact, not a TP3 limit.
 2. **`MaxCode = 24,000` is not the binding constraint for the compile goal.**
-   16,560 + 4,248 (our current runtime) = 20,808, comfortably inside 24,000.
+   16,560 + 4,384 (our current runtime) = 20,944, comfortably inside 24,000.
    The old `dataBase` alone had to move; `t43_codewindow` was the fixture that
    policed it and has been re-baselined (§3.2).
 3. **The §3 data budget is confirmed, not inferred.** Reported data is
@@ -363,7 +364,7 @@ recipe above regenerates them, and the numbers are what this document keeps.
    **DS size `0315h` (12,624 B)**, and **heap/stack `0400h` (16,384 B)**, with
    `A000h` as the maximum (640 KiB, in paragraphs). A `.COM` still uses
    separate CS/DS segments; the original proves it.
-5. **The runtime is 11,341 bytes** in the original. Ours is 4,248 B. It
+5. **The runtime is 11,341 bytes** in the original. Ours is 4,384 B. It
    explains where the original's fixed `pc := $2D7C` / `dc := $0240` came
    from, and why `TPSRC7:81-82` looks the way it does.
 
@@ -430,7 +431,7 @@ inline initmem    mode 0006, CS 0813, DS 11D7,
 
 The file is runtime + code, exactly the shape we now emit; the data is in the
 separate DS described by the inline parameters. Our CALC image will be smaller
-in runtime (4,248 B instead of 11,341 B) but has the same code-only, high-data
+in runtime (4,384 B instead of 11,341 B) but has the same code-only, high-data
 shape. The ladder moved **20,912 → 22,253** on this change; the next blocker is
 not layout but the untyped `file` declaration; that is fixed in the next rung.
 
@@ -464,9 +465,9 @@ membership, string fields in WRITE, real output, run-time set algebra,
 `Succ`/`Pred`, the original memory layout, the untyped file type, the
 file control-block operations, VAR string parameters, `Chr`, typed-file
 block I/O, text-file output, `Str`, pointer types with `New`/dereference,
-text `Eof`/`Readln`, and integer `Str`). The
-ladder has moved from the first typed constant at 7,791 to **28,074**, where
-`Val(Buffer^[0],EndOfFile,ErrorResult)` asks for string-to-integer conversion.
+text `Eof`/`Readln`, integer `Str`, and integer `Val`). The
+ladder has moved from the first typed constant at 7,791 to **31,758**, where
+`var Value : Real` asks for by-reference REAL parameters.
 
 The rung commits and their tags, in order (each is one rung with its own
 fixture, red proof, and — where the harness allows — execution under qemu and
@@ -509,7 +510,8 @@ Exec86):
 | `93d2ed4` | `v-TP3-CALC-TEXTOUT` | `ERR 41 26066` (`Str`) |
 | `38b6184` | `v-TP3-CALC-STR` | `ERR 30 26924` (pointer type) |
 | `1aed9cd` | `v-TP3-CALC-POINTER` | `ERR 41 27648` (`Eof`) |
-| *(this commit)* | `v-TP3-CALC-TEXTREAD` | **`ERR 41 28074`** (`Val`) |
+| `e940a1d` | `v-TP3-CALC-TEXTREAD` | `ERR 41 28074` (`Val`) |
+| *(this commit)* | `v-TP3-CALC-VALINT` | **`ERR 102 31758`** (VAR REAL) |
 
 - **Code HEAD** is the layout rung (`v-TP3-CALC-LAYOUT`).  Nothing is pushed.
   The terminal-config work (`v-TP3-TERMCFG`) and the editor key map
@@ -555,6 +557,12 @@ Exec86):
   parameter slot holds the caller's address; assignment, `Read`, `Length`,
   `writeln`, concatenation, comparison and `x[i]` all go through that address.
   `Chr(n)` folds or loads an ordinal and yields a CHAR.
+- **`Val(string, integer, error)` is landed (`t96_valint`).**  `val_int`
+  parses optional sign and decimal digits, stores the value on success, and
+  leaves the destination unchanged on error while writing the 1-based
+  position of the first invalid character.  Empty strings return error 0.
+  The fixture covers positive, negative, invalid and empty inputs and runs
+  under both oracles.
 - **Text `Eof`/`Readln` and integer `Str` are landed** (`t94_textread`,
   compile-only; `t95_strint`, executed).  `file_eof` compares the DOS current
   position with the size (and remembers ^Z from the text reader); `file_readln`
@@ -653,7 +661,7 @@ Exec86):
   `ERR 1 22253`, terminal config **4/4**, 78 `.COM` linked and **76 executed
   under both qemu and Exec86** (`t64_arrays` remains compile-only because it
   has no `.out`).  `tests/nonvacuity.sh`: **121 ok, 0 failed**.  The runtime is
-  4,248 bytes (wrintw, real_from_int, real_add, real_sub, real_mul, real_div,
+  4,384 bytes (wrintw, real_from_int, real_add, real_sub, real_mul, real_div,
   real_cmp, real_int, real_fmt, real_val, real_write, set_op, set_cmp,
   set_copy; the golden was re-blessed) and `tests/rt_exec.py` passes
   **275/275**, including the MBF arithmetic/output/parse cases and eleven
@@ -1162,9 +1170,9 @@ and TEXT file output is done (`t91_textout`), both compile-only because the
 harness has no filesystem.  `Str` real formatting is done (`t92_strreal`),
 pointer types with `New`/`Dispose`/dereference are done (`t93_pointer`), and
 text `Eof`/`Readln` plus integer `Str` are done (`t94_textread`/`t95_strint`).
-The next ladder blocker is `Val` string-to-integer conversion.  The probe
-scaffold has been moved to HDR=0x1300 / data 0x2110; the runtime is 4,248
-bytes and now has room for the remaining work.
+The next ladder blocker is a by-reference REAL parameter (`var Value : Real`
+in `Evaluate`).  The probe scaffold has been moved to HDR=0x1300 / data
+0x2110; the runtime is 4,384 bytes and now has room for the remaining work.
 
 **Stage 14 — the CRT identifiers.** `GotoXY` (25), `LowVideo`/`NormVideo`
 (16 + 16), `ClrEol` (10), `ClrScr` (6), `KeyPressed` (3), `Delay` (1),
@@ -1208,7 +1216,7 @@ remaining run-time capacity note.
 | limit | value | CALC needs | verdict |
 |---|---|---|---|
 | `TextLimit` (source buffer) | 62,903 | `CALC.PAS` + `CALC.INC`, normalised = **62,415** | **488 bytes of slack** |
-| `MaxCode` | 24,000 | 16,560 B program + 4,248 B runtime = **20,808 B** | **OK, 3,192 B spare** (§3.2) |
+| `MaxCode` | 24,000 | 16,560 B program + 4,384 B runtime = **20,944 B** | **OK, 3,056 B spare** (§3.2) |
 | code window | `CodeMax = 6F00h`, capped by `MaxCode` | 20,227 B | **OK**; no data gap (§3.2) |
 | data area | fixed image `8000h`, zeroed by `initmem` | **12,032 B** (measured, §3.1) | **OK for compile**; see the run-time cargo note (§3.2) |
 | stack | 16,384 min / 655,360 max | 16,384 min | matches the original's `minstk`/`maxstk` |

+ 3 - 2
SUMMARY.md

@@ -2044,7 +2044,7 @@ the compiler *emitting* a 16,560-byte program). The ratchet and front-end
 features through **file control-block operations and the original memory
 layout** are landed: the ladder (`tests/calc_ladder.sh` +
 `tests/fixtures/calc_ladder.tsv`, run by `run_all.sh`; CALC.PAS now stops at
-`ERR 41` at pos 28074, `Val(Buffer^[0],...)` in Help), the `{$I}` include,
+`ERR 102` at pos 31758, `var Value : Real` in Evaluate), the `{$I}` include,
 `^X`/`#nn`, scalar typed constants, sets, enums, records (CellRec = 80),
 subranges, arrays, element/field access, file types, string value parameters,
 `Length`, the CRT identifiers (`ClrScr`/`GotoXY`/`ClrEol`/`LowVideo`/
@@ -2063,7 +2063,8 @@ type (`t87`), file control-block operations (`t88`: `Assign`/`Reset`/
 parameters plus `Chr` (`t89`), typed-file block I/O (`t90`, compile-only), and
 text-file output (`t91`, compile-only), `Str` real formatting (`t92`), and
 pointer types with `New`/`Dispose`/dereference (`t93`), text `Eof`/`Readln`
-(`t94`), and integer `Str` (`t95`). The next rung is `Val` string-to-integer. The runtime is 3,907 bytes / 39 entries and its probe
+(`t94`), integer `Str` (`t95`), and integer `Val` (`t96`). The next rung is
+by-reference REAL parameters (`var Value : Real`). The runtime is 3,907 bytes / 39 entries and its probe
 scaffold is nearly full, so the next runtime addition must move HDR. Items 1-4
 below are independent of both tracks.
 

+ 40 - 2
shell/Compiler.mod

@@ -141,7 +141,7 @@ CONST
       next file increment. *)
    BI_Assign = 16 ; BI_Reset = 17 ; BI_Rewrite = 18 ;
    BI_Close = 19 ; BI_IoResult = 20 ; BI_Chr = 21 ; BI_Str = 22 ;
-   BI_New = 23 ; BI_Dispose = 24 ; BI_Eof = 25 ;
+   BI_New = 23 ; BI_Dispose = 24 ; BI_Eof = 25 ; BI_Val = 26 ;
    (* the sub-codes EmCrtSeq takes *)
    CrtClr = 0 ; CrtDl = 1 ; CrtDh = 2 ; CrtCaret = 3 ; CrtEol = 4 ;
    CrtLow = 5 ; CrtNorm = 6 ; CrtDelay = 7 ; CrtKey = 8 ;
@@ -411,6 +411,7 @@ VAR
    TU_FileEof     : CARDINAL ;  (* text-file end of file *)
    TU_FileReadln  : CARDINAL ;  (* text-file line read *)
    TU_IntFmt      : CARDINAL ;  (* integer -> counted string *)
+   TU_ValInt      : CARDINAL ;  (* counted string -> integer *)
    TU_CmpStr   : CARDINAL ;  (* string comparison; two addresses on the stack,
                                 signed -1/0/+1 in AX *)
    TU_StrCat   : CARDINAL ;  (* string concatenation; dest and source addresses
@@ -5028,7 +5029,7 @@ VAR arg : ERes ;
     pushed : BOOLEAN ;
     skipArg : BOOLEAN ;
     n, p : CARDINAL ;
-    dummy : ERes ;
+    dummy, errV : ERes ;
 BEGIN
    which := symtab [idx].cls ;               (* BI_* *)
    IF which = BI_Halt THEN
@@ -5138,6 +5139,40 @@ BEGIN
       END ;
       RETURN
    END ;
+   IF which = BI_Val THEN
+      (* Val(S, V, E): integer conversion.  E receives 0 on success or the
+         1-based position of the first invalid character; V is left unchanged
+         on error. *)
+      IF NOT MatchDelim ('(') THEN
+         Err (ENoSemi) ;
+         RETURN
+      END ;
+      ParseExpr (arg) ;
+      IF OK () AND (arg.cls = TString) AND
+         ((arg.kind = 1) OR (arg.kind = 3) OR (arg.kind = 5)) THEN
+         ExpectDelim (',', ENoSemi) ;
+         ParseExpr (dummy) ;
+         ExpectDelim (',', ENoSemi) ;
+         ParseExpr (errV) ;
+         IF OK () AND (dummy.kind = 1) AND (dummy.cls = TScalar)
+            AND (VarSize (dummy) = 2) AND (errV.kind = 1)
+            AND (errV.cls = TScalar) AND (VarSize (errV) = 2) THEN
+            EmPushVarAddr (symtab [errV.idx].local,
+                           (symtab [errV.idx].off + errV.boff) MOD 10000H) ;
+            EmPushVarAddr (symtab [dummy.idx].local,
+                           (symtab [dummy.idx].off + dummy.boff) MOD 10000H) ;
+            EmPushStrAddr (arg) ;
+            DropC (EmCall (TU_ValInt)) ;
+            EmAddSp (6)
+         ELSIF OK () THEN
+            Err (ETypeErr)
+         END
+      ELSIF OK () THEN
+         Err (ETypeErr)
+      END ;
+      ExpectDelim (')', ENoSemi) ;
+      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
@@ -7287,6 +7322,8 @@ BEGIN
    symtab [i].defnd := TRUE ;
    i := NewSym ("EOF", KBuiltin, BI_Eof, 0, 0, 0, 0, FALSE) ;
    symtab [i].defnd := TRUE ;
+   i := NewSym ("VAL", KBuiltin, BI_Val, 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. *)
@@ -7454,6 +7491,7 @@ BEGIN
    TU_FileEof     := RT_Entry (41) ;
    TU_FileReadln  := RT_Entry (42) ;
    TU_IntFmt      := RT_Entry (43) ;
+   TU_ValInt      := RT_Entry (44) ;
    TU_WrStr    := RT_Entry (15) ;      (* a string variable is written through
                                           the address on the stack *)
    TU_RdStr    := RT_Entry (16) ;      (* readln(s)/read(s): TPSRC8 prdstr,

+ 1 - 0
shell/Runtime.def

@@ -82,6 +82,7 @@ CONST
    E_FileEof = 41 ;         (* [BP+4]=text file; AX = 1 at end *)
    E_FileReadln = 42 ;      (* [BP+4]=file, [BP+6]=dest string, [BP+8]=max *)
    E_IntFmt = 43 ;          (* [BP+4]=dest string, [BP+6]=integer value *)
+   E_ValInt = 44 ;          (* [BP+4]=string, [BP+6]=dest, [BP+8]=error pos *)
 
    (* File control block, mirrored by Compiler.FileVarSize. *)
    F_NameOff = 4 ;           (* handle word, mode word, then the name *)

+ 65 - 3
shell/Runtime.mod

@@ -101,7 +101,9 @@ CONST
    D_HEAP  = 197 ;    (* 2 bytes: the bump allocator's next free byte *)
    D_TXEOF = 199 ;    (* 1 byte: text Readln saw ^Z or physical EOF *)
    D_TXCH  = 200 ;    (* 1 byte: one-byte INT 21h read scratch *)
-   D_END   = 201 ;    (* the block is padded to here *)
+   D_VALSIGN = 201 ;  (* 1 byte: Val integer sign flag *)
+   D_VALCH = 202 ;    (* 2 bytes: Val digit scratch *)
+   D_END   = 204 ;    (* the block is padded to here *)
 
    (* THE LOAD BIAS.  Everything above is an offset into the image as this
       compiler numbers it: the entry JMP is at image 0.  But a DOS .COM is
@@ -158,7 +160,7 @@ VAR
    dataAt : CARDINAL ;
    rtBase : CARDINAL ;
    built  : BOOLEAN ;
-   entNm  : ARRAY [0..43] OF ARRAY [0..MaxNm] OF CHAR ;
+   entNm  : ARRAY [0..44] OF ARRAY [0..MaxNm] OF CHAR ;
 
 (* ---------------------------------------------------------------- *)
 (*  name helpers                                                     *)
@@ -3157,6 +3159,57 @@ BEGIN
    MovBxBp4 ;
    B (88H) ; B (17H) ;               (* MOV [BX],DL: dest[0] := length *)
    PopDi ; PopSi ; PopDx ; PopCx ; PopBx ;
+   MovSpBp ; PopBp ; RetR ;
+
+   (* Val integer: [BP+4]=counted string, [BP+6]=dest integer,
+      [BP+8]=error position.  Code is 1-based and 0 on success; on error the
+      destination is left unchanged, matching TPSRC2's valerr path. *)
+   M ("val_int") ;
+   PushBp ; MovBpSp ;
+   PushBx ; PushCx ; PushDx ; PushSi ; PushDi ;
+   MovDiBp4 ;
+   LdAlDi ; MovClAl ; B (30H) ; B (0EDH) ;   (* CL=len, CH=0 *)
+   IncDi ;
+   B (89H) ; B (0FEH) ;               (* MOV SI,DI: first character *)
+   XorBxBx ;
+   StDataByte (D_VALSIGN, 0) ;
+   Jcxz8 ("vi_empty") ;
+   LdAlDi ;
+   B (3CH) ; B (2DH) ; Je8 ("vi_neg") ;       (* '-' *)
+   Jmp8 ("vi_loop") ;
+   M ("vi_neg") ;
+   StDataByte (D_VALSIGN, 1) ;
+   IncDi ; B (49H) ;                  (* INC DI, DEC CX *)
+   Jcxz8 ("vi_err") ;
+   M ("vi_loop") ;
+   LdAlDi ;
+   B (3CH) ; B (30H) ; Jb8 ("vi_err") ;       (* < '0' *)
+   B (3CH) ; B (39H) ; Ja8 ("vi_err") ;       (* > '9' *)
+   SubAl (ORD ("0")) ;
+   XorAhAh ;
+   StDataAx (D_VALCH) ;
+   MovAxBx ; MovBxImm (10) ; MulBx ;
+   B (03H) ; B (06H) ; Dd (D_VALCH) ;  (* ADD AX,[D_VALCH] *)
+   B (89H) ; B (0C3H) ;               (* MOV BX,AX *)
+   IncDi ; B (49H) ;                  (* INC DI, DEC CX *)
+   Jcxz8 ("vi_ok") ;
+   Jmp8 ("vi_loop") ;
+   M ("vi_empty") ;
+   MovBxBp8 ; XorAxAx ; B (89H) ; B (07H) ;   (* error := 0 *)
+   Jmp8 ("vi_done") ;
+   M ("vi_ok") ;
+   LdAlData (D_VALSIGN) ; CmpAl0 ; Je8 ("vi_store") ;
+   B (0F7H) ; B (0DBH) ;              (* NEG BX *)
+   M ("vi_store") ;
+   MovAxBx ; MovBxBp6 ; B (89H) ; B (07H) ;   (* dest := value *)
+   MovBxBp8 ; XorAxAx ; B (89H) ; B (07H) ;   (* error := 0 *)
+   Jmp8 ("vi_done") ;
+   M ("vi_err") ;
+   MovAxDi ; B (2BH) ; B (0C6H) ;     (* SUB AX,SI *)
+   B (40H) ;                          (* INC AX: 1-based position *)
+   MovBxBp8 ; B (89H) ; B (07H) ;     (* error := position *)
+   M ("vi_done") ;
+   PopDi ; PopSi ; PopDx ; PopCx ; PopBx ;
    MovSpBp ; PopBp ; RetR
 END EmitFileOps ;
 
@@ -3309,6 +3362,14 @@ BEGIN
       HALT
    END ;
    B (0) ;                         (* one-byte text read scratch *)
+   IF dataAt + D_VALSIGN # rpos THEN
+      HALT
+   END ;
+   B (0) ;                         (* Val sign flag *)
+   IF dataAt + D_VALCH # rpos THEN
+      HALT
+   END ;
+   B (0) ; B (0) ;                 (* Val digit scratch *)
    WHILE rpos < dataAt + D_END DO
       B (0)
    END ;
@@ -3426,6 +3487,7 @@ BEGIN
    SetStr (entNm [41], "file_eof") ;
    SetStr (entNm [42], "file_readln") ;
    SetStr (entNm [43], "int_fmt") ;
+   SetStr (entNm [44], "val_int") ;
    built := TRUE
 END RT_Build ;
 
@@ -3453,7 +3515,7 @@ BEGIN
    IF NOT built THEN
       RT_Build (0)
    END ;
-   IF i > 43 THEN
+   IF i > 44 THEN
       RETURN 0
    END ;
    RETURN rtBase + LblOff (entNm [i])

+ 4 - 3
shell/tests/RtProbe.mod

@@ -108,7 +108,7 @@ END PENT ;
 
 PROCEDURE Main ;
 VAR i, n, base : CARDINAL ;
-    names : ARRAY [0..43] OF ARRAY [0..15] OF CHAR ;
+    names : ARRAY [0..44] OF ARRAY [0..15] OF CHAR ;
 BEGIN
    base := GetBase () ;
    RT_Build (base) ;
@@ -121,7 +121,7 @@ BEGIN
    PCARD (RT_Size ()) ; PS (" bytes") ; NL ;
    PS ("code ends at ") ; PCARD (RT_CodeEnd ()) ; NL ;
    i := 0 ;
-   WHILE i <= 43 DO
+   WHILE i <= 44 DO
       names [i] := "" ;
       INC (i)
    END ;
@@ -156,8 +156,9 @@ BEGIN
    names [41] := "file_eof" ;
    names [42] := "file_readln" ;
    names [43] := "int_fmt" ;
+   names [44] := "val_int" ;
    i := 0 ;
-   WHILE i <= 43 DO
+   WHILE i <= 44 DO
       PENT (i, names [i]) ;
       INC (i)
    END ;

+ 6 - 6
shell/tests/fixtures/calc_ladder.tsv

@@ -25,12 +25,12 @@
 # positions shift — which is exactly why this must be a measured number, not a
 # remembered one.
 #
-# Current rung (2026-10-23): `Val(Buffer^[0],EndOfFile,ErrorResult)' in Help.
+# Current rung (2026-10-23): `var Value : Real' in Evaluate's parameter list.
 # UpCase, run-time set membership, string fields through DI, the original
 # memory layout, untyped-file declarations, file control-block operations, VAR
 # string parameters, Chr, typed-file block I/O, text-file output, Str,
-# pointers/New/dereference, text Eof/Readln and Str(integer) moved the ladder
-# 15911 -> 18267 -> 19847 -> 20912 -> 22253 -> 22280 -> 22706 -> 22859 ->
-# 23700 -> 25674 -> 26066 -> 26924 -> 27648 -> 28074.  The next blocker is Val
-# string-to-integer conversion (TP3 error 41).
-CALC.PAS	ERR	41	28074
+# pointers/New/dereference, text Eof/Readln, Str(integer) and Val(integer)
+# moved the ladder 15911 -> 18267 -> 19847 -> 20912 -> 22253 -> 22280 -> 22706
+# -> 22859 -> 23700 -> 25674 -> 26066 -> 26924 -> 27648 -> 28074 -> 31758.
+# The next blocker is a VAR parameter of type Real (TP3 error 102).
+CALC.PAS	ERR	102	31758

+ 5 - 0
shell/tests/fixtures/expected.tsv

@@ -678,3 +678,8 @@ t94_textread	OK	206	147
 #   t95_strint           Str(integer, S) via int_fmt: positive, negative and
 #                   zero, all into a string[10].
 t95_strint	OK	133	18
+
+#   t96_valint           Val(string, integer, error): positive, negative,
+#                   an invalid character at position 3 (destination unchanged)
+#                   and an empty string.
+t96_valint	OK	328	20

+ 4 - 0
shell/tests/fixtures/t96_valint.out

@@ -0,0 +1,4 @@
+42 0
+-7 0
+0 3
+0 0

+ 26 - 0
shell/tests/fixtures/t96_valint.pas

@@ -0,0 +1,26 @@
+program t96_valint;
+
+{ t96 -- Val(string, integer, error).  CALC.INC's Help converts the line count
+  string into EndOfFile with Val; the error position must be 0 on a valid
+  string and the 1-based position of the first bad character otherwise.  On
+  error the destination is unchanged (TPSRC2 valerr). }
+
+var
+  S : string[10];
+  I, E : integer;
+begin
+  S := '42';
+  I := 0;
+  Val (S, I, E);
+  writeln (I, ' ', E);
+  S := '-7';
+  Val (S, I, E);
+  writeln (I, ' ', E);
+  S := '12x';
+  I := 0;
+  Val (S, I, E);
+  writeln (I, ' ', E);
+  S := '';
+  Val (S, I, E);
+  writeln (I, ' ', E)
+end.

+ 1 - 1
shell/tests/rt_exec.py

@@ -114,7 +114,7 @@ ENTS = ["initmem", "progend", "stackchk", "wrint", "wrchar", "wrbool",
         "real_write", "set_op", "set_cmp", "set_copy",
         "file_assign", "file_reset", "file_rewrite", "file_close",
         "ioresult", "io_store", "heap_new", "file_eof", "file_readln",
-        "int_fmt"]
+        "int_fmt", "val_int"]
 
 # A call slot's flags, as rtdrv.s reads them.
 F_STACK = 1     # the argument goes on the stack, popped by the caller

+ 185 - 116
shell/tests/runtime.golden

@@ -22,7 +22,7 @@
 0015  39 CF       cmp di,cx
 0017  72 F5       jb 0eh
 0019  89 C8       mov ax,cx
-001B  A3 94 11    mov word ptr [1194h],ax
+001B  A3 1B 12    mov word ptr [121bh],ax
 001E  1E          push ds
 001F  07          pop es
 0020  C3          ret
@@ -43,7 +43,7 @@
 003B  58          pop ax
 003C  F7 D8       neg ax
 003E  B9 0A 00    mov cx,0ah
-0041  BB D7 10    mov bx,10d7h
+0041  BB 5E 11    mov bx,115eh
 0044  89 DE       mov si,bx
 0046  31 D2       xor dx,dx
 0048  F7 F1       div ax,cx
@@ -95,7 +95,7 @@
 00A7  58          pop ax
 00A8  F7 D8       neg ax
 00AA  B9 0A 00    mov cx,0ah
-00AD  BB D7 10    mov bx,10d7h
+00AD  BB 5E 11    mov bx,115eh
 00B0  89 DE       mov si,bx
 00B2  31 D2       xor dx,dx
 00B4  F7 F1       div ax,cx
@@ -127,18 +127,18 @@
 00E3  83 7E 04 00 cmp word ptr [bp+4h],0h
 00E7  89 EC       mov sp,bp
 00E9  75 05       jne 0f0h
-00EB  BA DC 10    mov dx,10dch
+00EB  BA 63 11    mov dx,1163h
 00EE  EB 03       jmp 0f3h
-00F0  BA D7 10    mov dx,10d7h
+00F0  BA 5E 11    mov dx,115eh
 00F3  B4 09       mov ah,9h
 00F5  CD 21       int 21h
 00F7  5D          pop bp
 00F8  C3          ret
-00F9  BA E5 10    mov dx,10e5h
+00F9  BA 6C 11    mov dx,116ch
 00FC  B4 09       mov ah,9h
 00FE  CD 21       int 21h
 0100  C3          ret
-0101  BA E2 10    mov dx,10e2h
+0101  BA 69 11    mov dx,1169h
 0104  B4 09       mov ah,9h
 0106  CD 21       int 21h
 0108  C3          ret
@@ -305,12 +305,12 @@
 021C  EB EF       jmp 20dh
 021E  58          pop ax
 021F  C3          ret
-0220  8B 1E EB 10 mov bx,word ptr [10ebh]
+0220  8B 1E 72 11 mov bx,word ptr [1172h]
 0224  83 FB 00    cmp bx,0h
 0227  74 09       je 232h
 0229  8A C3       mov al,bl
 022B  31 DB       xor bx,bx
-022D  89 1E EB 10 mov word ptr [10ebh],bx
+022D  89 1E 72 11 mov word ptr [1172h],bx
 0231  C3          ret
 0232  B4 08       mov ah,8h
 0234  CD 21       int 21h
@@ -318,7 +318,7 @@
 0237  88 C2       mov dl,al
 0239  BB 01 00    mov bx,1h
 023C  8A DA       mov bl,dl
-023E  89 1E EB 10 mov word ptr [10ebh],bx
+023E  89 1E 72 11 mov word ptr [1172h],bx
 0242  C3          ret
 0243  55          push bp
 0244  8B EC       mov bp,sp
@@ -545,7 +545,7 @@
 03C7  8B 4D 06    mov cx,word ptr [di+6h]
 03CA  8B 75 08    mov si,word ptr [di+8h]
 03CD  8B 7D 0A    mov di,word ptr [di+0ah]
-03D0  C7 06 ED 10 00 00 mov word ptr [10edh],0h
+03D0  C7 06 74 11 00 00 mov word ptr [1174h],0h
 03D6  E8 4D 00    call 426h
 03D9  5F          pop di
 03DA  89 05       mov word ptr [di],ax
@@ -574,7 +574,7 @@
 0403  8B 4D 06    mov cx,word ptr [di+6h]
 0406  8B 75 08    mov si,word ptr [di+8h]
 0409  8B 7D 0A    mov di,word ptr [di+0ah]
-040C  C7 06 ED 10 00 80 mov word ptr [10edh],8000h
+040C  C7 06 74 11 00 80 mov word ptr [1174h],8000h
 0412  E8 11 00    call 426h
 0415  5F          pop di
 0416  89 05       mov word ptr [di],ax
@@ -589,7 +589,7 @@
 0425  C3          ret
 0426  80 F9 00    cmp cl,0h
 0429  74 0E       je 439h
-042B  33 3E ED 10 xor di,word ptr [10edh]
+042B  33 3E 74 11 xor di,word ptr [1174h]
 042F  3C 00       cmp al,0h
 0431  75 07       jne 43ah
 0433  89 C8       mov ax,cx
@@ -601,16 +601,16 @@
 043E  91          xchg ax,cx
 043F  87 F3       xchg bx,si
 0441  87 FA       xchg dx,di
-0443  88 0E F1 10 mov byte ptr [10f1h],cl
+0443  88 0E 78 11 mov byte ptr [1178h],cl
 0447  28 C1       sub cl,al
 0449  80 F9 28    cmp cl,28h
 044C  72 06       jb 454h
-044E  8A 0E F1 10 mov cl,byte ptr [10f1h]
+044E  8A 0E 78 11 mov cl,byte ptr [1178h]
 0452  EB DF       jmp 433h
-0454  89 3E ED 10 mov word ptr [10edh],di
-0458  80 26 EE 10 80 and byte ptr [10eeh],80h
-045D  89 3E EF 10 mov word ptr [10efh],di
-0461  30 36 F0 10 xor byte ptr [10f0h],dh
+0454  89 3E 74 11 mov word ptr [1174h],di
+0458  80 26 75 11 80 and byte ptr [1175h],80h
+045D  89 3E 76 11 mov word ptr [1176h],di
+0461  30 36 77 11 xor byte ptr [1177h],dh
 0465  81 CF 00 80 or di,8000h
 0469  80 CE 80    or dh,80h
 046C  80 F9 10    cmp cl,10h
@@ -635,8 +635,8 @@
 0497  D0 DC       rcr ah,1h
 0499  FE C9       dec cl
 049B  75 F6       jne 493h
-049D  A0 F1 10    mov al,byte ptr [10f1h]
-04A0  F6 06 F0 10 80 test byte ptr [10f0h],80h
+049D  A0 78 11    mov al,byte ptr [1178h]
+04A0  F6 06 77 11 80 test byte ptr [1177h],80h
 04A5  75 14       jne 4bbh
 04A7  00 EC       add ah,ch
 04A9  11 F3       adc bx,si
@@ -656,7 +656,7 @@
 04C3  19 F3       sbb bx,si
 04C5  19 FA       sbb dx,di
 04C7  73 14       jnb 4ddh
-04C9  80 36 EE 10 80 xor byte ptr [10eeh],80h
+04C9  80 36 75 11 80 xor byte ptr [1175h],80h
 04CE  F6 D4       not ah
 04D0  F7 D3       not bx
 04D2  F7 D2       not dx
@@ -688,7 +688,7 @@
 050B  31 D2       xor dx,dx
 050D  C3          ret
 050E  80 E6 7F    and dh,7fh
-0511  32 36 EE 10 xor dh,byte ptr [10eeh]
+0511  32 36 75 11 xor dh,byte ptr [1175h]
 0515  C3          ret
 0516  55          push bp
 0517  8B EC       mov bp,sp
@@ -734,23 +734,23 @@
 056A  B0 01       mov al,1h
 056C  B4 4C       mov ah,4ch
 056E  CD 21       int 21h
-0570  89 0E F8 10 mov word ptr [10f8h],cx
+0570  89 0E 7F 11 mov word ptr [117fh],cx
 0574  8B CA       mov cx,dx
 0576  31 F9       xor cx,di
 0578  F6 D5       not ch
 057A  80 E5 80    and ch,80h
-057D  88 2E EE 10 mov byte ptr [10eeh],ch
+057D  88 2E 75 11 mov byte ptr [1175h],ch
 0581  80 CE 80    or dh,80h
 0584  81 CF 00 80 or di,8000h
-0588  89 36 FA 10 mov word ptr [10fah],si
-058C  89 3E FC 10 mov word ptr [10fch],di
-0590  A3 F2 10    mov word ptr [10f2h],ax
-0593  89 1E F4 10 mov word ptr [10f4h],bx
-0597  89 16 F6 10 mov word ptr [10f6h],dx
+0588  89 36 81 11 mov word ptr [1181h],si
+058C  89 3E 83 11 mov word ptr [1183h],di
+0590  A3 79 11    mov word ptr [1179h],ax
+0593  89 1E 7B 11 mov word ptr [117bh],bx
+0597  89 16 7D 11 mov word ptr [117dh],dx
 059B  30 E4       xor ah,ah
 059D  31 DB       xor bx,bx
 059F  31 D2       xor dx,dx
-05A1  BF F8 10    mov di,10f8h
+05A1  BF 7F 11    mov di,117fh
 05A4  B1 05       mov cl,5h
 05A6  47          inc di
 05A7  8A 2D       mov ch,byte ptr [di]
@@ -765,9 +765,9 @@
 05BA  BE 08 00    mov si,8h
 05BD  D0 DD       rcr ch,1h
 05BF  73 0C       jnb 5cdh
-05C1  02 26 F3 10 add ah,byte ptr [10f3h]
-05C5  13 1E F4 10 adc bx,word ptr [10f4h]
-05C9  13 16 F6 10 adc dx,word ptr [10f6h]
+05C1  02 26 7A 11 add ah,byte ptr [117ah]
+05C5  13 1E 7B 11 adc bx,word ptr [117bh]
+05C9  13 16 7D 11 adc dx,word ptr [117dh]
 05CD  D1 DA       rcr dx,1h
 05CF  D1 DB       rcr bx,1h
 05D1  D0 DC       rcr ah,1h
@@ -787,7 +787,7 @@
 05EB  74 02       je 5efh
 05ED  FE C9       dec cl
 05EF  91          xchg ax,cx
-05F0  32 36 EE 10 xor dh,byte ptr [10eeh]
+05F0  32 36 75 11 xor dh,byte ptr [1175h]
 05F4  3C 00       cmp al,0h
 05F6  75 06       jne 5feh
 05F8  31 C0       xor ax,ax
@@ -836,29 +836,29 @@
 064C  B0 01       mov al,1h
 064E  B4 4C       mov ah,4ch
 0650  CD 21       int 21h
-0652  89 0E F8 10 mov word ptr [10f8h],cx
+0652  89 0E 7F 11 mov word ptr [117fh],cx
 0656  8B CA       mov cx,dx
 0658  31 F9       xor cx,di
 065A  F6 D5       not ch
 065C  80 E5 80    and ch,80h
-065F  88 2E EE 10 mov byte ptr [10eeh],ch
+065F  88 2E 75 11 mov byte ptr [1175h],ch
 0663  80 CE 80    or dh,80h
 0666  81 CF 00 80 or di,8000h
-066A  89 36 FA 10 mov word ptr [10fah],si
-066E  89 3E FC 10 mov word ptr [10fch],di
-0672  A2 F2 10    mov byte ptr [10f2h],al
-0675  BF F7 10    mov di,10f7h
+066A  89 36 81 11 mov word ptr [1181h],si
+066E  89 3E 83 11 mov word ptr [1183h],di
+0672  A2 79 11    mov byte ptr [1179h],al
+0675  BF 7E 11    mov di,117eh
 0678  B1 05       mov cl,5h
 067A  BE 08 00    mov si,8h
-067D  3B 16 FC 10 cmp dx,word ptr [10fch]
+067D  3B 16 83 11 cmp dx,word ptr [1183h]
 0681  75 0A       jne 68dh
-0683  3B 1E FA 10 cmp bx,word ptr [10fah]
+0683  3B 1E 81 11 cmp bx,word ptr [1181h]
 0687  75 04       jne 68dh
-0689  3A 26 F9 10 cmp ah,byte ptr [10f9h]
+0689  3A 26 80 11 cmp ah,byte ptr [1180h]
 068D  72 0C       jb 69bh
-068F  2A 26 F9 10 sub ah,byte ptr [10f9h]
-0693  1B 1E FA 10 sbb bx,word ptr [10fah]
-0697  1B 16 FC 10 sbb dx,word ptr [10fch]
+068F  2A 26 80 11 sub ah,byte ptr [1180h]
+0693  1B 1E 81 11 sbb bx,word ptr [1181h]
+0697  1B 16 83 11 sbb dx,word ptr [1183h]
 069B  F5          cmc
 069C  D0 D5       rcl ch,1h
 069E  4E          dec si
@@ -872,24 +872,24 @@
 06AD  D1 D3       rcl bx,1h
 06AF  D1 D2       rcl dx,1h
 06B1  73 CA       jnb 67dh
-06B3  2A 26 F9 10 sub ah,byte ptr [10f9h]
-06B7  1B 1E FA 10 sbb bx,word ptr [10fah]
-06BB  1B 16 FC 10 sbb dx,word ptr [10fch]
+06B3  2A 26 80 11 sub ah,byte ptr [1180h]
+06B7  1B 1E 81 11 sbb bx,word ptr [1181h]
+06BB  1B 16 83 11 sbb dx,word ptr [1183h]
 06BF  F8          clc
 06C0  EB D9       jmp 69bh
 06C2  D0 E4       shl ah,1h
 06C4  D1 D3       rcl bx,1h
 06C6  D1 D2       rcl dx,1h
 06C8  72 11       jb 6dbh
-06CA  3B 16 FC 10 cmp dx,word ptr [10fch]
+06CA  3B 16 83 11 cmp dx,word ptr [1183h]
 06CE  75 0A       jne 6dah
-06D0  3B 1E FA 10 cmp bx,word ptr [10fah]
+06D0  3B 1E 81 11 cmp bx,word ptr [1181h]
 06D4  75 04       jne 6dah
-06D6  3A 26 F9 10 cmp ah,byte ptr [10f9h]
+06D6  3A 26 80 11 cmp ah,byte ptr [1180h]
 06DA  F5          cmc
-06DB  8B 0E F2 10 mov cx,word ptr [10f2h]
-06DF  8B 1E F4 10 mov bx,word ptr [10f4h]
-06E3  8B 16 F6 10 mov dx,word ptr [10f6h]
+06DB  8B 0E 79 11 mov cx,word ptr [1179h]
+06DF  8B 1E 7B 11 mov bx,word ptr [117bh]
+06E3  8B 16 7D 11 mov dx,word ptr [117dh]
 06E7  9F          lahf
 06E8  F6 C6 80    test dh,80h
 06EB  75 09       jne 6f6h
@@ -1032,47 +1032,47 @@
 07F1  B5 00       mov ch,0h
 07F3  B6 00       mov dh,0h
 07F5  51          push cx
-07F6  BB 48 11    mov bx,1148h
+07F6  BB CF 11    mov bx,11cfh
 07F9  E8 41 02    call 0a3dh
 07FC  59          pop cx
 07FD  89 D8       mov ax,bx
-07FF  BB 48 11    mov bx,1148h
+07FF  BB CF 11    mov bx,11cfh
 0802  2B C3       sub ax,bx
-0804  A3 88 11    mov word ptr [1188h],ax
-0807  89 0E 8A 11 mov word ptr [118ah],cx
-080B  8B 06 8A 11 mov ax,word ptr [118ah]
-080F  8B 16 88 11 mov dx,word ptr [1188h]
+0804  A3 0F 12    mov word ptr [120fh],ax
+0807  89 0E 11 12 mov word ptr [1211h],cx
+080B  8B 06 11 12 mov ax,word ptr [1211h]
+080F  8B 16 0F 12 mov dx,word ptr [120fh]
 0813  2B C2       sub ax,dx
 0815  83 F8 00    cmp ax,0h
 0818  7D 02       jnl 81ch
 081A  31 C0       xor ax,ax
-081C  A3 8C 11    mov word ptr [118ch],ax
-081F  8B 16 88 11 mov dx,word ptr [1188h]
+081C  A3 13 12    mov word ptr [1213h],ax
+081F  8B 16 0F 12 mov dx,word ptr [120fh]
 0823  03 C2       add ax,dx
 0825  3D FF 00    cmp ax,0ffh
 0828  77 03       jnbe 82dh
 082A  E9 03 00    jmp 830h
 082D  B8 FF 00    mov ax,0ffh
-0830  A3 8E 11    mov word ptr [118eh],ax
+0830  A3 15 12    mov word ptr [1215h],ax
 0833  8B 56 06    mov dx,word ptr [bp+6h]
 0836  89 D7       mov di,dx
 0838  88 05       mov byte ptr [di],al
 083A  47          inc di
-083B  8B 0E 8C 11 mov cx,word ptr [118ch]
+083B  8B 0E 13 12 mov cx,word ptr [1213h]
 083F  E3 07       jcxz 848h
 0841  B0 20       mov al,20h
 0843  88 05       mov byte ptr [di],al
 0845  47          inc di
 0846  E2 F9       loop 841h
-0848  BE 48 11    mov si,1148h
-084B  8B 0E 88 11 mov cx,word ptr [1188h]
+0848  BE CF 11    mov si,11cfh
+084B  8B 0E 0F 12 mov cx,word ptr [120fh]
 084F  E3 08       jcxz 859h
 0851  8A 04       mov al,byte ptr [si]
 0853  88 05       mov byte ptr [di],al
 0855  46          inc si
 0856  47          inc di
 0857  E2 F8       loop 851h
-0859  8B 06 8E 11 mov ax,word ptr [118eh]
+0859  8B 06 15 12 mov ax,word ptr [1215h]
 085D  5F          pop di
 085E  5E          pop si
 085F  5A          pop dx
@@ -1088,12 +1088,12 @@
 086B  57          push di
 086C  8B 5E 04    mov bx,word ptr [bp+4h]
 086F  8B 7E 06    mov di,word ptr [bp+6h]
-0872  89 1E 90 11 mov word ptr [1190h],bx
+0872  89 1E 17 12 mov word ptr [1217h],bx
 0876  E8 CF 02    call 0b48h
 0879  73 03       jnb 87eh
 087B  E9 0B 00    jmp 889h
 087E  89 D8       mov ax,bx
-0880  8B 16 90 11 mov dx,word ptr [1190h]
+0880  8B 16 17 12 mov dx,word ptr [1217h]
 0884  2B C2       sub ax,dx
 0886  E9 03 00    jmp 88ch
 0889  B8 FF FF    mov ax,0ffffh
@@ -1142,7 +1142,7 @@
 08D3  52          push dx
 08D4  53          push bx
 08D5  50          push ax
-08D6  88 0E 0A 11 mov byte ptr [110ah],cl
+08D6  88 0E 91 11 mov byte ptr [1191h],cl
 08DA  80 F9 00    cmp cl,0h
 08DD  78 03       js 8e2h
 08DF  E9 02 00    jmp 8e4h
@@ -1153,7 +1153,7 @@
 08EB  D0 EB       shr bl,1h
 08ED  00 FB       add bl,bh
 08EF  30 FF       xor bh,bh
-08F1  8D BF 0C 11 lea di,[bx+110ch]
+08F1  8D BF 93 11 lea di,[bx+1193h]
 08F5  8B 05       mov ax,word ptr [di]
 08F7  8B 5D 02    mov bx,word ptr [di+2h]
 08FA  8B 55 04    mov dx,word ptr [di+4h]
@@ -1170,7 +1170,7 @@
 0915  58          pop ax
 0916  5B          pop bx
 0917  5A          pop dx
-0918  F6 06 0A 11 80 test byte ptr [110ah],80h
+0918  F6 06 91 11 80 test byte ptr [1191h],80h
 091D  74 03       je 922h
 091F  E9 03 00    jmp 925h
 0922  E9 27 FC    jmp 54ch
@@ -1197,11 +1197,11 @@
 094C  3C 00       cmp al,0h
 094E  74 03       je 953h
 0950  E9 16 00    jmp 969h
-0953  BE FE 10    mov si,10feh
+0953  BE 85 11    mov si,1185h
 0956  C7 04 30 30 mov word ptr [si],3030h
 095A  46          inc si
 095B  46          inc si
-095C  81 FE 0A 11 cmp si,110ah
+095C  81 FE 91 11 cmp si,1191h
 0960  74 03       je 965h
 0962  E9 F1 FF    jmp 956h
 0965  B9 00 00    mov cx,0h
@@ -1245,7 +1245,7 @@
 09B4  FE C9       dec cl
 09B6  74 03       je 9bbh
 09B8  E9 F3 FF    jmp 9aeh
-09BB  BE FE 10    mov si,10feh
+09BB  BE 85 11    mov si,1185h
 09BE  88 F5       mov ch,dh
 09C0  B1 04       mov cl,4h
 09C2  D2 ED       shr ch,cl
@@ -1271,13 +1271,13 @@
 09E6  D1 D3       rcl bx,1h
 09E8  D1 D2       rcl dx,1h
 09EA  46          inc si
-09EB  81 FE 0A 11 cmp si,110ah
+09EB  81 FE 91 11 cmp si,1191h
 09EF  74 03       je 9f4h
 09F1  E9 CA FF    jmp 9beh
 09F4  59          pop cx
 09F5  C3          ret
 09F6  30 E4       xor ah,ah
-09F8  BB FE 10    mov bx,10feh
+09F8  BB 85 11    mov bx,1185h
 09FB  03 D8       add bx,ax
 09FD  80 3F 35    cmp byte ptr [bx],35h
 0A00  C6 07 00    mov byte ptr [bx],0h
@@ -1348,7 +1348,7 @@
 0A97  00 C8       add al,cl
 0A99  78 03       js 0a9eh
 0A9B  E9 08 00    jmp 0aa6h
-0A9E  C6 06 FE 10 00 mov byte ptr [10feh],0h
+0A9E  C6 06 85 11 00 mov byte ptr [1185h],0h
 0AA3  E9 0C 00    jmp 0ab2h
 0AA6  3C 0C       cmp al,0ch
 0AA8  73 03       jnb 0aadh
@@ -1356,7 +1356,7 @@
 0AAD  B0 0B       mov al,0bh
 0AAF  E8 44 FF    call 9f6h
 0AB2  5B          pop bx
-0AB3  BE FE 10    mov si,10feh
+0AB3  BE 85 11    mov si,1185h
 0AB6  F6 C5 80    test ch,80h
 0AB9  75 03       jne 0abeh
 0ABB  E9 05 00    jmp 0ac3h
@@ -1442,7 +1442,7 @@
 0B7A  31 DB       xor bx,bx
 0B7C  31 D2       xor dx,dx
 0B7E  31 C9       xor cx,cx
-0B80  C6 06 0B 11 00 mov byte ptr [110bh],0h
+0B80  C6 06 92 11 00 mov byte ptr [1192h],0h
 0B85  8A 0C       mov cl,byte ptr [si]
 0B87  80 F9 61    cmp cl,61h
 0B8A  73 03       jnb 0b8fh
@@ -1471,7 +1471,7 @@
 0BBA  58          pop ax
 0BBB  5B          pop bx
 0BBC  5A          pop dx
-0BBD  C7 06 ED 10 00 00 mov word ptr [10edh],0h
+0BBD  C7 06 74 11 00 00 mov word ptr [1174h],0h
 0BC3  E8 60 F8    call 426h
 0BC6  59          pop cx
 0BC7  5E          pop si
@@ -1479,7 +1479,7 @@
 0BC9  F6 C5 40    test ch,40h
 0BCC  75 03       jne 0bd1h
 0BCE  E9 04 00    jmp 0bd5h
-0BD1  FE 0E 0B 11 dec byte ptr [110bh]
+0BD1  FE 0E 92 11 dec byte ptr [1192h]
 0BD5  46          inc si
 0BD6  E9 AC FF    jmp 0b85h
 0BD9  80 F9 2E    cmp cl,2eh
@@ -1491,7 +1491,7 @@
 0BE9  80 CD 40    or ch,40h
 0BEC  E9 E6 FF    jmp 0bd5h
 0BEF  80 F9 45    cmp cl,45h
-0BF2  8A 0E 0B 11 mov cl,byte ptr [110bh]
+0BF2  8A 0E 92 11 mov cl,byte ptr [1192h]
 0BF6  74 03       je 0bfbh
 0BF8  E9 4D 00    jmp 0c48h
 0BFB  E8 2A FD    call 928h
@@ -1557,31 +1557,31 @@
 0C7C  56          push si
 0C7D  57          push di
 0C7E  8B 46 06    mov ax,word ptr [bp+6h]
-0C81  A3 8A 11    mov word ptr [118ah],ax
+0C81  A3 11 12    mov word ptr [1211h],ax
 0C84  8B 56 04    mov dx,word ptr [bp+4h]
 0C87  8B 4E 06    mov cx,word ptr [bp+6h]
 0C8A  8B 7E 08    mov di,word ptr [bp+8h]
-0C8D  BB 48 11    mov bx,1148h
+0C8D  BB CF 11    mov bx,11cfh
 0C90  E8 AA FD    call 0a3dh
 0C93  89 D8       mov ax,bx
-0C95  BB 48 11    mov bx,1148h
+0C95  BB CF 11    mov bx,11cfh
 0C98  2B C3       sub ax,bx
-0C9A  A3 88 11    mov word ptr [1188h],ax
-0C9D  8B 06 8A 11 mov ax,word ptr [118ah]
-0CA1  8B 16 88 11 mov dx,word ptr [1188h]
+0C9A  A3 0F 12    mov word ptr [120fh],ax
+0C9D  8B 06 11 12 mov ax,word ptr [1211h]
+0CA1  8B 16 0F 12 mov dx,word ptr [120fh]
 0CA5  2B C2       sub ax,dx
 0CA7  83 F8 00    cmp ax,0h
 0CAA  7D 02       jnl 0caeh
 0CAC  31 C0       xor ax,ax
-0CAE  A3 8C 11    mov word ptr [118ch],ax
-0CB1  8B 0E 8C 11 mov cx,word ptr [118ch]
+0CAE  A3 13 12    mov word ptr [1213h],ax
+0CB1  8B 0E 13 12 mov cx,word ptr [1213h]
 0CB5  E3 08       jcxz 0cbfh
 0CB7  B0 20       mov al,20h
 0CB9  B4 02       mov ah,2h
 0CBB  CD 21       int 21h
 0CBD  E2 F8       loop 0cb7h
-0CBF  BE 48 11    mov si,1148h
-0CC2  8B 0E 88 11 mov cx,word ptr [1188h]
+0CBF  BE CF 11    mov si,11cfh
+0CC2  8B 0E 0F 12 mov cx,word ptr [120fh]
 0CC6  E3 09       jcxz 0cd1h
 0CC8  8A 04       mov al,byte ptr [si]
 0CCA  B4 02       mov ah,2h
@@ -1752,14 +1752,14 @@
 0DE9  B8 01 00    mov ax,1h
 0DEC  89 45 02    mov word ptr [di+2h],ax
 0DEF  31 C0       xor ax,ax
-0DF1  A3 92 11    mov word ptr [1192h],ax
+0DF1  A3 19 12    mov word ptr [1219h],ax
 0DF4  EB 10       jmp 0e06h
 0DF6  89 C3       mov bx,ax
 0DF8  B8 FF FF    mov ax,0ffffh
 0DFB  89 05       mov word ptr [di],ax
 0DFD  31 C0       xor ax,ax
 0DFF  89 45 02    mov word ptr [di+2h],ax
-0E02  89 1E 92 11 mov word ptr [1192h],bx
+0E02  89 1E 19 12 mov word ptr [1219h],bx
 0E06  5F          pop di
 0E07  5A          pop dx
 0E08  59          pop cx
@@ -1783,14 +1783,14 @@
 0E26  B8 02 00    mov ax,2h
 0E29  89 45 02    mov word ptr [di+2h],ax
 0E2C  31 C0       xor ax,ax
-0E2E  A3 92 11    mov word ptr [1192h],ax
+0E2E  A3 19 12    mov word ptr [1219h],ax
 0E31  EB 10       jmp 0e43h
 0E33  89 C3       mov bx,ax
 0E35  B8 FF FF    mov ax,0ffffh
 0E38  89 05       mov word ptr [di],ax
 0E3A  31 C0       xor ax,ax
 0E3C  89 45 02    mov word ptr [di+2h],ax
-0E3F  89 1E 92 11 mov word ptr [1192h],bx
+0E3F  89 1E 19 12 mov word ptr [1219h],bx
 0E43  5F          pop di
 0E44  5A          pop dx
 0E45  59          pop cx
@@ -1815,30 +1815,30 @@
 0E66  89 05       mov word ptr [di],ax
 0E68  31 C0       xor ax,ax
 0E6A  89 45 02    mov word ptr [di+2h],ax
-0E6D  89 1E 92 11 mov word ptr [1192h],bx
+0E6D  89 1E 19 12 mov word ptr [1219h],bx
 0E71  5F          pop di
 0E72  5A          pop dx
 0E73  5B          pop bx
 0E74  89 EC       mov sp,bp
 0E76  5D          pop bp
 0E77  C3          ret
-0E78  8B 06 92 11 mov ax,word ptr [1192h]
-0E7C  C7 06 92 11 00 00 mov word ptr [1192h],0h
+0E78  8B 06 19 12 mov ax,word ptr [1219h]
+0E7C  C7 06 19 12 00 00 mov word ptr [1219h],0h
 0E82  C3          ret
-0E83  A3 92 11    mov word ptr [1192h],ax
+0E83  A3 19 12    mov word ptr [1219h],ax
 0E86  C3          ret
 0E87  55          push bp
 0E88  8B EC       mov bp,sp
 0E8A  53          push bx
 0E8B  51          push cx
 0E8C  52          push dx
-0E8D  8B 1E 94 11 mov bx,word ptr [1194h]
+0E8D  8B 1E 1B 12 mov bx,word ptr [121bh]
 0E91  8B 56 04    mov dx,word ptr [bp+4h]
 0E94  89 1A       mov word ptr [bp+si],bx
 0E96  8B 4E 06    mov cx,word ptr [bp+6h]
 0E99  89 D8       mov ax,bx
 0E9B  03 C1       add ax,cx
-0E9D  A3 94 11    mov word ptr [1194h],ax
+0E9D  A3 1B 12    mov word ptr [121bh],ax
 0EA0  5A          pop dx
 0EA1  59          pop cx
 0EA2  5B          pop bx
@@ -1852,7 +1852,7 @@
 0EAC  52          push dx
 0EAD  56          push si
 0EAE  57          push di
-0EAF  A0 96 11    mov al,byte ptr [1196h]
+0EAF  A0 1D 12    mov al,byte ptr [121dh]
 0EB2  3C 00       cmp al,0h
 0EB4  75 42       jne 0ef8h
 0EB6  8B 7E 04    mov di,word ptr [bp+4h]
@@ -1909,13 +1909,13 @@
 0F15  8B 76 04    mov si,word ptr [bp+4h]
 0F18  8B 04       mov ax,word ptr [si]
 0F1A  89 C3       mov bx,ax
-0F1C  BA 97 11    mov dx,1197h
+0F1C  BA 1E 12    mov dx,121eh
 0F1F  B9 01 00    mov cx,1h
 0F22  B4 3F       mov ah,3fh
 0F24  CD 21       int 21h
 0F26  83 F8 00    cmp ax,0h
 0F29  74 1C       je 0f47h
-0F2B  A0 97 11    mov al,byte ptr [1197h]
+0F2B  A0 1E 12    mov al,byte ptr [121eh]
 0F2E  3C 1A       cmp al,1ah
 0F30  74 1C       je 0f4eh
 0F32  3C 0D       cmp al,0dh
@@ -1929,13 +1929,13 @@
 0F43  47          inc di
 0F44  41          inc cx
 0F45  EB D1       jmp 0f18h
-0F47  C6 06 96 11 01 mov byte ptr [1196h],1h
+0F47  C6 06 1D 12 01 mov byte ptr [121dh],1h
 0F4C  EB 05       jmp 0f53h
-0F4E  C6 06 96 11 01 mov byte ptr [1196h],1h
+0F4E  C6 06 1D 12 01 mov byte ptr [121dh],1h
 0F53  8B 5E 06    mov bx,word ptr [bp+6h]
 0F56  88 0F       mov byte ptr [bx],cl
 0F58  31 C0       xor ax,ax
-0F5A  A3 92 11    mov word ptr [1192h],ax
+0F5A  A3 19 12    mov word ptr [1219h],ax
 0F5D  5F          pop di
 0F5E  5E          pop si
 0F5F  5A          pop dx
@@ -1955,13 +1955,13 @@
 0F71  C6 05 00    mov byte ptr [di],0h
 0F74  47          inc di
 0F75  8B 46 06    mov ax,word ptr [bp+6h]
-0F78  C6 06 97 11 00 mov byte ptr [1197h],0h
+0F78  C6 06 1E 12 00 mov byte ptr [121eh],0h
 0F7D  83 F8 00    cmp ax,0h
 0F80  7D 07       jnl 0f89h
-0F82  C6 06 97 11 01 mov byte ptr [1197h],1h
+0F82  C6 06 1E 12 01 mov byte ptr [121eh],1h
 0F87  F7 D8       neg ax
 0F89  B9 0A 00    mov cx,0ah
-0F8C  BB D7 10    mov bx,10d7h
+0F8C  BB 5E 11    mov bx,115eh
 0F8F  89 DE       mov si,bx
 0F91  31 D2       xor dx,dx
 0F93  F7 F1       div ax,cx
@@ -1970,14 +1970,14 @@
 0F99  88 14       mov byte ptr [si],dl
 0F9B  83 F8 00    cmp ax,0h
 0F9E  75 F1       jne 0f91h
-0FA0  A0 97 11    mov al,byte ptr [1197h]
+0FA0  A0 1E 12    mov al,byte ptr [121eh]
 0FA3  3C 00       cmp al,0h
 0FA5  74 04       je 0fabh
 0FA7  C6 05 2D    mov byte ptr [di],2dh
 0FAA  47          inc di
 0FAB  89 D9       mov cx,bx
 0FAD  29 F1       sub cx,si
-0FAF  A0 97 11    mov al,byte ptr [1197h]
+0FAF  A0 1E 12    mov al,byte ptr [121eh]
 0FB2  3C 00       cmp al,0h
 0FB4  74 01       je 0fb7h
 0FB6  41          inc cx
@@ -1997,3 +1997,72 @@
 0FCB  89 EC       mov sp,bp
 0FCD  5D          pop bp
 0FCE  C3          ret
+0FCF  55          push bp
+0FD0  8B EC       mov bp,sp
+0FD2  53          push bx
+0FD3  51          push cx
+0FD4  52          push dx
+0FD5  56          push si
+0FD6  57          push di
+0FD7  8B 7E 04    mov di,word ptr [bp+4h]
+0FDA  8A 05       mov al,byte ptr [di]
+0FDC  88 C1       mov cl,al
+0FDE  30 ED       xor ch,ch
+0FE0  47          inc di
+0FE1  89 FE       mov si,di
+0FE3  31 DB       xor bx,bx
+0FE5  C6 06 1F 12 00 mov byte ptr [121fh],0h
+0FEA  E3 35       jcxz 1021h
+0FEC  8A 05       mov al,byte ptr [di]
+0FEE  3C 2D       cmp al,2dh
+0FF0  74 02       je 0ff4h
+0FF2  EB 09       jmp 0ffdh
+0FF4  C6 06 1F 12 01 mov byte ptr [121fh],1h
+0FF9  47          inc di
+0FFA  49          dec cx
+0FFB  E3 46       jcxz 1043h
+0FFD  8A 05       mov al,byte ptr [di]
+0FFF  3C 30       cmp al,30h
+1001  72 40       jb 1043h
+1003  3C 39       cmp al,39h
+1005  77 3C       jnbe 1043h
+1007  2C 30       sub al,30h
+1009  30 E4       xor ah,ah
+100B  A3 20 12    mov word ptr [1220h],ax
+100E  89 D8       mov ax,bx
+1010  BB 0A 00    mov bx,0ah
+1013  F7 E3       mul bx
+1015  03 06 20 12 add ax,word ptr [1220h]
+1019  89 C3       mov bx,ax
+101B  47          inc di
+101C  49          dec cx
+101D  E3 0B       jcxz 102ah
+101F  EB DC       jmp 0ffdh
+1021  8B 5E 08    mov bx,word ptr [bp+8h]
+1024  31 C0       xor ax,ax
+1026  89 07       mov word ptr [bx],ax
+1028  EB 23       jmp 104dh
+102A  A0 1F 12    mov al,byte ptr [121fh]
+102D  3C 00       cmp al,0h
+102F  74 02       je 1033h
+1031  F7 DB       neg bx
+1033  89 D8       mov ax,bx
+1035  8B 5E 06    mov bx,word ptr [bp+6h]
+1038  89 07       mov word ptr [bx],ax
+103A  8B 5E 08    mov bx,word ptr [bp+8h]
+103D  31 C0       xor ax,ax
+103F  89 07       mov word ptr [bx],ax
+1041  EB 0A       jmp 104dh
+1043  8B C7       mov ax,di
+1045  2B C6       sub ax,si
+1047  40          inc ax
+1048  8B 5E 08    mov bx,word ptr [bp+8h]
+104B  89 07       mov word ptr [bx],ax
+104D  5F          pop di
+104E  5E          pop si
+104F  5A          pop dx
+1050  59          pop cx
+1051  5B          pop bx
+1052  89 EC       mov sp,bp
+1054  5D          pop bp
+1055  C3          ret