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