**************************************************************************
*
* The GNO Shell Project
*
* Developed by:
*   Jawaid Bazyar
*   Tim Meekins
*
* $Id: alias.asm,v 1.8 1998/12/31 18:29:11 tribby Exp $
*
**************************************************************************
*
* ALIAS.ASM
*   By Tim Meekins
*   Modified by Dave Tribby for GNO 2.0.6
*
* Note: text set up for tabs at col 16, 22, 41, 49, 57, 65
*              |     |                  |       |       |       |
*	^	^	^	^	^	^	
**************************************************************************
*
* Interfaces defined in this file:
*
* alias	subroutine (4:argv,2:argc)
*	Returns with status=0 in Accumulator
*
* unalias	subroutine (4:argv,2:argc)
*	return 2:status
*			 
* initalias	jsr/rts with no parameters
*
* expandalias	subroutine (4:cmd)
*	return 4:buf
*
* addalias	subroutine (4:aliasname,4:aliasval)
*	return
*
* removealias	subroutine (4:aliasname)
*	return
*		                  
* findalias	subroutine (4:aliasname),space
*	return 4:value
*
* startalias	jsl/rtl with no parameters
*
* nextalias	subroutine (4:p)
*	return 2:hashvalz
*
*
**************************************************************************

	mcopy	/obj/gno/bin/gsh/alias.mac

dummyalias	start		; ends up in root
	end

	setcom 60

VTABSIZE	gequ	17

**************************************************************************
*
* ALIAS: builtin command
* syntax: alias [name [def]]
*
* set aliases
*
**************************************************************************

alias	START

	using	AliasData

arg	equ	1
space	equ	arg+4
argc	equ	space+3
argv	equ	argc+2
end	equ	argv+4	

;	 subroutine (4:argv,2:argc),space

	tsc
	sec
	sbc	#space-1
	tcs
	phd
	tcd

	lock	AliasMutex
	lda	argc	How many arguments were provided?
	dec	a
	beq	showall	None -- show all alias names.
	dec	a
	beq	showone	One -- show a single name.
	jmp	setalias	More -- set an alias.

;
; Show all aliases
;
showall	jsl	startalias
showloop	jsl	nextalias
	sta	arg
	stx	arg+2
	ora	arg+2
	beq	noshow
	ldy	#6
	lda	[arg],y
	tax
	ldy	#4
	lda	[arg],y
	jsr	puts
	lda	#':'
	jsr	putchar
	lda	#' '
	jsr	putchar
	ldy	#10
	lda	[arg],y
	tax
	ldy	#8
	lda	[arg],y
	jsr	puts
	jsr	newline
	bra	showloop	
    
noshow	jmp	exit

;
; Show a single alias
;
showone	ldy	#4+2
	lda	[argv],y
	tax
	pha		;for findalias
	ldy	#4	
	lda	[argv],y
	pha
	jsr	puts	Print name.
	lda	#':'	Print ": ".
	jsr	putchar
	lda	#' '
	jsr	putchar
	jsl	findalias
	sta	arg
	stx	arg+2
	ora	arg+2
	beq	notthere
	lda	arg
	jsr	puts	Print alias value.
	jsr	newline	Print newline.
	jmp	exit	All done.

notthere	ldx	#^noalias	Print message:
	lda	#noalias	 'Alias not defined'
	jsr	puts
	jmp	exit

;
; Set an alias name
;
setalias	ldy	#4+2	;put alias name on stack
	lda	[argv],y
	pha
	ldy	#4
	lda	[argv],y
	pha

	ph4	#2
	~NEW
	sta	arg
	stx	arg+2
	lda	#0
	sta	[arg]

	add2	argv,#8,argv

	dec2	argc

buildalias	lda	argc
	beq	setit

	pei	(arg+2)
	pei	(arg)
	pei	(arg+2)
	pei	(arg)
	ldy	#2
	lda	[argv],y
	pha
	lda	[argv]
	pha
	jsr	catcstr
	stx	arg+2
	sta	arg
	jsl	nullfree

	pei	(arg+2)
	pei	(arg)
	pei	(arg+2)
	pei	(arg)
	ph4	#spacestr
	jsr	catcstr
	stx	arg+2
	sta	arg
	jsl	nullfree

	dec	argc
	add2	argv,#4,argv
	bra	buildalias

