* Stack.Asm
*
*	Written 1/1/87 by C.Heath
*
*	This program may be freely distributed, provided it is not modified
* in any way. If an executable is distributed, use assem and blink 6.7,
* which should result in an executable of 400 bytes.

*	This module replaces the ADOS "Stack" command.  It exactly matches
* the Stack command syntax except it also will print a reasonable error
* message if you use a non-numeric command line.  It also will save
* a disk block, and should run faster because it is smaller than the
* magic 488 byte "icon" file size, and is a single segment instead of two.

*	This is installment two of the "Abolish ADOS Commands" series.
* Collect them all, amaze your friends.

******	Equates and publics	***************************************

	INCLUDE	"exec/types.i"
	INCLUDE	"libraries/dos.i"
	INCLUDE	"libraries/dosextens.i"

MIN_LIB		set	$1f		; Library minimum rev level!
ASC_ZERO	set	$30		; Ascii ZERO
MIN_STACK	set	1600		; Minimum stack allowed by the
					; ADOS "stack" command

my_str		set	-60		; Size of string allowed to build


*** WITH MANX, SUBSTITUTE public FOR xref
xlib	MACRO
	xref	_LVO\1
	endm

*** BEGIN MANX code. To use the manx assember, uncomment the next few lines
*
*	entry	.begin
*	public	.begin
*.begin
*** END MANX specific code

	xlib	OpenLibrary
	xlib	CloseLibrary
	xlib	FindTask

	xlib	Output
	xlib	Write

******	The Program		***************************************


Start:
	move.l	A0,A2			; Register A2 is cmdline henceforth

	move.l	4,a6			; ExecBase
	suba.l	A1,A1
	jsr	_LVOFindTask(A6)
	move.l	D0,A3			; Process base
	move.l	pr_CLI(A3),D0
	 beq.s	BadExit			; Not a CLI process. Punt
	asl.l	#2,D0
	move.l	D0,A3			; A3 points at CLIStruct henceforth

	lea	DOSName(pc),A1		; Open DOS.library
	moveq.l	#MIN_LIB,d0
	jsr	_LVOOpenLibrary(A6)
	or.l	D0,D0
	 beq.s	BadExit			; Can't!! Return error value...
	move.l	D0,A6			; DOSBase in A6 henceforth

	link	A5,#my_str		; Need some writeable space in stack

************************************************************************
*
* Check the input arguements
*	If there is no arg, print the old stack value
*	Else If the arg is a valid number input, set new stack
*	Else print error message
*
************************************************************************

	move.b	(A2),D0
	 beq.s	Do_OldStack
	cmp.b	#$0a,D0
	 beq.s	Do_OldStack		; No command line, print old stack

*
* Here, loop to get input for new stack
* Loop getting Ascii digits
*
	moveq.l	#0,D0			; New Stack Value built into D0
ll0:	moveq.l	#0,D1
	move.b	(A2)+,D1
	cmp.b	#$0A,D1
	 beq.s	eos
	sub.b	#'0',D1
	 blt.s	bad_input		; Test for valid digits
	cmp.b	#9,D1
	 bgt.s	bad_input

	add.l	D0,D0
	move.l	D0,D2			; Multiply prior value by 10
	asl.l	#2,D2			; Required to allow long_word value
	add.l	D2,D0

	add.l	D1,D0			; Add in new digit
	bra.s	ll0			; Loop on digits

* End of string, register D0 is new stack value in bytes
eos:
	cmp.l	#MIN_STACK,D0
	 blt.s	too_small			; Match "stack" command

	lsr.l	#2,D0				; Convert to LWords
	move.l	D0,cli_DefaultStack(A3)		; Save it and
	bra.s	finished			; Get Outa Here!

* Bad input string.  Print error message
bad_input:
	lea	bad_str(pc),A0
	bra.s	ok_print

* Input value too small. Must match ADOS's requirements, ick.
too_small:
	lea	str_too_small(pc),A0
	bra.s	ok_print

************************************************************************
*
* BadExit is where to go if there is an error opening the DOS library
*	This should only happen if things are really sick
*
************************************************************************

BadExit:	moveq	#20,D0
		rts

* No input value, print out the current default stack setting instead
Do_OldStack:

	move.l	cli_DefaultStack(A3),D0
	asl.l	#2,D0			; Get current size

	lea	SStr(pc),A1		; Copy the string to stack area
	lea	my_str(A5),A0
llz:	move.b	(A1)+,(A0)+
	 bne.s	llz
	subq	#1,A0			; Build string HERE

	lea	divtab(pc),A1		; Sucessive subtraction table here

ll1:	move.l	(A1)+,D1
	cmp.l	D1,D0
	 blt.s	ll1			; Find first digit

ll2:	moveq	#ASC_ZERO,D2		; Loop to calculate this digit
ll3:	cmp.l	D1,D0
	 blt.s	ll4
	addq	#1,D2
	sub.l	D1,D0
	bra.s	ll3

ll4:	move.b	D2,(A0)+		; Output this digit
	move.l	(A1)+,D1		; Continue to next until
	 bne.s	ll2			; There Ain't No More

outahere:
	lea	ZStr(pc),A1		; Copy the "bytes" too
ll5:	move.b	(a1)+,(A0)+
	 bne.s	ll5

	lea	my_str(A5),A0		; Get string origin

***************************************************************************
*
* Here, Write the string at A0, which is null terminated.
*
***************************************************************************
ok_print:
	move.l	A0,D2			; Set pointer in D2 for Write arg
	moveq.l	#-1,D3
llx:	addq.l	#1,D3			; Get length in D3
	tst.b	(A0)+
	 bne.s	llx

	jsr	_LVOOutput(A6)		; Get Output handle
	move.l	D0,D1			; It's a calling arg
	jsr	_LVOWrite(A6)		; Echo "String"

finished:
	move.l	A6,A1
	move.l	4,A6			; AbsExecBase
	jsr	_LVOCloseLibrary(A6)

	moveq	#0,D0			; Exit(0)
	unlk	A5
	rts


***************************************************************************
*
* Following is just constant data used by the prgram
*
***************************************************************************

divtab:		dc.l	10000000,1000000,100000,10000,1000,100,10,1,0

DOSName:	dc.b	'dos.library',0

str_too_small:	dc.b	'suggested stack size too small',$0a,0
bad_str:	dc.b	'Bad command line. Use "stack #"',$0a,0

SStr:		dc.b	'current stack size is ',0
ZStr:		dc.b	' bytes',$0a,0

	END
