gno/bin/gsh/sv.asm

564 lines
8.1 KiB
NASM

**************************************************************************
*
* The GNO Shell Project
*
* Developed by:
* Jawaid Bazyar
* Tim Meekins
*
* $Id: sv.asm,v 1.7 1998/12/31 18:29:14 tribby Exp $
*
**************************************************************************
*
* SV.ASM
* By Tim Meekins
* Modified by Dave Tribby for GNO 2.0.6
*
* String Vector routines.
*
* Note: text set up for tabs at col 16, 22, 41, 49, 57, 65
* | | | | | |
* ^ ^ ^ ^ ^ ^
**************************************************************************
*
* Interfaces defined in this file:
*
* sv_alloc subroutine (2:size)
* return 4:ptr
*
* sv_add subroutine (4:vect,4:string,2:allocflag)
*
* sv_dispose subroutine (4:vect)
*
* sv_colprint subroutine (4:sv)
*
* sv_sort subroutine (4:sv)
*
* _qsort subroutine (4:sv,2:left,2:right)
*
**************************************************************************
mcopy /obj/gno/bin/gsh/sv.mac
dummysv start ; ends up in .root
end
setcom 60
**************************************************************************
*
* Allocate a string vector array
*
**************************************************************************
sv_alloc START
ptr equ 0
space equ ptr+4
subroutine (2:size),space
lda size
inc a ;for size and count
inc a ;at least one null entry
asl a Multiply by 4 (bytes/entry).
asl a
pea 0
pha
~NEW Allocate the memory
sta ptr and save address in
stx ptr+2 direct page variable.
ldy #2 Store number of entries
lda size as the value of the
sta [ptr],y first entry's high byte
lda #0 and zero as the low byte.
sta [ptr]
ldy #4 Set Y to index to 2nd entry.
ldx size X = num of entries following.
init sta [ptr],y Set all entries
iny2 to 0x00000000.
sta [ptr],y
iny2
dex
bpl init ;not bne so that extra null at end
add4 ptr,#4,ptr Set ptr to point at second entry.
return 4:ptr
END
**************************************************************************
*
* Add a string to the string vector
*
**************************************************************************
sv_add START
p equ 0
base equ p+4
space equ base+4
subroutine (4:vect,4:string,2:allocflag),space
sub4 vect,#4,base base points to entry # 0.
ldy #2
lda [base],y If number of entries in table
cmp [base] == number in use,
beq exit the vector is full!
;
; 1 = allocate memory, 0 = use string as is...
;
lda allocflag If "allocate memory" flag is set,
beq asis
pei (string+2) Determine length of
pei (string) new string.
jsr cstrlen
inc a
pea 0
pha
~NEW Allocate memory for it.
sta p Store address in p/p+1.
stx p+2
pei (string+2) Copy the string into
pei (string) the new memory.
phx
pha
jsr copycstr
bra doit else
asis mv4 string,p Just copy address to p/p+1.
;
; p contains address of string to be added to the vector.
;
doit lda [base]
tax X = number of entries in use.
asl a
asl a
tay Y = offset to next avail entry.
lda p Set entry to address of added string.
sta [vect],y
iny2
lda p+2
sta [vect],y
txa
inc a
sta [base] Bump the number of entries in use.
exit return
END
**************************************************************************
*
* Dispose a string vector
*
**************************************************************************
sv_dispose START
p equ 0
space equ p+4
subroutine (4:vect),space
sub4 vect,#4,p p points to head of vector
lda [p] Get number of entries in use.
beq done Done if zero.
loop asl a
asl a
tay Y points to last used entry.
lda [vect],y
tax
iny2
lda [vect],y
pha
phx
jsl nullfree Free memory used by this entry.
lda [p]
dec a
sta [p] Number used = number used - 1.
bne loop If more to do, stay in loop.
done pei (p+2) Free the vector itself.
pei (p)
jsl nullfree
return
END
**************************************************************************
*
* Column print a string vector
*
**************************************************************************
sv_colprint START
numrow equ 0
numcol equ numrow+2
base equ numcol+2
maxlen equ base+4
space equ maxlen+2
subroutine (4:sv),space
sub4 sv,#4,base base = ptr to entry 0.
;
; Find the maximum string length
;
lda #1
sta maxlen
lda #0 Keep track of entry number in Acc.
lenloop pha
asl a
asl a
tay Y = offset to entry number.
lda [sv],y
tax
iny2
lda [sv],y
pha
phx
jsr cstrlen Get length of entry's string.
cmp maxlen If > maxlen,
bcc nextlen
sta maxlen set maxlen to this length.
nextlen pla
inc a Bump entry number.
cmp [base] If not done,
bcc lenloop stay in loop.
;
; add one for a space
;
inc maxlen
;
; calculate the number of columns....this is probably simpler than doing
; a divide..
;
ldx #0
lda maxlen
clc
colloop inx
adc maxlen
cmp #80
bcc colloop
cpx #6+1 Make sure there
bcc okcol are no more
ldx #6 than 6 columns.
okcol stx numcol
lda [base]
cmp numcol Ensure number of columns
bcs okcol2 <= number of entries
tax
stx numcol
okcol2 anop
;
; recalculate the width based upon columns/80
;
UDivide (#80,@x),(maxlen,@a)
;
; calculate the height
;
lda [base]
UDivide (@a,numcol),(numrow,@x)
cpx #0
beq foocol
inc numrow
foocol anop
;
; find the index for each column...
;
lock offtblmutex
lda #0
tax
clc
mkidxloop sta offtbl,x
inx2
adc numrow
cmp [base]
bcc mkidxloop
stx numcol Double numcol since it's compared
ldx #0 against X to end the loop.
;
; Ready to print...
;
printloop lda offtbl,x
cmp [base]
bcs nextprint0
inc a
sta offtbl,x
phx
dec a
asl a
asl a
tay
lda [sv],y
tax
iny2
lda [sv],y
pha
phx
tax
lda 1,s
jsr puts
jsr cstrlen
tabit cmp maxlen
bcs nextprint
pha
lda #' '
jsr putchar
pla
inc a
bra tabit
nextprint plx
inx2
cpx numcol
bcc printloop
nextprint0 jsr newline
ldx #0
dec numrow
bne printloop
unlock offtblmutex
return
;
; Offset table: one entry for each column
;
offtbl ds 14
offtblmutex key
END
**************************************************************************
*
* Sort a string vector
*
**************************************************************************
sv_sort START
space equ 0
subroutine (4:sv),space
pei (sv+2)
pei (sv)
sub4 sv,#4,sv
pea 0
lda [sv]
dec a
pha
jsl _qsort
return
END
**************************************************************************
_qsort PRIVATE
vleft equ 0
i equ vleft+4
last equ i+2
ptr2 equ last+2
ptr1 equ ptr2+4
idx1 equ ptr1+4
space equ idx1+2
subroutine (4:sv,2:left,2:right),space
;
; if (left >= right)
; return;
;
lda right ;if one or two elements do nothing
jmi exit
cmp left
jcc exit
;
; swap(v, left, (left + right)/2);
;
lda left
asl a
asl a
sta idx1
tay
lda [sv],y
sta ptr1
iny2
lda [sv],y
sta ptr1+2
add2 left,right,@a
lsr a
asl a
asl a
tay
lda [sv],y
sta ptr2
lda ptr1
sta [sv],y
iny2
lda [sv],y
sta ptr2+2
lda ptr1+2
sta [sv],y
ldy idx1
lda ptr2
sta [sv],y
iny2
lda ptr2+2
sta [sv],y
;
; last = left;
;
lda left
sta last
asl a
asl a
tay
lda [sv],y
sta vleft
iny2
lda [sv],y
sta vleft+2
;
; for (i=left+1; i <=right; i++)
;
lda left
inc a
sta i
forloop lda i
cmp right
beq okloop
bcs endloop
okloop anop
;
; if (strcmp(v[i],v[left]) < 0)
;
asl a
asl a
tay
lda [sv],y
tax
iny2
lda [sv],y
pha
phx
pei (vleft+2)
pei (vleft)
jsr cmpcstr
bpl nextloop
;
; swap (v, ++last, i)
;
inc last
lda last
asl a
asl a
sta idx1
tay
lda [sv],y
sta ptr1
iny2
lda [sv],y
sta ptr1+2
lda i
asl a
asl a
tay
lda [sv],y
sta ptr2
lda ptr1
sta [sv],y
iny2
lda [sv],y
sta ptr2+2
lda ptr1+2
sta [sv],y
ldy idx1
lda ptr2
sta [sv],y
iny2
lda ptr2+2
sta [sv],y
nextloop inc i
jmp forloop
;
; swap(v, left, last)
;
endloop lda left
asl a
asl a
sta idx1
tay
lda [sv],y
sta ptr1
iny2
lda [sv],y
sta ptr1+2
lda last
asl a
asl a
tay
lda [sv],y
sta ptr2
lda ptr1
sta [sv],y
iny2
lda [sv],y
sta ptr2+2
lda ptr1+2
sta [sv],y
ldy idx1
lda ptr2
sta [sv],y
iny2
lda ptr2+2
sta [sv],y
;
; qsort(v, left, last-1)
;
pei (sv+2)
pei (sv)
pei (left)
lda last
dec a
pha
jsl _qsort
;
; qsort(v, last+1, right)
;
pei (sv+2)
pei (sv)
lda last
inc a
pha
pei (right)
jsl _qsort
exit return
END