        SUBT    > <wini>arm.FileSwitch.FSErrors - Error handlers + error blocks

        MACRO
$label  MAGICERRBLK $errnum, $string1, $string2, $noalign
        ALIGN
MagicErrorBlock_$label
        DCD     ErrorNumber_$errnum
        DCB     "$string1", 0
        DCB     "$string2", 0
 [ "$noalign" = ""
        ALIGN
 ]
        MEND

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Copy an error number then an error string into our buffer

; In    r0 -> error block (normal or magic). Can't be unaligned
;       fp = 0 -> no local frame, so can't store globalerror
;       wp valid, so we can always copy the error away

        MakeErrorBlock InvalidErrorBlock

CopyErrorInit ROUT

        ADR     r3, errorbuffer         ; Tell us we've had an error
        TEQ     fp, #0                  ; Might not have a local frame
        STRNE   r3, globalerror
 [ debugerror
 DREG fp, "fp for error was "
 ]

        TST     r0, #&FC000003          ; Crap error block ?
        ADRNE   r0, ErrorBlock_InvalidErrorBlock

        LDR     r2, [r0], #4            ; Copy error number
        STR     r2, [r3], #4

        MOV     r4, #256-4              ; How many more chars we
                                        ; can put into this error block

; .............................................................................
; Append an error string to the error buffer, not copying the terminator

; In    r0 -> string
;       r3 -> buffer to copy into

; Out   r0 -> past terminator
;       r2    corrupt
;       r3 -> next place to put a char in buffer (current zero)
;       r4 =  number of bytes left in error block (-ve -> r3 invalid)
;       VS always

; NOALIGN - drop thru !

CopyErrorCommon ROUT

90      SUBS    r4, r4, #1              ; Might have already gone under
        BMI     %FT99
        LDRB    r2, [r0], #1
        CMP     r2, #delete
        CMPNE   r2, #space-1
        MOVLS   r2, #0                  ; Keep error buffer terminated
        STRB    r2, [r3], #1
        BHI     %BT90

        SUB     r3, r3, #1              ; Point back at terminator
        ORRS    pc, lr, #V_bit

99      LDR     r0, ThreeDots           ; Truncate with grace
        STR     r0, errorbuffer+256-4   ; at known place
        ORRS    pc, lr, #V_bit

ThreeDots DCB   "...",0                 ; Picked up as a word

; .............................................................................

CopyErrorCommonSpan ; NOROUT

91      SUBS    r4, r4, #1              ; Might have already gone under
        BMI     %BT99
        SUBS    r5, r5, #1
        MOVMI   r2, #0
        LDRPLB  r2, [r0], #1
        CMP     r2, #delete
        CMPNE   r2, #space-1
        MOVLS   r2, #0                  ; Keep error buffer terminated
        STRB    r2, [r3], #1
        BHI     %BT91

        SUB     r3, r3, #1              ; Point back at terminator
        ORRS    pc, lr, #V_bit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; CopyError
; =========
;
; Copy the given error block into a safe place and note the error

; In    r0 -> error block

; Out   VSet always

CopyError ENTRY "r0, r2-r4"

        BL      CopyErrorInit           ; Copy error number + string. VSet
 [ debugerror
 ADRL r1, errorbuffer+4
 DSTRING r1, "***Error: "
 ]
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; MagicCopyError
; ==============
;
; Copy the given error block and msg into a safe place and note the error

; Used for errors such as "File 'fred' not found"

; A special 'magic' error block is used; format :

; r0 -> +------------+
;       | ErrNo Word |
;       +------------+
;       | Error Text |
;       +------------+
;       |   0   Byte |
;       +------------+
;       | Error Text |
;       +------------+
;       |   0   Byte |
;       +------------+

; In    r0 -> magic error block
;       r1 -> string to copy into the middle of the block, CtrlChar

; Out   VSet always

MagicCopyError ENTRY "r0, r2-r4, r6"

        BL      CopyErrorInit           ; Copy first part of error string

        MOV     r6, r0                  ; Save second part of string^
        MOV     r0, r1                  ; Copy dynamic string part
        BL      CopyErrorCommon

        MOV     r0, r6                  ; Copy second part of string
        BL      CopyErrorCommon
 [ debugerror
 ADRL r1, errorbuffer+4
 DSTRING r1, "***Error: "
 ]
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r0 -> magic error block
;       r1 -> string to copy into the middle of the block
;       r3 = ?string

