        SUBT    > Sources.FSErrors - Error handlers + error blocks

        MACRO
$label  MAGICERRBLK $errnum, $AltTag
        ALIGN
MagicErrorBlock_$label
ErrorBlock_$label
        DCD     ErrorNumber_$errnum
 [ "$AltTag"=""
        DCB     "$label", 0
 |
        DCB     "$AltTag", 0
 ]
        ALIGN
        MEND

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Store an error pointer in globalerror as necessary

; In    r0 -> error block
;       fp (may be 0)

CopyErrorStore ROUT
        TEQ     fp, #0
        STRNE   r0, globalerror
        MOVS    pc, lr

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Check external error pointer is kosha, replacing with translated
; InvalidErrorBlock if bad

; In    r0 -> error block

CopyErrorValidateExternal ROUT
        TST     r0, #&FC000003
        MOVEQS  pc, lr
        ADRL    r0, ErrorBlock_InvalidErrorBlock
        B       copy_error              ; Tail folding

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; CopyError
; =========
;
; Translate and store the given internally generated error in globalerror

; In    r0 -> error block

; Out   VSet always

CopyError ENTRY

        BL      copy_error
        BL      CopyErrorStore

 [ debugerror
 ADD    r0, r0, #4
 DSTRING r0, "***Error: "
 SUB    r0, r0, #4
 ]
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; CopyErrorExternal
; =================
;
; Copy the externally generated error to globalerror

; In    r0 -> error block

; Out   VSet always

CopyErrorExternal ENTRY

        ; Check for the lowlevel errors and copy with translation
        ADR     lr, ErrorBlock_UnsupportedFSEntry
        TEQ     r0, lr
        ADRNE   lr, ErrorBlock_UnalignedFSEntry
        TEQNE   r0, lr
        ADRNE   lr, ErrorBlock_NotEnoughStackForFSEntry
        TEQNE   r0, lr
        ADRNE   lr, ErrorBlock_NoSelectedFilingSystem
        TEQNE   r0, lr
        PullEnv EQ
        BEQ     CopyError

        BL      CopyErrorValidateExternal
        BL      CopyErrorStore
        SETV
        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   r0 -> the real error block
;       VSet always

MagicCopyError ENTRY    "r4"

        MOV     r4, r1
        BL      copy_error1
        BL      CopyErrorStore

 [ debugerror
 ADD    r0, r0, #4
 DSTRING r0, "***Error: "
 SUB    r0, r0, #4
 ]
        EXIT

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

; Out   VSet always

MagicCopyErrorSpan ENTRY "r0-r4"

        ADD     r4, r3, #1+3
        BIC     r4, r4, #3
        SUB     sp, sp, r4

        MOV     lr, #0
        B       %FT20
10
        LDRB    lr, [r1, r3]
20
        STRB    lr, [sp, r3]
        SUBS    r3, r3, #1
        BPL     %BT10

        MOV     r1, sp
        BL      MagicCopyError

        ADD     sp, sp, r4

 [ debugerror
 ADD    r0, r0, #4
 DSTRING r0, "***Error: "
 SUB    r0, r0, #4
 ]
        EXIT

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

; In    r0 -> error
;       r1 -> tag of string to substitute error into

; Out   VSet always

CopyErrorAppendingString ENTRY "r0-r3"

10
        ; Copy substitution tag onto stack to prepend the error number from the real error
        BL      strlen
        ADD     r3, r3, #1+3+4
        BIC     r3, r3, #3
        SUB     sp, sp, r3
        MOV     r2, r1
        ADD     r1, sp, #4
        BL      strcpy
        LDR     r1, [r0]
        STR     r1, [sp]

        ; Generate an error with real error's text substituted in
        ADD     r1, r0, #4
        MOV     r0, sp
        BL      MagicCopyError
        ADD     sp, sp, r3
        EXIT

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

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

; Out   VSet always

