        SUBT    > Sys.Output

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +                            O U T P U T                                    +
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Out : addr := validated current FCB. All other regs preserved

WriteCommon

        LDR     addr, [currbase, #hkffcbref]

; .............................................................................
; In : addr -> FCB to validate for output

; Out : temp = FCB flags. All other regs preserved

WriteCheck

        STASH   "count, link"
        BL      FCBtest
        LDMCCDB hasp!, {count, link}
        BCC     eUndefinedFile

        LDRB    temp, [addr, #fcbflags]
 [ debout
 STRIM " flags"
 DREG temp
 ]
        TST     temp, #R_file
        LDMEQDB hasp!, {count, pc}^

        GRAB    "count, link"
        B       eReadOnlyFile

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In : addr -> FCB to validate for output, checks whether BV is currently valid

; Out : All regs + flags preserved

PutCheck
        STASH   "temp, link"
        ADD     argp, addr, #fcbBV      ; argp -> BV
        BL      WriteCheck

        LDRB    temp, [addr, #fcbflags]
        TST     temp, #V_file
        LDMEQDB hasp!, {pc}^

        GRAB    "temp, link"
        BNE     eUndefinedBV

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Put a byte to the selected output stream

; In : addr -> FCB, R0b = char

; Out : l, v := false, false. All regs + flags preserved

PutR0   STASH   "R1, link"

        LDRB    R1, [addr, #fcbflags]   ; Set L, V false (non-empty sequence)
        BIC     R1, R1, #(L_file + V_file)
        STRB    R1, [addr, #fcbflags]

        LDR     R1, [addr, #fcbhandle]  ; May be a fast channel
        CMP     R1, #0
        SWIEQ   WriteC
 [ debout
 SWINE WriteI+"!"
 ]
        SWINE   Bput
        GRABS   "R1, pc"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In : R0 = length of string in stracc

StraccOut

        LV      argp, straccptr

; .............................................................................
; In : argp -> string to be output. R0 = length of string. TotalWidth valid

; Out : String output, padded to left/truncated as neccesary. R0 corrupt

TextOut ROUT

        STASH   "temp, count, link"

        LV      temp, TotalWidth
 [ debout
 STRIM " length"
 DREG R0
 STRIM ", tw"
 DREG temp
 ]
        CMP     R0, temp
        MOVCS   count, temp     ; Truncate string to fit in required TotalWidth
        MOVCC   count, R0
 [ debout
 STRIM ", using"
 DREG count
 ]

; If given length < TotalWidth, then pad at left with spaces

20      CMP     count, temp
        BCS     %FT40
        MOV     R0, #space
        BL      PutR0
        SUBS    temp, temp, #1
        BNE     %BT20

40      LDRB    R0, [argp], #1          ; Output the string
        BL      PutR0
        SUBS    count, count, #1
        BNE     %BT40

        SV      count, TotalWidth       ; Reset field width values (cheap 0)
        SV      count, FracDigits

        GRABS   "temp, count, pc"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; If tw = 0 then tw := R0. All regs preserved

DefaultWidth
        STASH   "t1, link"
        LV      t1, TotalWidth
        CMP     t1, #0
        STREQ   R0, [globalbase, #-TotalWidth]
 [ debout
 BNE %FT99
 STRIM " tw :="
 DREG R0
99
 ]
        GRABS   "t1, pc"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &89 - procedure page (f : file); { Send Form Feed character to file }

iPage   STASH   link
        POP     addr
        LDRB    r0, [addr, #fcbflags]
        TST     r0, #L_file     ; Perform 'writeln (f)' if line not empty
        BLEQ    prtw_CRLF
        MOV     R0, #12
        BL      PutR0
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &8F - Pr_Put_Txt.

iPutText
        STASH   link
        POP     addr
        BL      PutCheck

        LDRB    R0, [argp]
        BL      PutR0
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &90 - Pr_Put_Bts.

iPutBytes ; Size read from FCB

        STASH   link
        POP     addr
        BL      PutCheck

        B       PutThem

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &94 - Pr_Twr_Ln. No args

iTwrLn  STASH   link
        BL      WriteCommon

prtw_CRLF ; Have to output LF if bound to console

        LDR     R0, [addr, #fcbhandle]
        CMP     R0, #0
        MOVEQ   R0, #LF
        BLEQ    PutR0

        MOV     R0, #CR
        BL      PutR0

; Set l true (empty sequence on output stream) for page

        LDRB    r0, [addr, #fcbflags]
        ORR     r0, r0, #L_file
        STRB    r0, [addr, #fcbflags]
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &95 - Pr_Twr_Chr. Char (4b) arg on TOS

iTwrChr STASH   link
 [ debout
 STRIM " TwrChr"
 ]
        BL      WriteCommon
        MOV     R0, #1          ; TotalWidth = 1 for char_type
        BL      DefaultWidth

        DECSP   4
        MOV     R0, #1
        MOV     argp, sp
        BL      TextOut
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &96 - Pr_Twr_Boo. Boolean (4b) arg on TOS

iTwrBoo ROUT

        STASH   link
 [ debout
 STRIM " TwrBoo"
 ]
 [ 1=1
; New (proper) code

        BL      WriteCommon
        MOV     R0, #Default_TotalWidth_Boolean
        BL      DefaultWidth

        MOV     R0, # :LEN: "TRUE"      ; Assume 'True' for now
        ADR     argp, %FT90
        POP     temp
        CMP     temp, #troo
        ADDNE   argp, argp, R0          ; Advance over 'True', point to 'False'
        MOVNE   R0, # :LEN: "FALSE"
        BL      TextOut
        GRAB    pc

90
 = "TRUE"
 = "FALSE"
 |
; Old code (simpler, eh ?)

        POP     r0
        CMP     r0, #troo
        BNE     %FT40
        STRIM   "True"
        RETURN

40
        STRIM   "False"
        RETURN
 ]

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &97 - Pr_Twr_Int. Integer (4b) arg on TOS

iTwrInt STASH   link
 [ debout
 STRIM " TwrInt"
 ]
        BL      WriteCommon
        MOV     R0, #Default_TotalWidth_Integer
        BL      DefaultWidth

        POP     R0
        MOV     temp, #is_print
        BL      R0decimal
        BL      StraccOut
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Convert number to hex in stracc with leading zero supression

R0hex   STASH   "R1, temp, t0, t1, t2, t3, link"

        ADR     t3, HexTab
        B       R0HDcommon


; Convert number to decimal in stracc

; In : R0 = number to convert. temp = destination flag

; Out : R0 = length of numeric representation

R0decimal ROUT ; Entry for debug.line

        STASH   "R1, temp, t0, t1, t2, t3, link"

        ADR     t3, TensTab

; .............................................................................
; In : t3 -> Appropriate radix table

R0HDcommon
        SV      temp, debug_or_print

        LV      R1, straccptr
        MOV     temp, R1

        MOVS    t1, R0
        MOVEQ   R0, #"0"
        BLEQ    Pukka
 [ debout
 SWIEQ WriteC
 ]
        BEQ     %FT99

        RSBMI   t1, t1, #0              ; t1 := - t1
        MOVMI   R0, #"-"
        BLMI    Pukka
 [ debout
 SWIMI WriteC
 ]

51      LDR     t2, [t3], #4
        CMP     t1, t2
        BCC     %BT51
                       ; WHILE
52      MVN     t0, #0 ; t0 := -1
                       ; REPEAT
53      ADD     t0, t0, #1
        SUBS    t1, t1, t2
        BCS     %BT53
        ADD     t1, t1, t2
        CMP     t0, #10
        ADDLT   R0, t0, #"0"
        ADDGE   R0, t0, #"A"-10
        BL      Pukka
 [ debout
 SWI WriteC
 ]
        LDR     t2, [t3], #4
        CMP     t2, #0
        BNE     %BT52

99      SUB     R0, temp, R1
        GRAB    "R1, temp, t0, t1, t2, t3, pc"


TensTab & 1000000000 ; Maxint = 2147483637
        &  100000000
        &   10000000
        &    1000000
        &     100000
        &      10000
        &       1000
        &        100
        &         10
        &          1
        &          0


HexTab  &   &10000000 ; Maxint = &7FFFFFFF
        &    &1000000
        &     &100000
        &      &10000
        &       &1000
        &        &100
        &         &10
        &          &1
        &          &0


; Put a char (R0b) to the console or stracc, depending on who called us
; Must preserve the entire universe

Pukka   STASH   "R1, link"
        LV      R1, debug_or_print
        CMP     R1, #is_debug
        SWIEQ   WriteC
        STRNEB  R0, [temp], #1
        GRABS   "R1, pc"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &98 - Pr_Twr_Rea. Real (8b) arg on TOS

; Currently dumps the number as loaded into F0 as per Bill Stoye's doc !

iTwrRea STASH   link
 [ debout
 STRIM " TwrRea"
 ]
        BL      WriteCommon
        MOV     R0, #Default_TotalWidth_Real
        BL      DefaultWidth

; Now for the yuckky bit !

        STRIM   " Real : "
        LDFD    fa, [sp, #-8]!
        MOV     t0, #&1000
        LDR     t0, [t0, #-12] ; &FF4 - Point to F0

        LDR     r0, [t0, #12] ; Sign bit
        TEQ     r0, #0
        SWIPL   WriteI+"+"
        SWIMI   WriteI+"-"

        LDR     r0, [t0] ; Mantissa hi
        BL      HexLongWord
        LDR     r0, [t0, #4] ; Mantissa lo
        BL      HexLongWord

        SWI     WriteI+space
        SWI     WriteI+ExpChar
        LDR     r0, [t0, #8] ; Exponent
        TEQ     r0, #0
        SWIPL   WriteI+"+"
        SWIMI   WriteI+"-"
        RSBMI   r0, r0, #0
        BL      HexWord
        SWI     WriteI+space
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &99 - Pr_Twr_Hex. Integer (4b) arg on TOS

iTwrHex STASH   link
 [ debout
 STRIM " TwrHex"
 ]
        BL      WriteCommon
        MOV     R0, #Default_TotalWidth_Integer
        BL      DefaultWidth

        POP     r0
 [ 1=1
        MOV     temp, #is_print
        BL      R0hex
        BL      StraccOut
 |
        BL      HexLongWord
 ]
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &9A - Write_Digs

iWriteDigits

        POP     arga
        SV      arga, FracDigits
        CMP     arga, #48
        BHI     eBadFieldDigits
        RETURN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &9B - WriteWidth

iWriteWidth

        POP     arga
        SV      arga, TotalWidth
        CMP     arga, #255
        BHI     eBadFieldWidth
        RETURN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &9C - Pr_Twr_Str. Ptr to string (4b) on TOS

; In : count = length of string

iTwrStr STASH   link
 [ debout
 STRIM " TwrStr"
 ]
        BL      WriteCommon
        MOV     R0, count
        BL      DefaultWidth

        POP     argp
        MOV     R0, count
        BL      TextOut
        GRAB    pc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL code &9D - Pr_Iwr_Typ. Common routine for pr_iwr_bce/ptr/int/rea/set

iIwrType
        STASH   link
        BL      WriteCommon

        LDR     r0, [addr, #fcbcsz]
        SUB     sp, sp, r0
        MOV     argp, sp
        B       PutThem

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL codes &A2,A3 - Pr_Iwr_Uby/Uwd

iIwrUby
iIwrUwd STASH   link
        BL      WriteCommon

        SUB     sp, sp, #4
        MOV     argp, sp
        B       PutThem

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; BL codes &A4 - Pr_Iwr_Blk

iIwrBlk STASH   link
        BL      WriteCommon

        POP     argp

; .............................................................................
; In : STASHed link, addr -> FCB, argp -> BV. Size always read from FCB

PutThem ROUT

        LDR     count, [addr, #fcbcsz]
        LDR     R1, [addr, #fcbhandle]
10      LDR     R0, [argp], #1
        SWI     Bput
        SUBS    count, count, #1
        BNE     %BT10
        GRAB    pc

        LNK     Sys.Heap
