; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; SUBT > Sources.CtrlUtils ; FSControl utilities: ; Facilities for constructing full paths ; Facilities for doing catalogues/examines/infos and *accesses ; Facilities for starting up catalogues etc. ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_ConstructFullPathWithoutFSAndSpecial ; ; In r1 -> tail for directory ; r2 -> buffer to construct path into ; r3 = size of buffer ; r6 = scb^/special field^ ; fscb^ ; ; Out ; r2 advanced to end of string in buffer ; r3 reduced by length of string inserted, will be sent ; negative to correct value for full string ; r4 = special field^ for root fs ; r5 = root fscb^ ; int_ConstructFullPathWithoutFSAndSpecial Entry TEQ fscb, #Nowt BEQ %FT10 LDRB r14, [fscb, #fscb_info] TEQ r14, #0 BNE %FT10 Push "r1,r6,fscb" LDR fscb, [r6, #:INDEX:scb_fscb] LDR r1, [r6, #:INDEX:scb_path] LDR r6, [r6, #:INDEX:scb_special] BL int_ConstructFullPathWithoutFSAndSpecial LDR r1, [sp] LDRB r1, [r1] TEQ r1, #0 ADRNE r1, %FT90 ; . between path elements, only if next piece of path is non-"" BLNE %FT50 Pull "r1,r6,fscb" BL %FT50 ; <path> EXIT 10 ; Got to a real filing system - construct the starting gubbins MOV r4, r6 MOV r5, fscb CMP r1, #0 BLNE %FT50 ; <path> EXIT 50 ; Secure copy a string into the buffer - always accumulate the length, but ; not necessarily copy the string Push "lr" RSB r3, r3, #0 BL strlen_accumulate RSBS r3, r3, #0 Swap r1, r2, GT BLGT strcpy_advance Swap r1, r2, GT Pull "pc" 90 DCB ".", 0 ALIGN ; ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_ConstructPathWithoutFS ; ; In r1 -> tail for directory ; r2 -> buffer to construct path into ; r3 = size of buffer ; r6 = scb^/special field^ ; fscb^ ; ; Out r2 advanced to end of string in buffer ; r3 reduced by length of string inserted, will be sent ; negative to correct value for full string ; r4 = special field^ for root fs ; r5 = root fscb^ ; int_ConstructPathWithoutFS Entry "r1,r2,r3" ; Get to root FS and special MOV r3, #0 BL int_ConstructFullPathWithoutFSAndSpecial LDMIB sp, {r2,r3} ; #<special>: TEQ r4, #NULL TEQNE r4, #Nowt ADRNE r1, %FT80 BLNE %FT50 MOVNE r1, r4 BLNE %FT50 ADRNE r1, %FT85 BLNE %FT50 ; <rest of path> LDR r1, [sp] BL int_ConstructFullPathWithoutFSAndSpecial ; Store the return values STMIB sp, {r2,r3} EXIT 50 ; Secure copy a string into the buffer - always accumulate the length, but ; not necessarily copy the string Push "lr" RSB r3, r3, #0 BL strlen_accumulate RSBS r3, r3, #0 Swap r1, r2, GT BLGT strcpy_advance Swap r1, r2, GT Pull "pc" 80 DCB "#", 0 85 DCB ":", 0 ALIGN ; ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_ConstructFullPath ; ; In r1 -> tail for directory ; r2 -> buffer to construct path into ; r3 = size of buffer ; r6 = scb^/special field^ ; fscb^ ; ; Out r2 advanced to end of string in buffer ; r3 reduced by length of string inserted, will be sent ; negative to correct value for full string ; int_ConstructFullPath Entry "r1,r2,r3,r4,r5" ; Get to root FS and special MOV r3, #0 BL int_ConstructPathWithoutFS LDMIB sp, {r2,r3} TEQ r5, #Nowt BEQ %FT10 ; <fs> ADD r1, r5, #fscb_name BL %FT50 10 ; : (if no special) TEQ r4, #NULL TEQNE r4, #Nowt ADREQ r1, %FT85 BLEQ %FT50 ; <rest of path> LDR r1, [sp] BL int_ConstructPathWithoutFS ; Store the return values STMIB sp, {r2,r3} EXIT 50 ; Secure copy a string into the buffer - always accumulate the length, but ; not necessarily copy the string Push "lr" RSB r3, r3, #0 BL strlen_accumulate RSBS r3, r3, #0 Swap r1, r2, GT BLGT strcpy_advance Swap r1, r2, GT Pull "pc" 80 DCB "#", 0 85 DCB ":", 0 ALIGN ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_ConstructFullPathWithError ; ; In r1 -> tail for directory ; r2 -> buffer to construct path into ; r3 = size of buffer ; r6 = scb^/special field^ ; fscb^ ; ; Out r2 advanced to end of string in buffer ; r3 reduced by length of string inserted, will be sent ; negative to correct value for full string ; Buffer overflow error generated if r3<0 at the end ; int_ConstructFullPathWithError Entry BL int_ConstructFullPath CMP r3, #0 addr r0, ErrorBlock_BuffOverflow, LT BLLT CopyError EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_ConstructFullPathOnStack ; ; In r1 -> tail ; r6 = scb/special ; fscb^ ; ; Out ; stack dropped by enough and hole filled in with path ; int_ConstructFullPathOnStack Entry "r2,r3,r7" MOV r7, sp MOV r2, #ARM_CC_Mask MOV r3, #0 BL int_ConstructFullPath RSB r3, r3, #3+1 ; 3 for round-up, 1 for \0-terminator BIC r3, r3, #3 SUB sp, sp, r3 MOV r2, sp BL int_ConstructFullPath LDMIA r7, {$Proc_RegList,pc} ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_CatExTitle ; ; In r1 -> tail for directory ; r6 = scb^/special field^ ; fscb^ set ; MaxFilenameSpace * StaticName_length int_CatExTitle Entry "r0-r5,fscb" [ debugcontrol DSTRING r1, "CatExTitle tail is " DREG r6, "scb^/special field^ is " DREG fscb, "fscb is " ] MOV r5, sp BL int_ConstructFullPathOnStack BL faff_boot_option_startup_given BLVC int_ReadBootOptionGiven MOVVS sp, r5 BVS %FT95 AND r2, r2, #3 TEQ r2, #0 ADREQ r0, dirdotspace0 TEQ r2, #1 ADREQ r0, dirdotspace1 TEQ r2, #2 ADREQ r0, dirdotspace2 TEQ r2, #3 ADREQ r0, dirdotspace3 MOV r4, sp BL message_write01 MOV sp, r5 BVS %FT95 BL XOS_NewLine_CopyError ; Convert to the root non-MultiFS BLVC fscbscbTofscb MOVVC fscb, r2 [ debugcontrol DREG fscb, "Root fscb is " ] ; Current directory ADRVC r0, csdspace ADRVC r1, csdspaceu MOVVC r2, #Dir_Current BLVC DisplayDirectoryPath BLVC XOS_NewLine_CopyError ; Current directory ADRVC r0, libdotspace ADRVC r1, libdotspaceu MOVVC r2, #Dir_Library BLVC DisplayDirectoryPath BLVC XOS_NewLine_CopyError ; User root directory ADRVC r0, urdspace ADRVC r1, urdspaceu MOVVC r2, #Dir_UserRoot BLVC DisplayDirectoryPath BLVC XOS_NewLine_CopyError EXIT 90 ; Not enough stack for cat title addr r0, ErrorBlock_NotEnoughStackForFSEntry BL CopyError EXIT 95 BL CopyErrorExternal EXIT dirdotspace0 DCB "DDS0", 0 dirdotspace1 DCB "DDS1", 0 dirdotspace2 DCB "DDS2", 0 dirdotspace3 DCB "DDS3", 0 csdspace DCB "CSDS", 0 csdspaceu DCB "CSDSU", 0 libdotspace DCB "LDS", 0 libdotspaceu DCB "LDSU", 0 urdspace DCB "URDS", 0 urdspaceu DCB "URDSU", 0 ALIGN ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_CatExBody ; ; In r0 = 0 for Cat, 1 for Ex, 2 for FileInfo ; r1 -> path tail to supply to fs ; r2 -> Wildcard to match names to ; r6 = special field/scb^ ; fscb^ ; ; Out Directory catalogued [ CatExLong ; When long file names are in use, we vary the width of columns according to ; the length of the longest filename. We also adjust the width for the length ; of the file name; we scan the directory twice. The first time, we simply ; look at the length of the longest name. CatExMinWidth * 12 ; minimum amount to allocate for a name (8+'/'+3) ] CatSpaceAdjustForNFS * -36 [ CatExLong CatSpace * 320 CatStringSpace * 400 | CatSpace * 280 CatStringSpace * 100 ] CatExBodyFrame RN 9 ^ 0, CatExBodyFrame CatExBody_EntryCount # 4 CatExBody_ScreenWidth # 4 CatExBody_LPos # 4 CatExBody_PreGap # 4 CatExBody_ItemsLeft # 4 CatExBody_EntryRover # 4 [ CatExLong CatExBody_EntryWidth # 4 ; the width, in characters, of the longest filename to be displayed ] CatExBody_FrameSize * :INDEX: @ CatExBody_CatExType # 4 ; R0In CatExBody_PathTail # 4 ; R1In CatExBody_WildCard # 4 ; R2In CatExBody_R3In # 4 CatExBody_R4In # 4 CatExBody_R5In # 4 CatExBody_Special # 4 ; R6In CatExBody_R7In # 4 CatExBody_R8In # 4 CatExBody_R9In # 4 CatExBody_WindBlock DCD VduExt_WindowWidth DCD -1 [ CatExLong CatExMaxWidthStr = "FileSwitch$$NameWidth",0 ALIGN ] [ CatExLong int_CatExBody Entry "r0-r9", CatExBody_FrameSize | int_CatExBody Entry "r0-r9", CatExBody_FrameSize ] MOV CatExBodyFrame, sp SUB sp, sp, #CatSpace + CatStringSpace [ debugcontrol DREG r0, "int_CatExBody rc",cc DSTRING r1, " on ",cc DSTRING r2, " with wildcard " ] MOV lr, #0 STR lr, CatExBody_EntryCount STR lr, CatExBody_LPos STR lr, CatExBody_PreGap [ CatExLong STR lr, CatExBody_EntryWidth ; store the initial maximum width of an entry ] ADR r0, CatExBody_WindBlock ADR r1, CatExBody_ScreenWidth SWI XOS_ReadVduVariables BVS %FT80 [ CatExLong ; *** Here we scan the dir entries, to find the longest name. Boring, but someone ; has to do it. MOV r4, #0 ; we don't need to use the stack frame so much here 05 ; Read another set of directory entries MOV r0, #fsfunc_ReadDirEntriesInfo LDR r1, CatExBody_PathTail ADD r2, sp, #CatStringSpace MOV r3, #CatSpace + CatSpaceAdjustForNFS MOV r5, #CatSpace + CatSpaceAdjustForNFS LDR r6, CatExBody_Special [ debugcontrol DSTRING r1,"ReadDirEntriesInfo(",cc DREG r2,",",cc DREG r3,",",cc DREG r4,",",cc DREG r5,",",cc DREG r6,",",cc DLINE ")" ] BL CallFSFunc_Given [ debugcontrol DREG r3,"...->(",cc DREG r4,",",cc DLINE ")" ] BVS %FT85 ; Where no items read? TEQ r3, #0 BEQ %FT07 MOV r5, r3 ; r5 used to count down entries in buffer ADD r1, sp, #CatStringSpace ; point r1 at the buffer LDR r2, CatExBody_EntryWidth ; width of an entry ADD r1, r1, #&14 ; point at string 06 ; deal with another entry BL strlen ; (r1->r3) get length of the string CMP r3, r2 ; is this name longer than the longest? MOVHI r2, r3 ; if so, then set new longest ADD r1, r1, r3 ; ptr to next entry ADD r1, r1, #3+1+&14 ; and terminator and round to word, then onto string BIC r1, r1, #3 SUBS r5, r5, #1 ; BNE %BT06 ; if not then back round loop STR r2, CatExBody_EntryWidth ; store (maybe updated) width of entry CMP r4, #-1 ; go to the next stage BEQ %FT08 B %BT05 ; do some more entries 07 ; No items read ; Was it the end? CMP r4, #-1 BEQ %FT08 ; if it was the end, then we can go to the next stage ; Wasn't end, so must be buffer overflow addr r0, ErrorBlock_BuffOverflow BL CopyError B %FT85 08 ; the next stage ; find out if there's a system variable with the entry width SUB sp, sp, #16 MOV r2, #15 MOV r1, sp MOV r3, #0 MOV r4, #3 ; we want to convert it to a string (so that Macros will be sorted) ADR r0, CatExMaxWidthStr ; variable name SWI XOS_ReadVarVal ; get the variable back [ debugcontrol DREG r1, "ptr: " ] MOVVS r2, #255 ; maximum limit BVS %FT09 ; variable not found or too long - ignore it CMPS r4, #1 LDREQ r2, [sp] BEQ %FT09 ; convert its value MOV r0, #0 ; terminate the string STRB r0, [sp, r2] ; MOV r0, #10+(1<<30) ; base 10, restrict range 0-255 MOV r1, sp [ debugcontrol DSTRING r1, "string: " ] SWI XOS_ReadUnsigned ; get the value [ debugcontrol DREG r2, "converted to: " ] MOVVS r2, #255 09 ; here, r2 should contain the max width, or zero ADD sp, sp, #16 CMPS r2, #255 MOVHI r2, #255 MOVS r2, r2 MOVMI r2, #12 [ debugcontrol DREG r2, "init width: " ] LDR r3, CatExBody_EntryWidth ; get the width ; now compare screen with and entry width LDR r0, CatExBody_ScreenWidth ; width of screen LDR r14, CatExBody_CatExType TEQ r14, #0 SUBEQ r0, r0, #21-12 TEQ r14, #1 SUBEQ r0, r0, #63-12 TEQ r14, #2 SUBEQ r0, r0, #68-12 [ debugcontrol DREG r0, "width available from screen " ] ; MOV lr, #&6000 ; STMIA lr, {r0,r2,r3} CMPS r3, r0 MOVGT r3, r0 CMPS r3, r2 ; set the min width MOVGT r3, r2 CMPS r3, #CatExMinWidth ; and if it's <12, make it 12 MOVLT r3, #CatExMinWidth STR r3, CatExBody_EntryWidth ; and now we have a width! ; STR r3, [lr, #12] [ debugcontrol DREG r3, "CatExBody_EntryWidth: " ] ; now that we've worked out the width, we do the whole thing ; again. we should really optimise for the case where there's ; only one batch! ] MOV r4, #0 STR r4, CatExBody_EntryCount 10 ; Read another set of directory entries MOV r0, #fsfunc_ReadDirEntriesInfo LDR r1, CatExBody_PathTail ADD r2, sp, #CatStringSpace MOV r3, #CatSpace + CatSpaceAdjustForNFS LDR r4, CatExBody_EntryCount MOV r5, #CatSpace + CatSpaceAdjustForNFS LDR r6, CatExBody_Special [ debugcontrol DSTRING r1,"ReadDirEntriesInfo(",cc DREG r2,",",cc DREG r3,",",cc DREG r4,",",cc DREG r5,",",cc DREG r6,",",cc DLINE ")" ] BL CallFSFunc_Given [ debugcontrol DREG r3,"...->(",cc DREG r4,",",cc DLINE ")" ] BVS %FT85 STR r4, CatExBody_EntryCount STR r3, CatExBody_ItemsLeft ; Where no items read? TEQ r3, #0 BEQ %FT75 ADD r1, sp, #CatStringSpace 20 ; Fill the buffer on the stack ; pick out load, execute, length, Attributes, objecttype, advancing r1 to the object name LDMIA r1!, {r2,r3,r4,r5,r6} STR r1, CatExBody_EntryRover ; Is it a match? MOV r0, r2 LDR r2, CatExBody_WildCard BL WildMatch MOV r2, r0 BNE %FT33 LDR r8, CatExBody_CatExType ; r0 as passed in TEQ r8, #2 BNE %FT25 LDR lr, [fscb, #fscb_info] TST lr, #fsinfo_fileinfo BEQ %FT25 ; Filing system gets given FileInfo MOV r7, sp BL strlen MOV r0, r1 LDR r1, CatExBody_PathTail BL strlen_accumulate ADD r3, r3, #1+1+3 BIC r3, r3, #3 SUB sp, sp, r3 MOV r2, r1 MOV r1, sp BL strcpy_advance MOV r2, #"." STRB r2, [r1], #1 MOV r2, r0 BL strcpy_advance MOV r0, #fsfunc_FileInfo MOV r1, sp LDR r6, CatExBody_Special [ debugcontrol DREG r0, "Use filing system:",cc DSTRING r1,",",cc DSTRING r6,"," ] BL CallFSFunc_Given MOV sp, r7 BVS %FT85 B %FT33 25 MOV r0, r6 ; objecttype MOV r6, sp ; Buffer start ADD r7, r6, #CatStringSpace ; Buffer end BL AdjustObjectTypeReMultiFS [ CatExLong Push "r10" LDR r10, CatExBody_EntryWidth ; get the width of the entry [ debugcontrol DREG r10, "Width being used: " ] ] BL int_CatExItem [ CatExLong Pull "R10" ] BVS %FT80 ; Get width of string to output MOV r1, sp BL strlen ; Column width in r0 LDR r14, CatExBody_CatExType [ CatExLong LDR r0, CatExBody_EntryWidth TEQ r14, #0 ADDEQ r0, r0, #21-12 TEQ r14, #1 ADDEQ r0, r0, #63-12 TEQ r14, #2 ADDEQ r0, r0, #68-12 | TEQ r14, #0 MOVEQ r0, #21 ; Cat column width TEQ r14, #1 MOVEQ r0, #63 ; Ex column width TEQ r14, #2 MOVEQ r0, #68 ; FileInfo column width ] ; r6{Spacing going to be needed} = ; ((r7{position across line} + r8{at end of entry} + r0{column width} - 1)/r0{column width})*r0{column width} - r7{position across line} LDR r7, CatExBody_LPos LDR r8, CatExBody_PreGap ADD r6, r7, r8 ADD r6, r6, r0 SUB r6, r6, #1 DivRem r5, r6, r0, r14, norem MUL r6, r0, r5 SUB r6, r6, r7 ; r5{new position if printed on this line} = r6{spacing} + r3{width} + r7{current position} ADD r5, r6, r3 ADD r5, r5, r7 ; If following a name and overflow a line, then do a line feed TEQ r8, #0 LDR lr, CatExBody_ScreenWidth CMPNE r5, lr BLS %FT30 SWI XOS_NewLine BVS %FT80 MOV r7, #0 ; position MOV r8, #0 ; after an entry MOV r6, #0 ; spacing 30 ; position += spacing + width ADD r7, r7, r6 ADD r7, r7, r3 ; Spew out the spacing BL SpewSpaces ; Display the item MOVVC r0, sp SWIVC XOS_Write0 BVS %FT80 ; At end of item indicator (is inter-item gap) MOV r8, #1 STR r7, CatExBody_LPos STR r8, CatExBody_PreGap 33 ; Advance to the next item (skip over the name and round up to a word) LDR r1, CatExBody_EntryRover ADD r3, r1, #1 + 3 ; 1 for the nul terminator, 3 for the rounding BL strlen_accumulate BIC r1, r3, #3 ; Any more items in this batch? LDR r3, CatExBody_ItemsLeft SUBS r3, r3, #1 STR r3, CatExBody_ItemsLeft BNE %BT20 LDR r4, CatExBody_EntryCount CMP r4, #-1 BNE %BT10 50 ; Successful completion of the body - tidy up the display ; If not at start of line, get to the start of line LDR r8, CatExBody_PreGap TEQ r8, #0 SWINE XOS_NewLine BVS %FT80 B %FT85 75 ; No items read ; Was it the end? LDR r4, CatExBody_EntryCount CMP r4, #-1 BEQ %BT50 ; Wasn't end, so must be buffer overflow addr r0, ErrorBlock_BuffOverflow BL CopyError B %FT85 80 ; External error - copy it BL CopyErrorExternal 85 MOV sp, CatExBodyFrame EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; SpewSpaces ; ; In r6 = number of spaces to spew ; ; Out spaces spewed (r0, VS error return mechanism) ; SpewSpaces Entry "r6" B %FT20 10 SWI XOS_WriteI+space EXIT VS 20 SUBS r6, r6, #1 BPL %BT10 EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_CatExItem ; ; In r0 = object type ; r1 ->name ; r2 = load address ; r3 = execute address ; r4 = length ; r5 = attributes ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; r8 = number of control string: ; 0 - CatFormat ; 1 - ExFormat ; 2 - FileInfoFormat [ CatExLong ; r10 = width of a filename field ] ; ; Out r0, VS error return mechanism CatFormat DCB "Cat",0 ExFormat DCB "Ex",0 FileInfoFormat DCB "FileInfo",0 ALIGN [ CatExLong int_CatExItem Entry "r0-r9" | int_CatExItem Entry "r0-r9" ] TEQ r8, #0 ADREQ r0, CatFormat TEQ r8, #1 ADREQ r0, ExFormat TEQ r8, #2 ADREQ r0, FileInfoFormat BL message_lookup BVS %FT40 MOV r8, r0 LDR r0, [sp, #Proc_LocalStack + 0*4] LDRB r9, [r8], #1 CMP r9, #" " BHI %FT20 B %FT30 10 ; Space between items MOV r0, #space BL int_StuffByteIntoBuffer 20 [ debugcontrol DREG r9, "Stuffing a number " ] ; Place the text of this item into the buffer LDR r0, [sp, #Proc_LocalStack + 0*4] ; r0 in TEQ r9, #"0" BLEQ int_StuffFilenameIntoBuffer TEQ r9, #"1" BLEQ int_StuffAttsIntoBuffer TEQ r9, #"2" BLEQ int_StuffLoadExecIntoBuffer TEQ r9, #"3" BLEQ int_StuffFileSizeIntoBuffer TEQ r9, #"4" BLEQ int_StuffExactLoadExecIntoBuffer TEQ r9, #"5" BLEQ int_StuffExactFileSizeIntoBuffer BVS %FT40 ; Advance to next item LDRB r9, [r8], #1 CMP r9, #space BHI %BT10 30 ; Terminate the buffer MOV r0, #0 BL int_StuffByteIntoBuffer 40 STRVS r0, [sp] EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffFilenameIntoBuffer ; ; In r1 ->name ; r6 = buffer ; r7 = buffer end (beyond end of usable buffer space) [ CatExLong ; r10 = width of field ] ; ; Out r6 advanced or error (r0,VS errors) ; int_StuffFilenameIntoBuffer Entry "r3" [ CatExLong [ debugcontrol DREG r10, "stuffing width: " ] MOV r3, r10 BL int_StuffRPaddedMaybeTruncatedStringIntoBuffer | MOV r3, #12 BL int_StuffRPaddedStringIntoBuffer ] EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffAttsIntoBuffer ; ; In r0 = object type ; r5 = attributes ; r6 = buffer ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; int_StuffAttsIntoBuffer Entry "r0,r3", 8 MOV r3, sp ; D TST r0, #object_directory MOVNE r0, #"D" STRNEB r0, [r3], #1 ; L TST r5, #locked_attribute MOVNE r0, #"L" STRNEB r0, [r3], #1 ; W TST r5, #write_attribute MOVNE r0, #"W" STRNEB r0, [r3], #1 ; R/ TST r5, #read_attribute MOVNE r0, #"R" STRNEB r0, [r3], #1 MOV r0, #"/" STRB r0, [r3], #1 ; W TST r5, #public_write_attribute MOVNE r0, #"W" STRNEB r0, [r3], #1 ; R TST r5, #public_read_attribute MOVNE r0, #"R" STRNEB r0, [r3], #1 MOV r0, #0 STRB r0, [r3], #1 MOV r3, #7 MOV r1, sp BL int_StuffRPaddedStringIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffLoadExecIntoBuffer ; ; In r0 = object type ; r2 = load address ; r3 = execute address ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; ExDateFormat DCB "ExDt",0 ExLoadExecFormat DCB "ExLdEx",0 ALIGN int_StuffLoadExecIntoBuffer Entry "r4,r5" ADR r4, ExDateFormat ADR r5, ExLoadExecFormat BL int_GenStuffLoadExecIntoBuffer EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffExactLoadExecIntoBuffer ; ; In r0 = object type ; r2 = load address ; r3 = execute address ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; FileInfoDateFormat DCB "FileInDt",0 FileInfoLoadExecFormat DCB "FileInLdEx",0 ALIGN int_StuffExactLoadExecIntoBuffer Entry "r4,r5" ADR r4, FileInfoDateFormat ADR r5, FileInfoLoadExecFormat BL int_GenStuffLoadExecIntoBuffer EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_GenStuffLoadExecIntoBuffer ; ; In r0 = object type ; r2 = load address ; r3 = execute address ; r4 = tag of date format ; r5 = tag of load+exec format ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; DirText DCB "Dr",0 ALIGN int_GenStuffLoadExecIntoBuffer Entry "r0-r4",24 ; Is it a directory? TST r0, #object_directory BEQ %FT10 ; It's a directory - output "Directory" ADR r0, DirText BL message_lookup MOVVC r1, r0 B %FT20 10 ; Handling of files BL IsFileTyped addr r1, anull, NE ; No text in the type field if untyped BNE %FT20 ; It's typed - display type then date BL ExtractFileType BL DecodeFileType BVS %FT90 STMVCIA sp, {r2,r3} MOVVC r1, #0 STRVCB r1, [sp, #8] MOVVC r1, sp 20 ; Copy the type to the type field MOVVC r3, #9 BLVC int_StuffRPaddedStringIntoBuffer MOVVC r0, #space BLVC int_StuffByteIntoBuffer BVS %FT90 LDR r2, [sp, #Proc_LocalStack + 2*4] LDR r3, [sp, #Proc_LocalStack + 3*4] BL IsFileTyped BNE %FT40 ; Display the date. Reverse order of words to correct byte ordering of date STR r3, [sp, #0*4] STR r2, [sp, #1*4] MOV r0, r4 BL message_lookup BVS %FT90 [ debugcontrol DSTRING r0,"Looked up date format OK:" ] ; faff faff faff: copy the string to be nul-terminated MOV r1, r0 BL strlen ADD r4, r3, #1 + 3 BIC r4, r4, #3 SUB sp, sp, r4 MOV r2, r1 MOV r1, sp BL strcpy ; nul terminates MOV r3, r1 ADD r0, sp, r4 MOV r1, r6 SUB r2, r7, r6 SWI XOS_ConvertDateAndTime ADD sp, sp, r4 MOVVC r6, r1 B %FT90 40 ; It's untyped - display as hex ; Convert the hex numbers into text MOV r0, r2 MOV r1, sp MOV r2, #12 SWI XOS_ConvertHex8 MOVVC r0, r3 ADDVC r1, sp, #12 MOVVC r2, #12 SWIVC XOS_ConvertHex8 ; Now stuff the buffer with the hex numbers MOVVC r0, r5 MOVVC r1, r6 SUBVC r2, r7, r6 MOVVC r4, sp ADDVC r5, sp, #12 BLVC message_lookup22_into_buffer MOVVC r6, r1 90 STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffFileSizeIntoBuffer ; ; In r4 = length ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; int_StuffFileSizeIntoBuffer Entry "r0-r2" MOV r0, r4 MOV r1, r6 SUB r2, r7, r6 SWI XOS_ConvertFixedFileSize STRVS r0, [sp, #Proc_LocalStack + 0*4] MOVVC r6, r1 EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffExactFileSizeIntoBuffer ; ; In r4 = length ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; int_StuffExactFileSizeIntoBuffer Entry "r0-r2" MOV r0, r4 MOV r1, r6 SUB r2, r7, r6 SWI XOS_ConvertHex8 STRVS r0, [sp, #Proc_LocalStack + 0*4] MOVVC r6, r1 EXIT [ {FALSE} ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffLPaddedStringIntoBuffer ; ; In r1 ->name ; r3 = required width ; r6 = buffer ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; ; Stuffs the name into the buffer padded to width ; int_StuffLPaddedStringIntoBuffer Entry "r3" BL strlen_accumulate RSBS r3, r3, #0 MOVLO r3, #0 BL int_StuffSpacesIntoBuffer EXIT VS BL int_StuffStringIntoBuffer EXIT ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffRPaddedStringIntoBuffer ; ; In r1 ->name ; r3 = required width ; r6 = buffer ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; ; Stuffs the name into the buffer padded to width ; int_StuffRPaddedStringIntoBuffer Entry "r3" RSB r3, r3, #0 BL strlen_accumulate BL int_StuffStringIntoBuffer EXIT VS RSBS r3, r3, #0 MOVHI r3, #0 BL int_StuffSpacesIntoBuffer EXIT [ CatExLong ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffRPaddedMaybeTruncatedStringIntoBuffer ; ; In r1 ->name ; r3 = required width ; r6 = buffer ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; ; Stuffs the name into the buffer padded to width. If the string's ; longer than the buffer width, it truncates it. ; int_StuffRPaddedMaybeTruncatedStringIntoBuffer Entry "r3,r4" MOV r4, r3 BL strlen ; string length in R3 CMP r3, r4 BHI %FT10 SUB r3, r3, r4 BL int_StuffStringIntoBuffer EXIT VS RSBS r3, r3, #0 MOVHI r3, #0 BL int_StuffSpacesIntoBuffer EXIT 10 MOV r3, r4 BL int_StuffRTruncatedStringIntoBuffer EXIT ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffSpacesIntoBuffer ; ; In r1 ->name ; r3 = required number of spaces ; r6 = buffer ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced or error (r0,VS errors) ; ; Stuffs the given number of spaces into the buffer ; int_StuffSpacesIntoBuffer Entry "r0,r3" MOV r0, #space B %FT20 10 BL int_StuffByteIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT VS 20 SUBS r3, r3, #1 BGE %BT10 ; Signed EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffStringIntoBuffer ; ; In r1 = string (ctrl char terminated) ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced by string length, or error (r0,VS) ; terminator not placed into buffer ; int_StuffStringIntoBuffer Entry "r0,r1" B %FT20 10 BL int_StuffByteIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT VS 20 LDRB r0, [r1], #1 CMP r0, #space-1 TEQHI r0, #delete BHI %BT10 EXIT [ CatExLong ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffRTruncatedStringIntoBuffer ; ; In r1 = string (ctrl char terminated) ; r3 = number of characters to print (including '...') ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced by string length, or error (r0,VS) ; terminator not placed into buffer ; int_StuffRTruncatedStringIntoBuffer Entry "r0,r1,r3" SUB r3, r3, #3 B %FT20 10 BL int_StuffByteIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT VS 20 SUBS r3, r3, #1 BMI %FT30 LDRB r0, [r1], #1 CMP r0, #space-1 TEQHI r0, #delete BHI %BT10 EXIT 30 ; just termination to deal with MOV r0, #'.' BL int_StuffByteIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT VS MOV r0, #'.' BL int_StuffByteIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT VS MOV r0, #'.' BL int_StuffByteIntoBuffer STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; int_StuffByteIntoBuffer ; ; In r0 = byte ; r6 = Buffer start ; r7 = buffer end (beyond end of usable buffer space) ; ; Out r6 advanced by 1, or error (r0,VS) ; int_StuffByteIntoBuffer Entry "r0" CMP r6, r7 STRLOB r0, [r6], #1 EXIT LO addr r0, ErrorBlock_BuffOverflow BL copy_error STRVS r0, [sp, #Proc_LocalStack + 0*4] EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; Process_WildPathnameMustExist ; ; In r1 -> Wildcarded pathname ; ; Out r0 = object type of 1st of the objects ; r1 -> Pathtail for object or directory for enumeration as appropriate ; r2 = load address of the 1st of the objects ; r3 = execute address of the 1st of the objects ; r4 = length of the 1st of the objects ; r5 = attributes of the 1st of the objects ; r6 = scb^/special field^ ; r7 = NULL or wildcard for enumeration ; fscb^ ; ; PassedFilename, FullFilename and SpecialField are the relevant locations ; for the various parts after processing. ; ; Will generate an error if the object doesn't exist ; Process_WildPathnameMustExist Entry BL Process_WildPathname EXIT VS TEQ r0, #object_nothing EXIT NE LDR r1, PassedFilename BL SetMagicPlainNotFound BL JunkFileStrings EXIT ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; Process_WildPathname ; ; In r1 -> Wildcarded pathname ; ; Out r0 = object type of 1st of the objects ; r1 -> Pathtail for object or directory for enumeration as appropriate ; r2 = load address of the 1st of the objects ; r3 = execute address of the 1st of the objects ; r4 = length of the 1st of the objects ; r5 = attributes of the 1st of the objects ; r6 = scb^/special field^ ; r7 = NULL or wildcard for enumeration ; fscb^ ; ; PassedFilename, FullFilename and SpecialField are the relevant locations ; for the various parts after processing. ; Process_WildPathname ALTENTRY ADR r0, PassedFilename MOV r2, #NULL addr r3, anull ADR r4, FullFilename MOV r5, #0 ADR r6, SpecialField BL TopPath_DoBusinessToPath EXIT VS ; Reject case with no filing system TEQ fscb, #Nowt LDREQ r1, PassedFilename BLEQ SetMagicPlainNotFound BLVS JunkFileStrings EXIT VS ; Is it an absolute directory? Push "r0,r3" BL strlen SUB r3, r3, #1 LDRB r0, [r1, r3] BL IsAbsolute Pull "r0,r3" BEQ %FT70 ; It's a non-absolute, check the source leaf for wildness LDR r7, PassedFilename [ debugutil DSTRING r7, "PassedFilename = " ] Push "r1,r3" MOV r1, r7 BL strlen ADD r8, r7, r3 Pull "r1,r3" 10 LDRB r14, [r8], #-1 TEQ r14, #"*" TEQNE r14, #"#" BEQ %FT30 TEQ r14, #"." TEQNE r14, #":" ; blah:blah or blah::blah, neither of which are wildcards BEQ %FT70 CMP r8, r7 BHS %BT10 B %FT70 20 ; A wildcard char has been found, continue and see whether it's a leaf name ; or just a wierd disc name. LDRB r14, [r8], #-1 TEQ r14, #"." BEQ %FT40 TEQ r14, #":" BNE %FT30 CMP r8, r7 BLO %FT70 ; It's just :<wierd disc name> LDRB r14, [r8] TEQ r14, #":" BEQ %FT70 ; It's <thing>::<wierd disc name> MOV r14, #":" B %FT40 ; It's <thing>:<wildcard> 30 CMP r8, r7 BHS %BT20 40 ; Confirmed wildleaf found with r8 before string or before preceding . or : TEQ r14, #"." TEQNE r14, #":" ADDEQ r7, r8, #2 ADDNE r7, r8, #1 ; Chop off the leaf from the path tail BL strlen ADD r8, r1, r3 50 LDRB r14, [r8, #-1]! TEQ r14, #"." MOVEQ r14, #0 STREQB r14, [r8] EXIT EQ CMP r8, r1 BHI %BT50 ; If haven't come to a ., but have come to start of string ; then must be tail for MultiFS, so chop it there. MOV r14, #0 STRB r14, [r8] EXIT 70 ; It's an absolute or non-wildcard, so ; let's do it singularly MOV r7, #NULL EXIT END