AppendMessageToError ALTENTRY

        LDR     r0, globalerror
        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-r5", (?fsw_on_file_handle + 4 + 12 + 3) :AND: :NOT: 3

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

        AND     r0, r1, #&FF
        MOV     r1, sp
        MOV     r2, #12
        SWI     XOS_ConvertCardinal4    ; Stick channel number on end
        BVS     %FT80

        ADD     r1, sp, #12 + 4
        ADR     r2, fsw_on_file_handle
        BL      strcpy
        LDR     r4, globalerror
        LDR     r2, [r4], #4            ; Text of original error
        STR     r2, [r1, #-4]!          ; error number of original error
        MOV     r0, r1
        MOV     r5, sp                  ; handle converted to digits
        BL      copy_error2

80
        STR     r0, globalerror

85      PullEnv
        ORRS    pc, lr, #V_bit

fsw_on_file_handle DCB "OnFileHandle", 0
        ALIGN
 ]

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

SetMagicFileNotFound ENTRY "r0"
        ADR     r0, MagicErrorBlock_FileNotFound

50      BL      MagicCopyError
        EXIT

SetMagicIsAFile ALTENTRY
        ADR     r0, MagicErrorBlock_IsAFile
        B       %BT50

SetMagicDirNotFound ALTENTRY
        ADR     r0, MagicErrorBlock_DirNotFound
        B       %BT50

SetMagicIsADirectory ALTENTRY
        ADR     r0, MagicErrorBlock_IsADirectory
        B       %BT50

SetMagicBadFileName ALTENTRY
        ADR     r0, MagicErrorBlock_BadFileName
        B       %BT50

SetMagicFSDoesntExist ALTENTRY
        ADR     r0, MagicErrorBlock_FSDoesntExist ; Error if fs not found
        B       %BT50

SetMagicPartNotEmpty ALTENTRY
        ADR     r0, MagicErrorBlock_PartNotEmpty
        B       %BT50

SetMagicPlainNotFound ALTENTRY
        ADR     r0, MagicErrorBlock_PlainNotFound
        B       %BT50

SetMagicCantSetLibOrURD ALTENTRY
        ADR     r0, MagicErrorBlock_CantSetLibOrURD

60
        ADD     r1, fscb, #fscb_name
        B       %BT50

SetMagicFSNotSpecial ALTENTRY
        ADR     r0, MagicErrorBlock_FSNotSpecial
        B       %BT60

SetMagicFSNeedsFilename ALTENTRY
        ADR     r0, MagicErrorBlock_BadNulFileName
        B       %BT60

SetErrorStreamIsDirectory ENTRY "r0,r1,r3,r6,fscb"     ; scb valid

        LDR     r1, scb_path
        LDR     r6, scb_special
        LDR     fscb, scb_fscb
        MOV     r3, sp
        BL      int_ConstructFullPathOnStack
        MOV     r1, sp
        BL      SetMagicIsADirectory
        MOV     sp, r3
        EXIT

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

FileNotFound            MAGICERRBLK FileNotFound, NoFile
DirNotFound             MAGICERRBLK FileNotFound, NoDir
PlainNotFound           MAGICERRBLK FileNotFound, NoAny
IsAFile                 MAGICERRBLK IsAFile, IsAFil
IsADirectory            MAGICERRBLK IsADirectory, IsADir
WildCards               MAGICERRBLK WildCards, Wild
BadFileName             MAGICERRBLK BadFileName
BadNulFileName          MAGICERRBLK BadFileName, NulName
CantOpenFile            MAGICERRBLK FileNotFound, CantOpen
FSDoesntExist           MAGICERRBLK UnknownFilingSystem, UkFS
UnknownFilingSystemPath MAGICERRBLK UnknownFilingSystem, UkFSP
UkFS                    MAGICERRBLK UnknownFilingSystem, UFS
FSNotSpecial            MAGICERRBLK FSNotSpecial
RecursivePath           MAGICERRBLK RecursivePath, PathPath
CreateFileOntoDir       MAGICERRBLK TypesDontMatch, FOnDir
CreateDirOntoFile       MAGICERRBLK TypesDontMatch, DirOnF
RenameDestinationFound  MAGICERRBLK BadRename, DestThere
CantSetLibOrURD         MAGICERRBLK UnsupportedFSEntry, CantLib
BadAccessAttributes     MAGICERRBLK BadParameters,BadAtts
BadDiscName             MAGICERRBLK BadParameters,BadDscNm
PartNotEmpty            MAGICERRBLK DirectoryNotEmpty,PNotEmpty

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