setit	pei	(arg+2)
	pei	(arg)
	jsl	addalias
	pei	(arg+2)
	pei	(arg)
	jsl	nullfree

exit	unlock AliasMutex
	lda	space
	sta	end-3
	lda	space+1
	sta	end-2
	pld
	tsc
	clc
	adc	#end-4
	tcs

	lda	#0	Return status always 0.

	rtl

noalias	dc	c'Alias not defined',h'0d00'
spacestr	dc	c' ',h'00'

	END

**************************************************************************
*
* UNALIAS: builtin command
* syntax: unalias [var ...]
*
* removes each alias listed
*
**************************************************************************

unalias	START

	using	AliasData

status	equ	0
space	equ	status+2

	subroutine (4:argv,2:argc),space

	lock	AliasMutex

	stz	status

	lda	argc
	dec	a
	bne	loop

	ldx	#^Usage
	lda	#USage
	jsr	errputs
	inc	status	Return status = 1.
	bra	done

loop	add2	argv,#4,argv
	dec	argc
	beq	done

	ldy	#2
	lda	[argv],y
	pha
	lda	[argv]
	pha
	jsl	removealias

	bra	loop

done	unlock AliasMutex
	return 2:status

Usage	dc	c'Usage: unalias name ...',h'0d00'

	END

;=========================================================================
;
; Init alias table
;
;=========================================================================

initalias	START

	using	AliasData

; Set all entries in AliasTable to 0

	lda	#0
	ldy	#VTABSIZE
	tax
yahaha	sta	AliasTable,x
	inx2
	sta	AliasTable,x
	inx2
	dey	
	bne	yahaha

	rts

	END		 

;=========================================================================
;
; Expand alias
;
;=========================================================================

expandalias	START
	
outbuf	equ	0
sub	equ	outbuf+4
word	equ	sub+4
buf	equ	word+4
space	equ	buf+4
	
	subroutine (4:cmd),space

	ph4	#1024
	~NEW
	stx	buf+2
	sta	buf
	stx	outbuf+2
	sta	outbuf
	jsl	alloc1024
	stx	word+2
	sta	word
	lda	#0
	sta	[buf]	In case we're called with empty string
	sta	[word]
;
; eat leading spaces
;
eatleader	lda	[cmd]
	and	#$FF
	jeq	done
	cmp	#' '
	bne	getword
	inc	cmd
	sta	[outbuf]
	inc	outbuf
	bra	eatleader
;
; find the leading word
;
getword	short	a
	ldy	#0
makeword	lda	[cmd],y
	if2	@a,eq,#0,gotword
	if2	@a,eq,#' ',gotword
	if2	@a,eq,#';',gotword
	if2	@a,eq,#'&',gotword
	if2	@a,eq,#'|',gotword
	if2	@a,eq,#'>',gotword
	if2	@a,eq,#'<',gotword
	if2	@a,eq,#13,gotword
	if2	@a,eq,#9,gotword
	if2	@a,eq,#10,gotword
	sta	[word],y
	iny
	bra	makeword
;
; we got a word, now check if it's an alias
;
gotword	lda	#0
	sta	[word],y	
	long	a
	add2	@y,cmd,cmd
	phy
	pei	(word+2)
	pei	(word)
	jsl	findalias
	sta	sub
	stx	sub+2
	ora	sub+2
	beq	noalias
;
; expand it, if you hadn't figured it out for yourself by now.
;
	pla
	ldy	#0
putalias	lda	[sub],y
	and	#$FF
	beq	next
	sta	[outbuf]
	inc	outbuf
	iny
	bra	putalias
;
; no alias, so just copy the original string
;
noalias	plx
	beq	next
	ldy	#0
noalias2	lda	[word],y
	sta	[outbuf]
	inc	outbuf
	iny
	dex
	bne	noalias2
;
; the alias is expanded, now copy until we reach the next command
;
next	lda	[cmd]
	inc	cmd
	sta	[outbuf]
	inc	outbuf
	and	#$FF
	beq	done
	if2	@a,eq,#13,nextalias
	if2	@a,eq,#';',nextalias
	if2	@a,eq,#'&',nextalias
	if2	@a,eq,#'|',nextalias
	if2	@a,eq,#'\',backstabber
	if2	@a,eq,#"'",singquoter
	if2	@a,eq,#'"',doubquoter
	bra	next
