* * * * * * * * * * * * * * * * * * * * * * * * *
* ls.asm					*
* v5.0						*
* Jörgen Grahn					*
*						*
* 910718 ... 921116 ... 921221 ...		*
* 921231 ... 930101 ... 930711			*
*						*
* * * * * * * * * * * * * * * * * * * * * * * * *
*						*
* History:					*
*						*
* (...)						*
*						*
* v4.2	(11.7.93)				*
*	Fixed silly, horrible reentrancy bug by *
*	replacing the BSS hunk with a dynamic	*
*	allocation. This made the program	*
*	8 bytes smaller.			*
*						*
* v4.3	(11.7.93)				*
*	Fixed memory location zero bug.	Ls	*
*	would try to allocate $ABADCAFE memory	*
*	or something like that if MungWall was	*
*	active - thanks, Carolyn!		*
*						*
* v4.4	(11.7.93)				*
*	Fixed another memory location zero bug,	*
*	an old one this time. Ls would not list	*
*	current directory if given no argument	*
*	with MungWall active.			*
*						*
* v5.0	(12.7.93)				*
*	Changed error report when trying to do	*
*	a directory listing on a file.		*
*	Added hardlinks in italic and softlinks	*
*	in white.				*
*						*
*	(17.7.93)				*
*	Redid the source slightly so that 	*
*	others may compile without changes.	*
*	No more comments in Swedish - if other	*
*	people hate comments in Swedish as much *
*	as I hate comments in German, those	*
*	would have meant *very* bad publicity.	*
*	;-)					*
*						*
*	My own include "offsets204.i" skipped,	*
*	xrefs added instead.			*
*						*
* * * * * * * * * * * * * * * * * * * * * * * * *

ABSEXECBASE		EQU 4
MEMF_ANY		EQU 0
SHARED_LOCK		EQU -2
ERROR_DIR_NOT_FOUND	EQU 204
ERROR_OBJECT_WRONG_TYPE	EQU 212
ERROR_NO_MORE_ENTRIES	EQU 232
SIGBREAKF_CTRL_C	EQU $00001000
fib_SIZEOF		EQU 260
fib_DIRENTRYTYPE	EQU 4			* <0 -> file, >=0 -> dir
fib_FILENAME		EQU 8

ST_ROOT			EQU  1
ST_USERDIR		EQU  2
ST_SOFTLINK		EQU  3	
ST_LINKDIR		EQU  4	
ST_FILE			EQU -3
ST_LINKFILE		EQU -4
ST_PIPEFILE		EQU -5

	XREF	_LVOAllocVec
	XREF	_LVOOpenLibrary
	XREF	_LVOReadArgs
	XREF	_LVOLock
	XREF	_LVOExamine
	XREF	_LVOPrintFault
	XREF	_LVOCheckSignal
	XREF	_LVOIoErr
	XREF	_LVOUnLock
	XREF	_LVOFreeArgs
	XREF	_LVOCloseLibrary
	XREF	_LVOFreeVec
	XREF	_LVOOutput
	XREF	_LVOPutStr
	XREF	_LVOFlush
	XREF	_LVOExNext


libcall	MACRO
	jsr _LVO\1(a6)
	ENDM

* * * * * * * * * * * * * * * * * * * * * * * * *

	OFFSET	0
ra_array:
	ds.l	1
***	CNOP	0,4		* Why can't I CNOP here?
				* Well, it's OK anyway. FileInfoBlocks
				* need to be on a LONG-aligned address.
				* Just think twice before adding data here!
fib:	ds.b	fib_SIZEOF	* FileInfoBlock
	ds.w	0
***	CNOP	0,2
file:	ds.b	4+4+30+4+4+1+1	* Room for:
				* a) Two Escape sequences
				* b) 30 byte filename
				* c) Two Escape sequences
				* d) one space
				* e) terminating NULL byte
blocksize:

* * * * * * * * * * * * * * * * * * * * * * * * *

	SECTION "text",code

