gno/bin/gsh/alias.asm
tribby 6269a8ca25 Changes for gsh version 2.0d8:
Fixed several mutual exclusion problems, including a particularly nasty
one that would cause gsh to loop forever inside the memory manager. (You
could identify this one by the "BRA (-23)" at the bottom of the infinite
loop.)

Fixed the string vector print routine to properly handle all numbers of
entries in the hash table.  Previously, it would always print duplicate
entries if there were < 6 commands hashed, and would sometimes print
duplicates (depending on previous contents of an internal table) for
other numbers of commands.

gsh would wait on background processes started from an exec file
(executed, not sourced). Now the exec file does not wait on the process,
but the background process is not associated with the parent shell after
the exec file terminates.

Made gsh globbing work more like csh: if none of the requested patterns
are found, print "No match" and exit.

At startup, if /etc/glogin, $HOME/glogin, or $HOME/gshrc does not exist,
don't report a "file not found" error message. (PR#100)
1998-12-31 18:29:14 +00:00

859 lines
12 KiB
NASM

**************************************************************************
*
* 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