        SUBT    > <wini>arm.FileSwitch.FSControl

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +                                                                           +
; +                     F S C O N T R O L    S W I                            +
; +                                                                           +
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; FSControlEntry. Vectored SWI level entry
; ==============
;
; Perform various actions in FileSwitch analogous to JMI (FSCV) on BBC micro

; Filename parameters are all GSTRANSed in the standard Filing System way

; In    r0 = action requested, various parms (NB. Not r0b)

; Out   VC: Action performed, r0 preserved (frequently)
;       VS: Something terrible has happened, r0 -> error block

FSControlEntry ROUT

 [ debugcontrol
 DREG r0,"Doing FSControl ",cc
 DREG r1," arg1 ",cc
 DREG sp,", sp = "
 ]
        CMP     r0, #FSControl_Max
        JTAB    r0, LO, FSControl       ; Good rc if LO
        B       FSControl_BadReason

                                  ; Check reason codes against &.Hdr.File

        JTE     DirEntry,         FSControl_Dir
        JTE     LibEntry,         FSControl_Lib
        JTE     StartApplicEntry, FSControl_StartApplication
        JTE     RunTypeEntry,     FSControl_RunType
        JTE     RunEntry,         FSControl_Run
        JTE     CatEntry,         FSControl_Cat
        JTE     CatEntry,         FSControl_Ex   ; Same as Cat
        JTE     LCatEntry,        FSControl_LCat
        JTE     LCatEntry,        FSControl_LEx  ; Same as LCat
        JTE     CatEntry,         FSControl_Info ; Same as Cat
        JTE     OptEntry,         FSControl_Opt
        JTE     SetFromNameEntry, FSControl_StarMinus
        JTE     AddFSEntry,       FSControl_AddFS
        JTE     LookupFSEntry,    FSControl_LookupFS
        JTE     SelectFSEntry,    FSControl_SelectFS
        JTE     BootupFSEntry,    FSControl_BootupFS
        JTE     RemoveFSEntry,    FSControl_RemoveFS
        JTE     AddSecondaryFSEntry, FSControl_AddSecondaryFS
        JTE     ReadFileTypeEntry, FSControl_ReadFileType
        JTE     RestoreCurrEntry, FSControl_RestoreCurrent
        JTE     ReadTempModEntry, FSControl_ReadModuleBase
        JTE     ReadFSHandle,     FSControl_ReadFSHandle
        JTE     ShutFilesEntry,   FSControl_Shut
        JTE     ShutDownEntry,    FSControl_ShutDown
        JTE     AccessEntry,      FSControl_Access
        JTE     RenameEntry,      FSControl_Rename
 [ hascopy
        JTE     CopyEntry,               FSControl_Copy
 |
        JTE     FSControl_BadReason
 ]
 [ haswipe
        JTE     WipeEntry,               FSControl_Wipe
 |
        JTE     FSControl_BadReason
 ]
 [ hascount
        JTE     CountEntry,              FSControl_Count
 |
        JTE     FSControl_BadReason
 ]
        JTE     CreateHandleEntry,       FSControl_CreateHandle
        JTE     ReadSecModEntry,         FSControl_ReadSecondaryModuleBase
        JTE     FileTypeFromStringEntry, FSControl_FileTypeFromString
        JTE     FileInfoEntry,           FSControl_FileInfo
        JTE     ReadFSNameEntry,         FSControl_ReadFSName
        JTE     SetContextsEntry,        FSControl_SetContexts

FSControl_Max * (.-$JumpTableName) :SHR: 2


FSControl_BadReason

        addr    r0, ErrorBlock_BadFSControlReason
        Pull    lr
        ORRS    pc, lr, #V_bit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; RunEntry. Top level FSControl entry
; ========
;
; Run a file from the temporary Filing System

; In    r1 -> filename (space, CtrlChar term) and command line (CtrlChar term)