entrypoint:
	movem.l	d1-d7/a0-a6,-(sp)

	move.l	ABSEXECBASE.w,a6

	move.l	#blocksize,d0
	move.l	#MEMF_ANY,d1
	libcall	AllocVec			* Allocate memory
	move.l	d0,a4				* to play with...
	beq	exit

	lea	dosname(pc),a1
	moveq	#36,d0

	libcall	OpenLibrary
	move.l	d0,a6
	beq	freemem

	* We now have DosBase in a6, and "BSS" in a4.

	lea	ra_array(a4),a0
	lea.l	zerostring(pc),a1		* Point the argument to fill
	move.l	a1,(a0)				* in to a zero lenght string
	move.l	a0,d2				* to be used as default.
	lea	template(pc),a0
	move.l	a0,d1
	clr.l	d3

	libcall	ReadArgs
	move.l	d0,a5				* Save the ReadArgs struct
	bne.s	readargs_ok

	bsr	printioerr
	bra	closedos

readargs_ok:					* Dos in a6, ReadArgs in a5.

	move.l	ra_array(a4),d1			* Program argument string
	move.l	#SHARED_LOCK,d2
	libcall	Lock
	move.l	d0,d7
	bne.s	locked_ok

	bsr	printioerr
	bra.s	freeargs

locked_ok:				* Dos - a6	ReadArgs - a5
					* Lock - d7	"BSS" - a4
	lea	fib(a4),a3		* fib - a3

	move.l	d7,d1
	move.l	a3,d2
	libcall	Examine
	tst.l	d0
	beq.s	examine_failed
	tst.l	fib_DIRENTRYTYPE(a3)	* Did we Lock() a file?
	bpl.s	dir_examined

examine_on_file:
	moveq	#0,d2
	move.l	#ERROR_OBJECT_WRONG_TYPE,d1
	libcall	PrintFault
	bra.s	freelock

	* d3 holds how many names have been written to this row.
	* d4 holds the _real_ position on the row.
dir_examined:
	clr.l	d3
	move.l	d3,d4

exnext:
	lea	file(a4),a2
	bsr	readname		* fib (a3) file (a2) lock (d7)
					* nr_names (d3) pos (d4)
	tst.l	d0
	bne.s	print_file
	bsr.s	newline			* Put us on new line...
	bra.s	no_more_files		* ...and close down

print_file:
	move.l	a2,a0
	bsr.s	putstr

	move.l	#SIGBREAKF_CTRL_C,d1
	libcall	CheckSignal		* Check for ^C.
	tst.l	d0
	beq.s	exnext

	bsr.s	newline			* Put us on new line...
	lea	breakstring(pc),a0
	bsr.s	putstr
	bra.s	freelock

examine_failed:
no_more_files:
	libcall	IoErr			* Should an error be printed?
	cmpi.l	#ERROR_NO_MORE_ENTRIES,d0
	beq.s	freelock
	bsr	printioerr

freelock:
	move.l	d7,d1
	libcall	UnLock

freeargs:
	move.l	a5,d1
	libcall	FreeArgs

closedos:
	move.l	a6,a1
	move.l	ABSEXECBASE.w,a6
	libcall	CloseLibrary

freemem:
	move.l	a4,a1
	move.l	ABSEXECBASE.w,a6
	libcall	FreeVec

exit:
	moveq	#0,d0
	movem.l	(sp)+,d1-d7/a0-a6
	rts

* * * * * * * * * * * * * * * * * * * * * * * * *
*
* Puts us on a new line, if necessary.
* Destroys d0-d2/a0-a1.

newline:
	tst.l	d4
	beq.s	1$
	lea	newlinestr(pc),a0
	bsr.s	putstr
1$:	rts

* * * * * * * * * * * * * * * * * * * * * * * * *
*
* fputs(string (a0))
* Destroys d0-d1/d5/a0-a1
*

putstr:
	move.l	a0,-(sp)
	libcall	Output
	move.l	d0,d5
	beq.s	1$
	move.l	(sp)+,d1
	libcall	PutStr
	move.l	d5,d1
	libcall	Flush
1$:	rts