;
; "\" found
;
backstabber	lda	[cmd]
	inc	cmd
	sta	[outbuf]
	inc	outbuf
	and	#$FF
	beq	done
	bra	next
;
; "'" found
;
singquoter	lda	[cmd]
	inc	cmd
	sta	[outbuf]
	inc	outbuf
	and	#$FF
	beq	done
	if2	@a,ne,#"'",singquoter
	bra	next
;
; '"' found
;
doubquoter	lda	[cmd]
	inc	cmd
	sta	[outbuf]
	inc	outbuf
	and	#$FF
	beq	done
	if2	@a,ne,#'"',doubquoter
	bra	next

;
; ";", "|", or "&" found: it's another command
;
nextalias	jmp	eatleader

done	ldx	word+2
	lda	word
	jsl	free1024

	return 4:buf

	END

;=========================================================================
;
; Add alias to table
;
;=========================================================================

addalias	START
	
	using	AliasData

tmp	equ	0
ptr	equ	tmp+4
hashval	equ	ptr+4
space	equ	hashval+4

	subroutine (4:aliasname,4:aliasval),space

	pei	(aliasname+2)
	pei	(aliasname)
	jsl	hashalias
	sta	hashval
	
	tax	
	lda	AliasTable,x
	sta	ptr
	lda	AliasTable+2,x
	sta	ptr+2

search	lda	ptr
	ora	ptr+2
	beq	notfound
	ldy	#4
	lda	[ptr],y
	tax
	ldy	#4+2
	lda	[ptr],y
	pha
	phx
	pei	(aliasname+2)
	pei	(aliasname)
	jsr	cmpcstr
	jeq	replace
	ldy	#2
	lda	[ptr]
	tax
	lda	[ptr],y
	sta	ptr+2
	stx	ptr
	bra	search

replace	ldy	#8+2
	lda	[ptr],y
	pha	
	ldy	#8
	lda	[ptr],y
	pha
	jsl	nullfree
	pei	(aliasval+2)
	pei	(aliasval)
	jsr	cstrlen
	inc	a
	pea	0
	pha
	~NEW
	sta	tmp
	stx	tmp+2
	ldy	#8
	sta	[ptr],y
	ldy	#8+2
	txa
	sta	[ptr],y
	pei	(aliasval+2)
	pei	(aliasval)
	pei	(tmp+2)
	pei	(tmp)
	jsr	copycstr
	jmp	done

notfound	ph4	#4*3
	~NEW
	sta	ptr
	stx	ptr+2
	ldy	#2
	ldx	hashval
	lda	AliasTable,x
	sta	[ptr]
	lda	AliasTable+2,x
	sta	[ptr],y
	pei	(aliasname+2)
	pei	(aliasname)
	jsr	cstrlen
	inc	a
	pea	0
	pha
	~NEW
	sta	tmp
	stx	tmp+2
	ldy	#4
	sta	[ptr],y
	ldy	#4+2
	txa
	sta	[ptr],y
	pei	(aliasname+2)
	pei	(aliasname)
	pei	(tmp+2)
	pei	(tmp)
	jsr	copycstr
	pei	(aliasval+2)
	pei	(aliasval)
	jsr	cstrlen
	inc	a
	pea	0
	pha
	~NEW
	sta	tmp
	stx	tmp+2
	ldy	#8
	sta	[ptr],y
	ldy	#8+2
	txa
	sta	[ptr],y
	pei	(aliasval+2)
	pei	(aliasval)
	pei	(tmp+2)
	pei	(tmp)
	jsr	copycstr
	ldx	hashval
	lda	ptr
	sta	AliasTable,x
	lda	ptr+2
	sta	AliasTable+2,x
		        
done	return

	END

;=========================================================================
;
; Remove an alias
;
;=========================================================================

removealias	START

	using	AliasData