SetErrorNoSelectedFilingSystem ENTRY "r0"

        ADR     r0, ErrorBlock_NoSelectedFilingSystem

50      BL      CopyError
        EXIT


SetErrorChannel ALTENTRY

        ADR     r0, ErrorBlock_Channel
        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

 MakeInternatErrorBlock NoSelectedFilingSystem,,NoSelFS
 MakeInternatErrorBlock Channel
 MakeInternatErrorBlock NotOpenForReading,,NoRead
 MakeInternatErrorBlock NotOpenForUpdate,,NoUpdate
 MakeInternatErrorBlock UnsupportedFSEntry,,UsFSE
 MakeInternatErrorBlock UnalignedFSEntry,,UaFSE
 MakeInternatErrorBlock NotEnoughStackForFSEntry,,NoStack

 [ :LNOT: AssemblingArthur
 MakeInternatErrorBlock BuffOverflow,,BufOFlo
 MakeInternatErrorBlock OutsideFile,,OffFile
 MakeInternatErrorBlock BadCommand,,BadComm
 ]

 MakeInternatErrorBlock BadOSFileReason,,BadOSFile
 MakeInternatErrorBlock BadOSArgsReason,,BadOSArgs
 MakeInternatErrorBlock BadOSGBPBReason,,BadOSGBPB
 MakeInternatErrorBlock BadModeForOSFind,,BadFindMode
 MakeInternatErrorBlock BadFSControlReason,,BadControl
 MakeInternatErrorBlock BadBufferSizeForStream,,BadBuf
 MakeInternatErrorBlock BadFilingSystemName,,BadFSName
 MakeInternatErrorBlock UnknownFilingSystem,,UkMultiFS
 MakeInternatErrorBlock CantRemoveFSByNumber,,CantNumberFS
 MakeInternatErrorBlock TooManyOpenFiles,,OpnFils
 MakeInternatErrorBlock EndOfFile,,EOF
 MakeInternatErrorBlock NoRoomForTransient,,TransNoMem
 MakeInternatErrorBlock ExecAddrTooLow,,ExTooLow
 MakeInternatErrorBlock ExecAddrNotInCode,,ExNotInCode
 MakeInternatErrorBlock CantStartApplication,,HeSayNo
 MakeInternatErrorBlock CoreNotReadable,,BadRead
 MakeInternatErrorBlock CoreNotWriteable,,BadWrt
 MakeInternatErrorBlock BadCopy
 MakeInternatErrorBlock BadRename,,BadRen
 MakeInternatErrorBlock NothingToCopy,,CopyNowt
 MakeInternatErrorBlock NothingToDelete,,WipeNowt
 MakeInternatErrorBlock FSFileTooBig,,TooBig
 MakeInternatErrorBlock BadFileType,,BadType
 MakeInternatErrorBlock FileSwitchCantBeKilledWhilstThreaded,,Busy
 MakeInternatErrorBlock BadCommandOption,,BadComOpt
 MakeInternatErrorBlock InvalidErrorBlock,,BadErr
 MakeInternatErrorBlock WasntDollarAfterDisc,,BadName1
 MakeInternatErrorBlock NotEnoughMemoryForWildcardResolution,,NoMem1
 MakeInternatErrorBlock NotEnoughStackForWildcardResolution,,NoStack1
 MakeInternatErrorBlock MultipartPathUsed,,PPPath
 MakeInternatErrorBlock TooManyErrorLookups
 MakeInternatErrorBlock MessageFileBusy
NotGoodDisc     MAGICERRBLK IsAFile,BadDisc
CopyFileOntoDir MAGICERRBLK TypesDontMatch,CpFOnDir
CopyDirOntoFile MAGICERRBLK TypesDontMatch,CpDirOnF
BadSetDirDir    MAGICERRBLK BadParameters,BadSetDr
 MakeInternatErrorBlock PartitionBusy,,PBusy
UnknownLoadAction MAGICERRBLK UnknownActionType, UkLoad
UnknownRunAction MAGICERRBLK UnknownActionType, UkRun

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

        END