* * * * * * * * * * * * * * * * * * * * * * * * *
*
* Reads a filename for printing.
*
* a2 - 'file' array
* a3 - fib
* d7 - lock
* d3 - number of names previous on row (altered [0..3])
* d4 - position on row (altered)
*
* returns 0 if end of names.

readname:
	movem.l	d1-d2/d5-d7/a0-a6,-(sp)

	move.l	d7,d1
	move.l	a3,d2
	libcall	ExNext
	tst.l	d0
	beq	sorry

	move.l	a2,a1				* a2 - name buffer (aligned)
	move.l	fib_DIRENTRYTYPE(a3),d1		* Type in d1.

	* Following is conditional code to print different
	* types of files in different ways.
	* Softlinks:	in white
	* Hardlinks:	italic
	* Directories:	blue
	* Files:	black
	* Other things:	black

	bmi	isfiletype
	* A softlink, a hardlink to directory, a directory, or something else.
	cmpi.w	#ST_SOFTLINK,d1
	bne.s	1$
	lea	csifaint(pc),a5
	bsr	esc_cpy
	bsr.s	fill_name
	lea	csicolclr(pc),a5
	bsr	esc_cpy
	bra.s	endprint
1$:	cmpi.w	#ST_LINKDIR,d1
	bne.s	2$
	lea	csihigh(pc),a5
	bsr.s	esc_cpy
	lea	csiital(pc),a5
	bsr.s	esc_cpy
	bsr.s	fill_name
	lea	csicolclr(pc),a5
	bsr.s	esc_cpy
	lea	csiioff(pc),a5
	bsr.s	esc_cpy
	bra.s	endprint
2$:
	lea	csihigh(pc),a5
	bsr.s	esc_cpy
	bsr.s	fill_name
	lea	csicolclr(pc),a5
	bsr.s	esc_cpy
	bra.s	endprint
isfiletype:
	* A file, a hardlink or something else.
	cmpi.w	#ST_LINKFILE,d1
	bne.s	1$
	lea	csiital(pc),a5
	bsr.s	esc_cpy
	bsr.s	fill_name
	lea	csiioff(pc),a5
	bsr.s	esc_cpy
	bra.s	endprint
1$:
	bsr.s	fill_name
endprint:
	
fill_spaces:
	move.b	positions(pc,d3),d0
1$:	move.b	#' ',(a1)+
	addq.l	#1,d4
	cmp.b	d0,d4
	ble.s	1$

done_spaces:
	addq.l	#1,d3
	cmpi.w	#4,d3
	bne.s	1$

	clr.l	d3
	move.l	d3,d4
	move.b	#10,(a1)+
1$:	move.b	#0,(a1)			* D0 should here be non-zero.

sorry:	movem.l	(sp)+,d1-d2/d5-d7/a0-a6
	rts

fill_name:
	lea	fib_FILENAME(a3),a0
2$:	move.b	(a0)+,d0
	beq.s	1$
	addq.l	#1,d4
	move.b	d0,(a1)+
	bra.s	2$
1$:	rts

esc_cpy:
1$:	move.b	(a5)+,(a1)+
	bne.s	1$
	lea	-1(a1),a1
	rts

* * * * * * * * * * * * * * * * * * * * * * * * *
*
* Prints IoErr().
* Destroys a0-a1/d0-d2.
*
printioerr:
	libcall	IoErr
	moveq	#0,d2
	move.l	d0,d1
	libcall	PrintFault
	rts

* * * * * * * * * * * * * * * * * * * * * * * * *

positions:	dc.b	16,32,48,64
template:	dc.b	'DIR',0
dosname:	dc.b	'dos.library',0
versionstring:	dc.b	'$VER: ls 5.0 (12.7.93) Jörgen Grahn',0
breakstring:	dc.b	'***Break'
newlinestr:	dc.b	10
zerostring:	dc.b	0
escapesequences:
csihigh:	dc.b	$9b,'33m',0	* Highlight (blue)
csifaint:	dc.b	$9b,'2m',0	* Faint (white)
csicolclr:	dc.b	$9b,'39m',0	* Reset colour
csiital:	dc.b	$9b,'3m',0	* Italic
csiioff:	dc.b	$9b,'23m',0	* Italic off
	END