oldptr	equ	0
ptr	equ	oldptr+4
space	equ	ptr+4

	subroutine (4:aliasname),space

	pei	(aliasname+2)
	pei	(aliasname)
	jsl	hashalias
	tax
	lda	AliasTable,x
	sta	ptr
	lda	AliasTable+2,x
	sta	ptr+2
	lda	#^Aliastable
	sta	oldptr+2
	clc
	txa
	adc	#AliasTable
	sta	oldptr

searchloop	ora2	ptr,ptr+2,@a
	beq	done

	ldy	#4+2
	lda	[ptr],y
	pha
	ldy	#4
	lda	[ptr],y
	pha
	pei	(aliasname+2)
	pei	(aliasname)
	jsr	cmpcstr
	beq	foundit
	mv4	ptr,oldptr
	ldy	#2
	lda	[ptr],y
	tax
	lda	[ptr]
	sta	ptr
	stx	ptr+2
	bra	searchloop

foundit	ldy	#2
	lda	[ptr],y
	sta	[oldptr],y
	lda	[ptr]
	sta	[oldptr]
	ldy	#4+2
	lda	[ptr],y
	pha
	ldy	#4
	lda	[ptr],y
	pha
	jsl	nullfree
	ldy	#8+2
	lda	[ptr],y
	pha
	ldy	#8
	lda	[ptr],y
	pha
	jsl	nullfree
	pei	(ptr+2)
	pei	(ptr)
	jsl	nullfree
		        
done	return

	END

;=========================================================================
;
; Find an alias
;
;=========================================================================

findalias	START

	using	AliasData

ptr	equ	0
value	equ	ptr+4
space	equ	value+4

	subroutine (4:aliasname),space

	stz	value
	stz	value+2

	pei	(aliasname+2)
	pei	(aliasname)
	jsl	hashalias
	tax
	lda	AliasTable,x
	sta	ptr
	lda	AliasTable+2,x
	sta	ptr+2

searchloop	ora2	ptr,ptr+2,@a
	beq	done

	ldy	#4+2
	lda	[ptr],y
	pha
	ldy	#4
	lda	[ptr],y
	pha
	pei	(aliasname+2)
	pei	(aliasname)
	jsr	cmpcstr
	beq	foundit
	ldy	#2
	lda	[ptr],y
	tax
	lda	[ptr]
	sta	ptr
	stx	ptr+2
	bra	searchloop

foundit	ldy	#8
	lda	[ptr],y
	sta	value
	ldy	#8+2
	lda	[ptr],y
	sta	value+2

done	return 4:value

	END

;=========================================================================
;
; Start alias
;
;=========================================================================

startalias	START

	using	AliasData

	stz	AliasNum
	mv4	AliasTable,AliasPtr
	rtl

	END

;=========================================================================
;
; Next alias
;
;=========================================================================

nextalias	START

	using	AliasData

value	equ	0
space	equ	value+4

	subroutine (0:fubar),space

	stz	value
	stz	value+2
puke	if2	AliasNum,cs,#VTABSIZE,done

	ora2	AliasPtr,AliasPtr+2,@a
	bne	flush
	inc	AliasNum
	lda	AliasNum
	asl2	a
	tax
	lda	AliasTable,x
	sta	AliasPtr
	lda	AliasTable+2,x
	sta	AliasPtr+2
	bra	puke

flush	mv4	AliasPtr,value
	ldy	#2
	lda	[value]
	sta	AliasPtr
	lda	[value],y
	sta	AliasPtr+2	

done	return 4:value

	END

;=========================================================================
;
; Hash an alias
;
;=========================================================================

hashalias	PRIVATE

hashval	equ	0
space	equ	hashval+2

	subroutine (4:p),space
		               
	lda	#11
	sta	hashval

	ldy	#0
loop	asl	hashval
	lda	[p],y
	and	#$FF
	beq	done
	clc
	adc	hashval
	sta	hashval
	iny
	bra	loop
done	UDivide (hashval,#VTABSIZE),(@a,@a)

	asl2	a	;Make it an index.
	sta	hashval

	return 2:hashval

	END

;=========================================================================
;
; Alias data
;
;=========================================================================

AliasData	DATA

AliasNum	dc	i2'0'
AliasPtr	dc	i4'0'
AliasMutex	key

AliasTable	ds	VTABSIZE*4

	END	               