; Out   VSet always

MagicCopyErrorSpan ENTRY "r0-r6"

        BL      CopyErrorInit           ; Copy first part of error string

        MOV     r6, r0                  ; Save second part of string^
        MOV     r0, r1                  ; Copy dynamic string part
        LDR     r5, [sp, #4*3]          ; r3in
        BL      CopyErrorCommonSpan

        MOV     r0, r6                  ; Copy second part of string
        BL      CopyErrorCommon
 [ debugerror
 ADRL r1, errorbuffer+4
 DSTRING r1, "***Error: "
 ]
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; CopyErrorAppendingString
; ========================

; In    r0 -> error
;       r1 -> string to tack on afterwards

; Out   VSet always

CopyErrorAppendingString ENTRY "r0, r2-r4"

10      BL      CopyErrorInit

 [ debugerror
 ADRL r0, errorbuffer+4
 DSTRING r0, "***Error: ",cc
 DSTRING r1, ", now appending "
 ]
        MOV     r0, r1
        BL      CopyErrorCommon

 [ debugerror
 ADRL r1, errorbuffer+4
 DSTRING r1, "***Error now: "
 ]
        EXIT

; .............................................................................
;
; AppendMessageToError
; ====================

; In    r1 -> string to tack onto existing error block (no space)

; Out   VSet always

AppendMessageToError ALTENTRY

        ADR     r0, errorbuffer
        B       %BT10

 [ appendhandle
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; AppendHandleToError
; ===================
;
; Append the message ' on channel nnn' to the error in the buffer

; In    r1b = FileSwitch handle

; Out   VSet always

AppendHandleToError ENTRY "r0-r4"

        TST     r1, #&FF                ; 'on handle 0' is silly !
        BEQ     %FA85

        ADR     r0, errorbuffer
        BL      CopyErrorInit

        ADR     r0, %FT90               ; ' on file handle '
        BL      CopyErrorCommon

        SUB     sp, sp, #16
        AND     r0, r1, #&FF
        MOV     r1, sp
        MOV     r2, #10+1               ; All digits significant
        SWI     XOS_BinaryToDecimal     ; Stick channel number on end
        MOV     r0, #0                  ; Only error is 'Buffer overflow'
        STRB    r0, [r1, r2]            ; Terminate error block

        MOV     r0, sp
        BL      CopyErrorCommon
        ADD     sp, sp, #16

85      PullEnv
        ORRS    pc, lr, #V_bit

90
        DCB     " on file handle ", 0
        ALIGN
 ]

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;                          Magic  errors
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r1 -> filename to use

SetMagicFileNotFound ENTRY "r0"

        ADR     r0, MagicErrorBlock_FileNotFound

50      BL      MagicCopyError
        EXIT


SetMagicIsADirectory ALTENTRY

        ADR     r0, MagicErrorBlock_IsADirectory
        B       %BT50


SetMagicBadFileName ALTENTRY

        ADR     r0, MagicErrorBlock_BadFileName
        B       %BT50

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SetMagicWildCardIfSo ENTRY "r0, r1"

        LDRB    r14, wildleafname
        CMP     r14, #0
        ADRNE   r0, MagicErrorBlock_WildCards
        LDRNE   r1, PassedFilename
        BLNE    MagicCopyError
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Magic error blocks

FileNotFound  MAGICERRBLK FileNotFound, "File '", "' not found"
DirNotFound   MAGICERRBLK FileNotFound, "Directory '", "' not found"
IsAFile       MAGICERRBLK IsAFile,      "'", "' is a file" ; For OSFile_MakeErr
IsADirectory  MAGICERRBLK IsADirectory, "'", "' is a directory"
WildCards     MAGICERRBLK WildCards,    "'", "' contains wild cards"
ObjectLocked  MAGICERRBLK ObjectLocked, "'", "' is locked"
BadFileName   MAGICERRBLK BadFileName,  "Bad file name '", "'"
CantOpenFile  MAGICERRBLK FileNotFound, "Can't open '", "'"

FSDoesntExist MAGICERRBLK UnknownFilingSystem,"Filing system '", ":' not present"
; For REAL filing systems

UnknownFilingSystem MAGICERRBLK UnknownFilingSystem, "Filing system or path '", ":' not present"
; General wimp out


UnknownActionType MAGICERRBLK UnknownActionType, "No ", " action specified for this file type"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Error blocks with non-standard text

ErrorBlock_CopyFileOntoDir
        DCD     ErrorNumber_TypesDontMatch
        DCB     "Can't copy file as destination is a directory", 0
        ALIGN

ErrorBlock_CopyDirOntoFile
        DCD     ErrorNumber_TypesDontMatch
        DCB     "Can't copy directory as destination is a file", 0
        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;                         Standard  errors
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SetErrorAccessViolation ENTRY "r0"

        ADR     r0, ErrorBlock_AccessViolation

50      BL      CopyError
        EXIT


SetErrorNoSelectedFilingSystem ALTENTRY

        ADR     r0, ErrorBlock_NoSelectedFilingSystem
        B       %BT50


SetErrorChannel ALTENTRY

        ADR     r0, ErrorBlock_Channel
        B       %BT50


SetErrorDataLost ALTENTRY

        ADR     r0, ErrorBlock_FileSwitchDataLost
        B       %BT50


SetErrorStreamIsDirectory ALTENTRY

        ADR     r0, ErrorBlock_IsADirectory
        B       %BT50


SetErrorNotOpenForReading ALTENTRY

        ADR     r0, ErrorBlock_NotOpenForReading
        B       %BT50


SetErrorNotOpenForUpdate ALTENTRY

        ADR     r0, ErrorBlock_NotOpenForUpdate
        B       %BT50

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Lowlevel_UnsupportedFSEntry

        ADR     r0, ErrorBlock_UnsupportedFSEntry
        ORRS    pc, lr, #V_bit                  ; VSet, r0 as if FS


Lowlevel_UnalignedFSEntry

        ADR     r0, ErrorBlock_UnalignedFSEntry
        ORRS    pc, lr, #V_bit                  ; VSet, r0 as if FS


Lowlevel_NotEnoughStackForFSEntry

        ADR     r0, ErrorBlock_NotEnoughStackForFSEntry
        ORRS    pc, lr, #V_bit                  ; VSet, r0 as if FS


Lowlevel_NoFilingSystemsActive

        ADR     r0, ErrorBlock_NoSelectedFilingSystem
        ORRS    pc, lr, #V_bit                  ; VSet, r0 as if FS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Standard error blocks

 MakeErrorBlock AccessViolation
 MakeErrorBlock NoSelectedFilingSystem
 MakeErrorBlock Channel
 MakeErrorBlock FileSwitchDataLost
 MakeErrorBlock IsADirectory
 MakeErrorBlock NotOpenForReading
 MakeErrorBlock NotOpenForUpdate
 MakeErrorBlock UnsupportedFSEntry
 MakeErrorBlock UnalignedFSEntry
 MakeErrorBlock NotEnoughStackForFSEntry

 [ :LNOT: AssemblingArthur
 MakeErrorBlock BuffOverflow
 MakeErrorBlock OutsideFile
 MakeErrorBlock BadString
 MakeErrorBlock BadCommand
 ]

 MakeErrorBlock BadOSFileReason
 MakeErrorBlock BadOSArgsReason
 MakeErrorBlock BadOSGBPBReason
 MakeErrorBlock BadModeForOSFind
 MakeErrorBlock BadFSControlReason
 MakeErrorBlock BadBufferSizeForStream
 MakeErrorBlock BadFilingSystemName
 MakeErrorBlock UnknownFilingSystem
 MakeErrorBlock CantRemoveFSByNumber
 MakeErrorBlock AlreadyExists
 MakeErrorBlock TooManyOpenFiles
 MakeErrorBlock EndOfFile
 MakeErrorBlock FSNotSpecial
 MakeErrorBlock NoRoomForTransient
 MakeErrorBlock ExecAddrTooLow
 MakeErrorBlock ExecAddrNotInCode
 MakeErrorBlock CantStartApplication
 MakeErrorBlock CoreNotReadable
 MakeErrorBlock CoreNotWriteable
 MakeErrorBlock BadCopy
 MakeErrorBlock BadRename
 MakeErrorBlock NothingToCopy
 MakeErrorBlock NothingToDelete
 MakeErrorBlock FSFileTooBig
 MakeErrorBlock InconsistentHandleSet
 MakeErrorBlock BadFileType

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        LNK     $fileprefix.FSCommon
