;  AllFiles Program source
;   Author: Mike Cargal
;   January  1989

True   EQU 0
False  EQU -1 

ArpBaseR EQUR  A6
WrkR     EQUR  A5
LocR     EQUR  A4

       OPTION NL
       INCLUDE 'libraries/arpbase.p'
       INCLUDE 'libraries/dosextens.i'
       INCLUDE 'exec/memory.i'
       INCLUDE 'ltypes.i'   ; used to define neg offset structures
;                              for LINK and UNLK instructions       
       OPTION L

       XREF    _LVOOpenLibrary
       XREF    _LVOCloseLibrary
       XREF    _LVOFindTask

FileNameLen  EQU 256   ; DOS says 255 max ,but I'm reading only
;                          and I want to keep long word alignment  

  STRUCTURE WrkStorage,0
        APTR    ArgPtr
		LONG	Initial_SP
		LABEL   WorkSt_SizeOf
		
  STRUCTURE Parameters,0
        L_APTR    CurrLock
        L_APTR    DirPtr
        L_STRUCT  FileName,FileNameLen
        L_STRUCT  MyFib,fib_SIZEOF
        L_LABEL   Parameters_SizeOf

_ABSExecBase EQU 4
LineFeed     EQU 10

EXECALL: MACRO $\1
       MOVE.L  A6,-(SP)        ; Save current A6
       MOVEA.L _ABSExecBase,A6 ; Load Exec Base
       JSR     _LVO\1(A6)      ; Jump to Subroutine
       MOVE.L  (SP)+,A6        ; Restore A6
       ENDM

ARPCALL: MACRO $\1
       JSR     _LVO\1(A6)      ; Jump to Subroutine
       ENDM

*      SECTION  CODE
******************************************************************
*      Start of Code                                             *
******************************************************************
       MOVEM.L D0/A0,-(SP)     ; Save command line ptr/len
       MOVEQ.L #ArpVersion,D0  ; Current version of ARP
       LEA     ArpNm,A1        ; Point to library name
       EXECALL OpenLibrary     ; Open it up
       MOVEA.L D0,ArpBaseR     ; Save ArpBaseR
       TST.L   D0              ; Did we get NULL Pointer ?
       BNE     ArpOpenOK       ; -NO- good
       MOVEQ.L #ERROR_INVALID_RESIDENT_LIBRARY,D0
       ADDQ    #8,SP           ; Reset Stack
       RTS                     ; ARP didn't open (bad news)
ArpOpenOK
       MOVE.L  #WorkSt_SizeOf,D0 ; Size of working storage
       ARPCALL ArpAlloc        ; Get working storage
       MOVE.L  D0,WrkR         ; Use Wrk Reg to point to working stg
       TST.L   D0              ; Did we get a NULL pointer ?
       BNE     1$              ; -NO- good
       ADDQ    #8,SP           ; -YES- Restore Stack Pointer
       MOVE.L  #ERROR_NO_FREE_STORE,D0
       BRA     AllocOut        ;   and exit program
1$
******************************************************************
*   Process Command Line                                         *
******************************************************************
       MOVEM.L (SP)+,D0/A0
       MOVE.L  SP,Initial_SP(A5) ; Save Stack Pointer
*       MOVE.L  #CLSTRING,A0    ;  ***** TEST CODE *****
*       MOVE.L  #CLSTRINGLEN,D0 ;  ***** TEST CODE *****
       LEA     HelpString,A1   ; Point to help text
       LEA     ArgPtr(A5),A2   ; Point to Arg array
       LEA     Template,A3     ; Point to Command Template
       ARPCALL GADS            ; Edit Command Line input
       CMPI.L  #-1,D0          ; Error return ?
       BNE     CL_OK           ; - No -
       MOVE.L  #ERROR_ACTION_NOT_KNOWN,D0  ; - Yes - Set error code
       BRA     ERROR           ; and exit
CL_OK
       TST.L   D0              ; Any Arguments ?
       BEQ     NoDirSpec       ; - No - use current dir
NextArg
       MOVEA.L ArgPtr(WrkR),A1 ; get arg pointer
       TST.L   (A1)            ; NULL pointer ?
       BEQ.S   Done            ; -yes- then we're done
       MOVEA.L (A1)+,A0        ; A0 points to current arg
       MOVE.L  A1,ArgPtr(WrkR) ; Pointer to next arg ptr
       BSR     ListDir         ; Call Recursive routine to Process Arg
       BRA.S   NextArg         ; Get Next Arg
NoDirSpec
       LEA     zbyte,A0
       BSR     ListDir         ; Call recursive routine to process
Done                           ;   current dir
       MOVE.L  Initial_SP(A5),SP ; Restore initial Stack pointer
       MOVEA.L ArpBaseR,A1     ; Point to ARP library
       EXECALL CloseLibrary    ;   and close it
       MOVEQ   #0,D0           ; Set good return code
       RTS                     ; See ya later