; Out   if it doesn't return:
;            current FS restored, program running or aborted
;       if it does return:
;            VC: file has been run ok (eg. *EXECed OR PIC transient)
;            VS: error in running or file returned badly

RunTypeEntry ; for the mo.

RunEntry NewSwiEntry "r0-r3"

 [ debugrun
 DREG sp,"run sp in = "
 ]
        BL      FS_SkipSpaces           ; Saves code to have this here
                                        ; Allows */ fred etc.
        BCC     %FA99                   ; [*/ with no arg]

        ADR     r0, CommandLine
        BL      SGetLinkedString        ; May have spaces in it, so watch out !
        BVS     %FA98                   ; Nothing to deallocate

 [ debugrun
 DSTRING r1,"Trying to run "
 ]
        BL      SkipOverNameAndSpaces
        STR     r1, commandtailptr

        BL      TryRunningFile
        BVS     %FA97                   ; Total cockup ?
        BEQ     %FA97                   ; Run a file ok ?

        MOV     r2, #object_nothing
        MOV     r0, #OSFile_MakeError
        LDR     r1, [fp, #4*1]
        SWI     XOS_File
        BLVS    CopyError


97 ; CommandLine to be deallocated

        BL      SFreeCommandLine

98      SwiExit


99      addr    r14, ErrorBlock_BadCommand
        B       %BA9999 ; SwiExit with r14 -> error

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; TryRunningFile
; ==============
;
; Split off from main RUN entry for ease of error handling / exiting

; In    r1 -> filename (space, CtrlChar term) and command line (CtrlChar term)

; Out   if it doesn't return:
;            current FS restored, program running or aborted
;       if it does return:
;            VS: error has been set
;            VC: EQ: file has been run ok (eg. *EXECed OR PIC transient)
;                NE: file not found

TryRunningFile ENTRY "r0-r5" ; Try not to keep too much stacked for RUN

        LDR     r1, CommandLine         ; Restore filename^
        BL      TransNameIntoBuffer
        BVS     RunExit_CL

; Look in Run$Path; if undefined then use default

        addr    r0, RunPathVariableNameCR
        ADD     r2, r0, #(RunPathVariableDefault - RunPathVariableNameCR)
        BL      ExPathWithDefaultNoDir  ; Loop, not matching dirs ! (PTH)
        BVS     RunExit_CL_PF

; Now have FullFilename and SpecialField allocated too if exists

        CMP     r0, #object_file        ; Normal File ?
        BNE     RunExit_CL_PF           ; NE -> failed to run file
                                        ; NB. Exit NE !!!
 [ debugrun
 DSTRING r1, "File to run is ",cc
 LDR r14, FullFilename
 DSTRING r14, ", fullfilename is "
 ]

; --------------------- Suss how to run this file now -------------------------

        ADR     r14, fileblock_base     ; Read file parms what we got
        LDMIA   r14, {r2-r5}            ; Length is useful for later checks

        TST     r5, #read_attribute     ; Can only run files with R attribute
        BEQ     %FT91                   ; So there !

        CMP     r2, #0
        CMPNE   r2, #-1
        CMPEQ   r3, #-1                 ; Is it a command file (execaddr = -1)?
        LDREQ   r2, =&FFFFFE00+&FF      ; Pretend to be dated if so, and get #

        CMN     r2, #&00100000          ; Is the file date stamped ? CSet if so
        BCC     Run_UndatedFile

        MOV     r0, r2, ASR #8          ; File type now in the lowest 12 bits
        CMP     r0, #&FFFFFFF8          ; Type FF8 ?
        BEQ     Run_Absolute8000File
        CMP     r0, #&FFFFFFFC          ; Type FFC ?
        BEQ     Run_TransientFile

; .............................................................................
; In    r2 = load address to decode

Run_UnrecognisedFile

        LDR     r3, commandtailptr      ; Can supply a command tail to append
        ADR     r4, RunActionPrefix
        ADR     r5, RunActionErrorString
        BL      ReadActionVariable      ; Leaves r0 -> action vbl (pushed)
        BVS     RunExit_CL_PF_FF_SF

        SWI     XOS_CLI
        BLVS    CopyError

        ADR     r0, ActionVariable
        BL      SFreeLinkedArea         ; Accumulate V

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

Run_Common_NoCopy

        CMPVC   r0, r0                  ; EQ -> file run ok

; .............................................................................
; In    CommandLine, PassedFilename, FullFilename and SpecialField
;       to be deallocated

RunExit_CL_PF_FF_SF

        BL      SFreeFullFilename       ; Deallocate please

        BL      SFreeSpecialField       ; Deallocate please

; .............................................................................
; In    CommandLine and PassedFilename to be deallocated

RunExit_CL_PF

        BL      SFreePassedFilename     ; Deallocate please

; .............................................................................
; CommandLine now deallocated outside for efficiency

RunExit_CL

        EXIT


RunActionErrorString    DCB     "run", 0
RunActionPrefix         DCB     "Alias$@RunType_" ; Shared zero with ...
66
        DCB     0

        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Type FF8

Run_Absolute8000File

        MOV     r2, #&8000              ; Load at &8000
        STR     r2, fileblock_load
        MOV     r3, r2                  ; And execute it there

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

Run_UndatedFile

 [ debugrun
 DREG r3,"Running file at &"
 ]
        CMP     r2, #&8000              ; Can't load anything below 32K now
        BLO     %FA92
        BIC     r3, r3, #ARM_CC_Mask    ; Form sensible ARM address for exec
        ADD     r5, r2, r4              ; Does exec address live in the code ?
        SUB     r14, r5, #1             ; Stops zero length files running too
        CMP     r3, r2                  ; ie. start <= exec < (start+length)
        RSBGES  r14, r3, r14
        BLT     %FA93                   ; LT -> not in range (ie. not in code)

        BL      ValidateR2R5_WriteToCore
        BVS     RunExit_CL_PF_FF_SF

        addr    r0, anull               ; Null command tail fudge
        MOV     r2, r3                  ; CAO address := entry point of file
        LDR     r3, CommandLine
        BL      StartUpTheApplication   ; Which restores current FS
        BVS     RunExit_CL_PF_FF_SF

 [ AssemblingArthur
        LDR     r0, =EnvString          ; r0 -> copy of run string
 |
        LDR     r0, EnvStringAddr       ; r0 -> copy of run string
 ]
        MOV     r1, r0                  ; NB. Our strings are all dead now
        BL      SkipOverNameAndSpaces   ; r1 -> copy of command tail

        LDR     sp, =SVCSTK             ; Flatten superstack, we don't return

        TEQP    pc, #0                  ; USR mode, all ints on
        MOV     r12, #&80000000         ; Cause address extinction if used
        MOV     r13, #&80000000         ; (keep 1.20 compat capable)
        ADR     lr, ReturnFromAbsoluteCode
        MOV     pc, r2                  ; Go to it !

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Type FFC

; Offsets in transient PIC RMA block

                        ^       0
transient_savearea      #       4*6     ; SaveArea for r6-r9, r13_usr, r14_usr
transient_code          #       0

transient_ws * &0400

Run_TransientFile

; Claim a RMA block for the transient

        ADD     r5, r4, #transient_code ; Need length of file + my block size
        ADD     r5, r5, #3              ; Word align for wp,sp_usr below
        BIC     r5, r5, #3              ; Remember r5: used for ws below !
        ADD     r3, r5, #transient_ws   ; Plus some workspace for it

        BL      SGetLinkedTransientArea
        BVS     RunExit_CL_PF_FF_SF
        BEQ     %FA94                   ; No room ?

; Need to preserve any registers that haven't been saved for EXIT so that
; transients may call other transients, preserving all registers + state
; Use a save area on the front of the code block for these.
; r10-r12 assumed to be preserved by the main SWI handler.

 assert transient_savearea = 0
        STMIA   r2, {r6-r9, r13-r14}^   ; Must preserve r13_usr and r14_usr
                                        ; r0-r5 already stacked
        ADD     r2, r2, #transient_code ; Load code just after info block
        STR     r2, fileblock_load

        MOV     r0, #fsfile_Load        ; Don't use _Given (no fscb, r6 here)
        BL      CallFSFile
        BVS     %FT88

        LDR     r0, CommandLine
        addr    r1, %BA66               ; Null command tail fudge (shared)
        BL      CopyCommandLineAndReadTime

; Don't flatten superstack for PIC objects as they return to me !

        Push    "fp, wp"                ; Need to remember these for return

        LDR     r0, CommandLine
        LDR     r1, commandtailptr

        TEQP    pc, #0                  ; USR mode, all ints on
        ADD     r5, r2, r5              ; r12 -> transient workspace. Not bank
        SUB     wp, r5, #transient_code ; Must correct as r5 = info + code
                                        ; and r2 = code^
        ADD     sp, wp, #transient_ws   ; r13 -> small stack in the above ws
        ADR     lr, ReturnFromPIC       ; No point in having mode bits set
        MOV     pc, r2                  ; Go to it !


; Failed to load transient after allocating space

88      LDR     r0, globalerror         ; fp is valid, of course ...
        MOV     r1, #V_bit
        B       DeleteTransient

; *****************************************************************************
; Foulup time during runs

91      BL      SetErrorAccessViolation
        B       RunExit_CL_PF_FF_SF

92      addr    r0, ErrorBlock_ExecAddrTooLow
        B       %FT98

93      addr    r0, ErrorBlock_ExecAddrNotInCode
        B       %FT98

94      addr    r0, ErrorBlock_NoRoomForTransient

98      BL      CopyError               ; VSet too
        B       RunExit_CL_PF_FF_SF

        LTORG

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This is where position independent code will return to if it does MOV pc, lr

; Error may be in transient's workspace, so copy before deleting block

ReturnFromPIC

        MOV     r1, psr                 ; Remember V, you whalley (SWI clears)

        SWI     XOS_EnterOS             ; Get back to superstate in all cases

        Pull    "fp, wp"                ; Sanity slowly restoring ...

; .............................................................................
; In    fp, wp valid
;       r1 = psr
;       r0 -> error block if r1 has V set

DeleteTransient

; Delink this block from the transient list now that it has returned

; Restore saved registers from the block

        LDR     r2, TransientBlock
        LDMIA   r2, {r6-r9, r13-r14}^   ; Writing to r13,r14_usr

        TST     r1, #V_bit              ; Did it report error ?
        BLNE    CopyError

        ADR     r0, TransientBlock
        BL      SFreeLinkedArea         ; Accumulates V

        B       Run_Common_NoCopy       ; Lots of deallocation there

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This is where absolute code will return to if it does MOV pc, lr
; If it did an Exit then the guy with the exit handler has it !
; We'd better do the SWI Exit for it; as the superstack is flat we can't return
;
; In    r0-r2 optionally set such that a return code may be set by called code

ReturnFromAbsoluteCode

        SWI     OS_Exit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; ReadActionVariable
; ==================
;
; Reads Alias$@xxxType_ttt for given ttt and substitutes filename and cmdline
; into the variable as read.

; In    r2 = load address to decode (000ttt00)
;       r3 -> command tail to append after FullFilename
;       r4 -> variable prefix, eg 'Alias$@LoadType_'
;       r5 -> bit of text to put in error if variable unset
; filename to use is assumed to be in FullFilename

; Out   VC: r0 -> string to do with as you wish
;       string is in ActionVariable, just dying to be freed

ReadActionVariable ENTRY "r1-r4, r6" ; r0 result

             ^  0, sp
rav_varname  #  32                      ; Variable name is small
                                        ; as it might be a macro variable
rav_size     *  :INDEX: @

        SUB     sp, sp, #rav_size       ; Room for the variable string + result

        ADR     r3, rav_varname
05      LDRB    r14, [r4], #1           ; Copy variable name in
        TEQ     r14, #0
        STRNEB  r14, [r3], #1           ; No terminator; leave r3 -> next byte
        BNE     %BT05

        MOV     r2, r2, LSR #8          ; Shift -> 00000ttt for common code
        BL      ConvertHex3

; Get alias$@runtype_xxx filename commandline in a buffer

        ADR     r0, rav_varname         ; Point at string again
        MOV     r3, #0

20      MOV     r2, #-1
        SWI     XOS_ReadVarVal          ; Does it exist ? VSet misleading

        CMP     r4, #VarType_Number     ; Set if it's a number (that's silly)
        BEQ     %BT20                   ; Loop if so (maybe others)

        MOVS    r2, r2                  ; -ve -> exists
        BPL     %FA90                   ; [nope, -> Unknown run type]

; Variable exists, so copy RunType_xxx filename commandline to buffer

        LDR     r1, =ScratchSpace
        ADR     r2, rav_varname + (:LEN: "Alias$")
        BL      strcpy
        LDR     r2, FullFilename
        BL      AppendStringIfNotNull
        LDR     r2, [sp, #rav_size+4*2] ; Rest of line from caller r3
        BL      AppendStringIfNotNull

 [ debugrun
 DSTRING r1, "Subtituted string is "
 ]
        ADR     r0, ActionVariable      ; Wop this into a string
        BL      SGetLinkedString        ; May have spaces in it
        LDRVC   r0, ActionVariable      ; And return a pointer to it. Phew !

88      ADD     sp, sp, #rav_size
        EXIT


90      addr    r0, MagicErrorBlock_UnknownActionType
        MOV     r1, r5                  ; Stick the appropriate bit in
        BL      MagicCopyError
        B       %BT88                   ; Get out

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r2 =  number
;       r3 -> core

; Out   r2, r3 preserved
;       core contains 'abc', 0

ConvertHex3 ENTRY "r1"

        MOV     r1, #8                  ; MSN at base bit 8
        BL      NibbleToText
        STRB    r1, [r3, #0]
        MOV     r1, #4                  ; CSN at base bit 4
        BL      NibbleToText
        STRB    r1, [r3, #1]
        MOV     r1, #0                  ; LSN at base bit 0
        STRB    r1, [r3, #3]            ; Terminate string too
        BL      NibbleToText
        STRB    r1, [r3, #2]
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r1 = bitfield base
;       r2 = number

; Out   r1 = nibble at bitfield converted to base 16

NibbleToText ENTRY

        MOV     r1, r2, ROR r1
        AND     r1, r1, #15
        CMP     r1, #10
        ADDLO   r1, r1, #"0"
        ADDHS   r1, r1, #"A"-10
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; StartApplicEntry. Top level FSControl entry
; ================

; In    r1 -> command tail to append to EnvString
;       r2 = CAO ptr to write
;       r3 -> command name (first bit) to copy to EnvString

StartApplicEntry NewSwiEntry "r0"

        MOV     r0, r1
        MOV     r1, #0
        BL      StartUpTheApplication
        SwiExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; StartUpTheApplication
; =====================

; In    r0 -> command tail to append to EnvString
;       r1 -> file to load (at fileblock_load) if non zero
;       r2 =  CAO ptr to write
;       r3 -> command name (first bit) to copy to EnvString

; Out   VC: all ready to go
;       else error raised with OS_GenerateError as application destroyed
;       All linked areas in this domain freed
;       Current FS restored

StartUpTheApplication ENTRY "r0-r3"

 [ debugrun
 DREG r2,"StartUpTheApplication: CAO ",cc
 DSTRING r1, ", filename ",cc
 DSTRING r3, ", ComName ",cc
 DSTRING r0, ", ComTail "
 ]
        MOV     r0, #UpCall_NewApplication
        SWI     XOS_UpCall              ; After application gets called
        CMP     r0, #UpCall_Claimed     ; to release handlers we can't give
        BEQ     %FA95                   ; it a VSet return - it's not there

        MOV     r1, #Service_NewApplication
        SWI     XOS_ServiceCall         ; Can never give error
        CMP     r1, #Service_Serviced
        BEQ     %FA96                   ; Must give serious exception type err

 ; try out the pervy scheme for removing handlers
  [ {TRUE}
        Push   "r0-r5"
        MOV     r0, #MemoryLimit
        MOV     r1, #0
        SWI     XOS_ChangeEnvironment
        MOV     r5, r1
        MOV     r0, #ExitHandler
        MOV     r1, #0
        MOV     r2, #0
        MOV     r3, #0
        SWI     XOS_ChangeEnvironment
        CMP     r1, r5
        BLT     application_is_shelling
        MOV     r0, #UndefinedHandler
remove_naff_handlers
        MOV     r1, #0
        MOV     r2, #0
        MOV     r3, #0
        SWI     XOS_ChangeEnvironment
        CMP     r1, r5
        SWILT   XOS_ReadDefaultHandler
        SWILT   XOS_ChangeEnvironment
        ADD     r0, r0, #1
        CMP     r0, #ExceptionDumpArea
        MOVEQ   r0, #UpCallHandler
        CMP     r0, #UpCallHandler
        BLS     remove_naff_handlers

 ASSERT UpCallHandler+1=MaxEnvNumber  ; any added handlers need consideration

application_is_shelling
        Pull   "r0-r5"
    ]

        LDR     r1, [sp, #4]            ; Use passed name as flag
        CMP     r1, #0                  ; Sam calling ? VClear
        MOVNE   r0, #fsfile_Load        ; Will load at fileblock_load
        BLNE    CallFSFile              ; Only I load files, various valid bits
        BVS     %FT97                   ; and core already validated


; Can now set CAO, copy the string + read time for GetEnv

        MOV     r0, #CAOPointer
        MOV     r1, r2
        SWI     XOS_ChangeEnvironment

        MOV     r0, r3                  ; Command name^
        LDR     r1, [sp]                ; Command tail^ (null for me)
        BL      CopyCommandLineAndReadTime

        BL      SFreeAllLinkedAreas     ; Only in the current domain

        LDR     r14, currentfs          ; Restore current FS
        STR     r14, tempfs
        EXIT


95      addr    r0, ErrorBlock_CantStartApplication ; UpCall claimed
        BL      CopyError
        EXIT


96      addr    r0, ErrorBlock_CantStartApplication ; Service claimed
        STR     r0, globalerror


97      BL      SFreeAllLinkedAreas     ; Only in the current domain

        LDR     r14, currentfs          ; Restore current FS
        STR     r14, tempfs

        LDR     r0, globalerror         ; Must explode as application has
        SWI     OS_GenerateError        ; got its hooks out

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r0 -> command first bit
;       r1 -> command tail to append

CopyCommandLineAndReadTime ENTRY "r0-r2"

 [ debugrun
 DSTRING r0, "CopyCommandLineAndReadTime: First bit ,cc
 DSTRING r1, ", command tail "
 ]
 [ AssemblingArthur
        LDR     r1, =EnvString
 |
        LDR     r1, EnvStringAddr
 ]
        MOV     r2, r0                  ; Command name^
        BL      strcpy
        LDR     r2, [sp, #4]            ; Append command tail to that
        BL      AppendStringIfNotNull
 [ debugrun
 DSTRING r1, "EnvString now "
 ]

        MOV     r0, #14
 [ AssemblingArthur
        LDR     r1, =EnvTime
 |
        LDR     r1, EnvTimeAddr
 ]
        MOV     r14, #3
        STR     r14, [r1]
        SWI     XOS_Word                ; ReadTime shouldn't give error
        EXITS                           ; So make like it didn't !

        LTORG

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r2 -> string (CtrlChar term) to append to r1 string

AppendStringIfNotNull ENTRY "r2"

 [ debugrun
 DSTRING r2, "AppendStringIfNotNull: "
 ]
        LDRB    r14, [r2]               ; Is string empty ?
        CMP     r14, #space
        ADRHS   r2, %FT90               ; space
        BLHS    strcat
        LDRHS   r2, [sp]                ; string
        BLHS    strcat
        EXIT
90
        DCB     space, 0
        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;                       Ones that can be commoned up
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; LibEntry. Top level FSControl entry
; ========

; In    r1 -> command tail

LibEntry NewSwiEntry "r0-r5",,ShareFrame ; FSFunc only preserves r6 up

        MOV     r0, #fsfunc_Lib

; .............................................................................
; Save quite a bit of code by commoning up frame creation, translation, fsop,
; string deallocation + exit!

; In    r0 = fsfunc_xxx
;       r1 -> name to translate
;       frame not yet created

                         GBLS    FSControlCommon_RegList
FSControlCommon_RegList  SETS    "$Proc_RegList"


FSControlCommon ; NONewSwiEntry

        InitialiseFrame

        BL      TransNameSetFSAndPolice
        BVS     FSControlCommonSwiExit

        BL      CallFSFunc              ; Use fsforthisop

FSControlCommonDeallocate

        BL      SFreePassedFilenameAndSpecial

FSControlCommonSwiExit

        SwiExit

; .............................................................................
;
; CatEntry. Top level FSControl entry
; ========

; In    r1 -> command tail (for Cat, Ex, Info)

 assert (FSControl_Cat-fsfunc_Cat) = (FSControl_Ex  -fsfunc_Ex  )
 assert (FSControl_Cat-fsfunc_Cat) = (FSControl_Info-fsfunc_Info)

CatEntry NewSwiEntry "r0-r5",,ShareFrame ; FSFunc only preserves r6 up

        SUB     r0, r0, #(FSControl_Cat-fsfunc_Cat)

        B       FSControlCommon
 ASSERT "$Proc_RegList" = "$FSControlCommon_RegList"

; .............................................................................
;
; LCatEntry. Top level FSControl entry
; =========

; In    r1 -> command tail (for LCat, LEx, Info)

 assert (FSControl_LCat-fsfunc_LCat) = (FSControl_LEx-fsfunc_LEx)

LCatEntry NewSwiEntry "r0-r5",,ShareFrame ; FSFunc only preserves r6 up

        SUB     r0, r0, #(FSControl_LCat-fsfunc_LCat)

        B       FSControlCommon
 ASSERT "$Proc_RegList" = "$FSControlCommon_RegList"

; .............................................................................
;
; FileInfoEntry. Top level FSControl entry
; =============

; In    r1 -> command tail

FileInfoEntry NewSwiEntry "r0-r5",,ShareFrame ; FSFunc only preserves r6 up

        MOV     r0, #fsfunc_FileInfo

        B       FSControlCommon
 ASSERT "$Proc_RegList" = "$FSControlCommon_RegList"

; .............................................................................
;
; AccessEntry. Top level FSControl entry
; ===========
;
; The attribute string is not checked and may contain any old crap, and should
; be assumed to be space or CtrlChar terminated

; In    r1 -> filename
;       r2 -> attribute string

AccessEntry NewSwiEntry "r0-r5",,ShareFrame ; FSFunc only preserves r6 up

        MOV     r0, #fsfunc_Access

        B       FSControlCommon
 ASSERT "$Proc_RegList" = "$FSControlCommon_RegList"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; DirEntry. Top level FSControl entry
; ========

; In    r1 -> command tail

DirEntry NewSwiEntry "r0-r5" ; FSFunc only preserves r6 up

        BL      TransNameSetFSAndPolice
        BVS     FSControlCommonSwiExit

        MOV     r0, #fsfunc_Dir
        BL      CallFSFunc      ; Use fsforthisop
        BVS     FSControlCommonDeallocate

        LDRB    r0, hadfsprefix ; DIR implies change to new fs if one specified
        TEQ     r0, #0          ; and we got no error in the filesyst operation
        LDRNE   r0, fsforthisop
        STRNE   r0, tempfs
        STRNE   r0, currentfs

        B       FSControlCommonDeallocate
 ASSERT "$Proc_RegList" = "$FSControlCommon_RegList"

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;                   Ones that can't really be commoned up
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; OptEntry. Top level FSControl entry
; ========
;
; Filing System action control

; In    r1 = first parm, r2 = second parm

OptEntry NewSwiEntry "r0-r5, r6, fscb" ; FSFunc only preserves r6 up

        LDR     fscb, tempfs            ; Use tempfs
        TEQ     fscb, #Nowt             ; Give 'No sel FS' error lower down
        BEQ     %FT10

        CMP     r1, #1                  ; Keep a note of OPT 1 setting ?
        MOVLO   r2, #0                  ; Default setting is 0 / CMOS ?
        STRLSB  r2, [fscb, #fscb_opt1]  ; Keep a note of/Reset OPT 1 setting ?
        BEQ     %FA90 ; SwiExit         ; Don't tell Filing System EVER

10      MOV     r0, #fsfunc_Opt         ; Numeric arguments
        MOV     r6, #0                  ; Use current context
        BL      CallFSFunc_Given        ; Use fscb^

90      SwiExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; RenameEntry. Top level FSControl entry
; ===========

; In    r1 -> path to rename
;       r2 -> new name for file(s)

RenameEntry NewSwiEntry "r0-r5, r6-r8" ; FSFunc only preserves r6 up

        MOV     r1, r2                  ; Parse second filename (r2in)
        BL      TransNameSetFSAndPolice
        BVS     %FA90 ; SwiExit, no deallocate

        LDR     r7, SpecialField        ; r7 := second special field for op
        STR     r7, SpecialField2       ; And move to second string set
        LDR     r14, PassedFilename
        STR     r14, PassedFilename2

        BL      SetMagicWildCardIfSo
        BVS     %FA89 ; SwiExit, deallocate once, AFTER making it No.2

        LDR     r8, fsforthisop         ; And second file system
        MOV     r2, r1                  ; And stripped name^

        LDR     r1, [fp, #4*1]          ; Parse first filename (r1in)
        BL      TransNameSetFSAndPolice
        BVS     %FA89 ; SwiExit, deallocate once

        BL      SetMagicWildCardIfSo
        BVS     %FA88 ; SwiExit, deallocate both

        LDR     r14, fsforthisop        ; Must be on same Filing System
        TEQ     r14, r8                 ; otherwise we must copy + delete
        BNE     %FA85 ; Bad Rename, deallocate both

; r1,r2 -> names, r7 -> second special

        MOV     r0, #fsfunc_Rename
        BL      CallFSFunc              ; Use fsforthisop
        BVS     %FA88 ; SwiExit, deallocate both

; r1 = 0 -> Rename performed, <> 0 -> Rename too hard

        TEQ     r1, #0                  ; Done it ?
        BEQ     %FA88 ; SwiExit, deallocate both

85      addr    r0, ErrorBlock_BadRename
        BL      CopyError

88      BL      SFreePassedFilenameAndSpecial

89      BL      SFreePassedFilename2AndSpecial2

90      SwiExit

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

        LTORG

        LNK     $fileprefix.FSCtrl2
