;
; enumerate.s
;
; Run a command on lots of files (MDW)
;
;  1994-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's core utilities (coreutils).
;
; Coreutils is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Coreutils is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Coreutils.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Standard stuff -------------------------------------------------------

		GET	libs:swis
		GET	libs:header

		IMPORT	version

;----- Main code ------------------------------------------------------------

		AREA	|!!!Util$$Header|,CODE,READONLY

main		ROUT

		; --- Pass the command string to OS_ReadArgs ---

		STMDB	R13!,{R14}		;Keep my return address
		ADR	R0,enum_commDef		;Point to command definition
		MOV	R2,R12			;Point to the output buffer
		MOV	R3,#&100		;Size of my buffer
		SWI	XOS_ReadArgs		;Parse up my command string
		LDMVSIA	R13!,{PC}		;If it failed, quit now

		; --- Check validity of arguments ---

		LDMIA	R12,{R10,R11}		;Load info from the buffer

		LDR	R14,[R12,#8]		;Load the help flag
		CMP	R14,#0			;Does he want help?
		BNE	enum_showHelp		;Yes -- display helpful text

		CMP	R11,#0			;Is there a command to do?
		BEQ	enum_noCommand		;No -- complain about this
		CMP	R10,#0			;Is there a directory?
		ADREQ	R10,enum_currDir	;No -- use current director

		ADD	R14,R12,#12		;Point to nofiles/nodirs
		LDMIA	R14,{R8,R9}		;Load these flags out
		CMP	R8,#0			;Check for no files
		CMPNE	R9,#0			;And for no directories
		BNE	enum_trivial		;If both set, it's easy!

		; --- Copy the command into a buffer ---

		ADD	R0,R12,#&100		;Point to second buffer

00main		LDRB	R14,[R11],#1		;Get a byte from the command
		CMP	R14,#32			;Is this a nice character?
		STRCSB	R14,[R0],#1		;Store it in the buffer
		BCS	%00main			;If more to do, loop round

		MOV	R14,#' '		;A space to put on the end
		STRB	R14,[R0],#1		;Stick it on the end
		SUB	R11,R0,R12		;Find length of this string
		SUB	R11,R11,#&100

		; --- Copy the name after the command ---

		ADD	R7,R12,#&300		;Point to fourth buffer
		MOV	R0,R10			;Point to pathname

01main		LDRB	R14,[R0],#1		;Get a dirname byte
		CMP	R14,#32			;Is this the end yet?
		STRCSB	R14,[R7],#1		;Store it in the buffer
		BCS	%01main			;If more to do, do more

		MOV	R14,#'.'		;Put a dot after the dirname
		STRB	R14,[R7],#1		;Store that on the end

		; --- Set up for main scanning loop ---

		ADR	R6,enum_star		;Find all names in the dir
		MOV	R5,#&80			;Size of the buffer
		MOV	R4,#0			;This is the first call

		; --- Read directory entries and do commands ---

02main		MOV	R3,#1			;Read one entry at a time
		ADD	R2,R12,#&200		;Point to the buffer
		MOV	R1,R10			;Point to the directory name
		MOV	R0,#10			;Read files and information
		SWI	XOS_GBPB		;Get a directory entry
		LDMVSIA	R13!,{PC}		;If it failed, return error
		CMN	R4,#1			;Is that the end of it all?
		LDMEQIA	R13!,{PC}^		;Yes -- return to caller

		; --- Find out if we process this entry ---

		LDR	R0,[R2,#16]		;Get the object type
		CMP	R0,#1			;Is the object a file?
		BNE	%03main			;No -- check for a directory
		CMP	R8,#0			;Are we to process files?
		BNE	%02main			;No -- ignore this entry
		B	%04main			;Skip ahead to handle file

03main		CMP	R9,#0			;Are we to process dirs?
		BNE	%02			;No -- ignore this entry

		; --- Process the current entry ---

04main		ADD	R0,R2,#20		;Point to the actual name
		MOV	R1,R7			;Point to the command head
05main		LDRB	R14,[R0],#1		;Get a byte from the name
		STRB	R14,[R1],#1		;Store it in the buffer
		CMP	R14,#0			;Is that the end?
		BNE	%05main			;No -- go round again

		STMFD	R13!,{R4}		;Save the current index
		ADD	R0,R12,#&300		;Point to full pathname
		ADD	R1,R12,#&200		;Use buffer three for output
		MOV	R2,#&100		;It's 256 bytes in size
		ADD	R3,R12,#&100		;Point to template string
		MOV	R4,R11			;Get length of template
		SWI	XOS_SubstituteArgs	;Try and substitute things
		LDMFD	R13!,{R4}		;Reload the directory index
		LDMVSIA	R13!,{PC}		;If it failed, return

                MOV	R0,R1			;Point to output buffer
		SWI	XOS_CLI			;Perform the command
		BVC	%02main			;If it was OK continue

		LDR	R14,[R12,#20]		;Is the x flag on?
		TEQ	R14,#0			;Don't corrupt the V flag
		BNE	%02main			;Yes -- ignore the error
		LDMFD	R13!,{PC}		;Otherwise return to caller

enum_commDef	DCB	"dir,"			;Offset 0
		DCB	"cmd,"			;Offset 4

		DCB	"help/S,"		;Offset 8
		DCB	"noFiles/S,"		;Offset 12
		DCB	"noDirs/S,"		;Offset 16
		DCB	"noErrors=x/S,"		;Offset 20
		DCB	0

enum_currDir	DCB	"@",0

enum_star	DCB	"*",0

enum_showHelp	ADR	R0,enum_helpText	;Point to the help text
		MOV	R1,#0			;No didtionary, please
		LDR	R2,=version		;Find the version string
		ADR	R14,main		;Point to my base address
		ADD	R2,R14,R2		;Find the actual string
		SWI	XOS_PrettyPrint		;Display the string
		LDMIA	R13!,{PC}^		;And return to caller

enum_helpText	DCB	"enumerate ",27,0,13
		DCB	13
		DCB	"Syntax: enumerate [<options>] [-dir <directory>] "
		DCB	"-cmd <command>",13
		DCB	13
		DCB	"Executes <command> on each file/directory in "
		DCB	"<directory>.  If no <directory> is specified, the "
		DCB	"current directory is used.",13
		DCB	13
		DCB	"Options (which may be abbreviated) are:"
		DCB	13
		DCB	"-help",9,9,"Display this help text",13
		DCB	"-noDirs",9,9,"Do not execute command on "
		DCB	"directories",13
		DCB	"-noFiles",9,"Do not execute command on files",13
		DCB	"-noErrors",9,"Ignore errors from command",13
		DCB	0

enum_noCommand	ADR	R0,enum_noCmdErr
		LDMIA	R13!,{R14}
		ORRS	PC,R14,#&10000000

enum_trivial	ADR	R0,enum_easyErr
		LDMIA	R13!,{R14}
		ORRS	PC,R14,#&10000000

enum_noCmdErr	DCD	1
		DCB	"enumerate: No command specified.",0

enum_easyErr	DCD	1
		DCB	"enumerate: Nothing to do -- -nodirs and "
		DCB	"-nofiles both set!",0

;----- That's all, folks ----------------------------------------------------

		END