******************************************************************
*      Recursive subroutine to print directories listings        *
*         at entry A0 points to directory name                   *
******************************************************************
ListDir 
       LINK    LocR,#Parameters_SizeOf ; allocate work strg on stack
       MOVE.L  A0,DirPtr(LocR) ; save pointer to directory name
       MOVE.L  A0,D1           ; move to D1 to get lock
       MOVE.L  #ACCESS_READ,D2 ; request read lock
       ARPCALL ArpLock         ; get lock
       MOVE.L  D0,CurrLock(LocR) ; save lock
       BNE     1$              ; process if not NULL
       MOVE.L  #ERROR_OBJECT_NOT_FOUND,D0 ; error if null
       BRA     ErrOut
1$
       LEA     MyFib(LocR),A0  ; point to my File Info Blk
       MOVE.L  A0,D2           ; put pointer in D2 for Examine
       MOVE.L  CurrLock(LocR),D1 ; move current lock to D1
       ARPCALL Examine         ; Examine current lock
       TST.L   D0              ; check return
       BEQ.S   LD_Exit         ;  if zero then get outa here
LD_Loop
       LEA     _LVOPuts(ArpBaseR),A1 ; put break message if broke
       ARPCALL CheckAbort      ; Check for ctrl-c etc.
       TST.L   D0              ; aborted ?
       BNE     Done            ; -yes-
       LEA     MyFib(LocR),A0  ; point to my File Info Blk
       MOVE.L  A0,D2           ; put pointer in D2 for Examine
       MOVE.L  CurrLock(LocR),D1 ; move current lock to D1
       ARPCALL ExNext          ; examine next entry 
       TST.L   D0              ; check return
       BNE.S   LD_First        ; non-zero is good
       ARPCALL IoErr           ; what was the problem ?
       CMPI.L  #ERROR_NO_MORE_ENTRIES,D0 ; no more entries ?
       BEQ.S   LD_Exit         ; -yes- finished with this level
       BRA.S   ERROR           ; -no- we've got a problem                       
LD_First
       MOVEA.L DirPtr(LocR),A0 ; point A0 to directory name
       LEA     MyFib+fib_FileName(LocR),A1 ; point A1 to entry name
       LEA     FileName(LocR),A2 ; point to local name buffer
       BSR     ConcatName      ; concatenate them
       TST.L   MyFib+fib_DirEntryType(LocR) ; is this entry a dir ?
       BMI.S   PutFile         ; -no- print file name 
       LEA     FileName(LocR),A0 ; -yes- point A0 to directory name 
       BSR     ListDir         ; and call this rtn recursively
       BRA.S   LD_Loop         ; when we get back, continue on where 
PutFile                        ;   we left off
       LEA     FileName(LocR),A1 ; point to file name
       ARPCALL Puts            ; print it to stdout
       BRA.S   LD_Loop         ; and carry on
LD_Exit
       UNLK    LocR            ; deallocate storage on stack
       RTS                     ; and exit this level
******************************************************************
**    Concatenate two strings with a '/' between them           **
**       A0 - Points to Directory Name                          **
**       A1 - Points to name to append after '/'                **
**       A2 - Points to destination buffer                      **
******************************************************************
ConcatName
       MOVE.L  #FileNameLen,D0 ; max length of file name
       CMPI.B  #0,(A0)
       BEQ.S   MoveEntry
1$     MOVE.B  (A0)+,(A2)+     ; move directory to buffer
       DBEQ    D0,1$
       TST.L   D0              ; did we fill buffer (shouldn't happen)
       BEQ     ErrOut          ; -yes- then we've got a problem
       CMPI.B  #':',-2(A2)     ; was it a device
       BNE     NotDev          ; -no-
       LEA     -1(A2),A2       ; -yes- back up over 0 byte
       ADDQ.L  #1,D0           ; add one back to byte count
       BRA.S   MoveEntry       ; and don't put '/'
NotDev         
       MOVE.B  #'/',-1(A2)     ; put '/' after directory name
MoveEntry       
2$     MOVE.B  (A1)+,(A2)+     ; add new entry name (file or dir) 
       DBEQ    D0,2$    
       RTS                     ; and return
******************************************************************
                     
ERROR 
       ARPCALL IoErr           ; find error code
       MOVE.L  D0,D2           ; put it in reg D2 for WHY Command
       MOVE.L  #RETURN_ERROR,D0 ; set error return code
ErrOut
       MOVE.L  Initial_SP(A5),SP ; Restore initial stack pointer
AllocOut
       MOVEA.L ArpBaseR,A1     ; Point to ARP library
       EXECALL CloseLibrary    ;   and close it
       RTS                     ; See ya later
******************************************************************

;       SECTION DATA,DATA
ArpNm      CSTRING 'arp.library'

;CLString     DC.B 'includes'
;CLStringLen  EQU *-CLString
;             DC.B 0

Template   CSTRING 'Directory/...' 

HelpString DC.B 'FAll with no arguments will list all files in the',LineFeed
  DC.B 'current directory, and any subdirectories. If you specify',LineFeed
  DC.B 'a directory(s), the same will be done for the directories',LineFeed
  DC.B 'specified.  In both cases, files will be listed with the',LineFeed
  DC.B 'full file name needed to access them from your current directory'
  DC.B LineFeed,0
zbyte DC.B 0
           END