mirror of https://github.com/GnoConsortium/gno.git
687 lines
11 KiB
NASM
687 lines
11 KiB
NASM
**************************************************************************
|
|
*
|
|
* The GNO Shell Project
|
|
*
|
|
* Developed by:
|
|
* Jawaid Bazyar
|
|
* Tim Meekins
|
|
*
|
|
* $Id: shellutil.asm,v 1.8 1998/12/31 18:29:14 tribby Exp $
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* SHELLUTIL.ASM
|
|
* By Tim Meekins
|
|
* Modified by Dave Tribby for GNO 2.0.6
|
|
*
|
|
* Utility functions used by the shell. Mainly string functions.
|
|
*
|
|
* Note: text set up for tabs at col 16, 22, 41, 49, 57, 65
|
|
* | | | | | |
|
|
* ^ ^ ^ ^ ^ ^
|
|
**************************************************************************
|
|
*
|
|
* Interfaces defined in this file:
|
|
*
|
|
* tolower Convert the accumulator to lower case
|
|
* {accumulator = character}
|
|
* jsr tolower
|
|
* {if acc was uppercase it's now lowercase; else no change}
|
|
*
|
|
* toslash Convert ':' to '/'
|
|
* {accumulator = character}
|
|
* jsr toslash
|
|
* {if acc was ':', it's now '/'; otherwise no change}
|
|
*
|
|
* lowercstr Convert a c string to lower case
|
|
* {push address of c string on stack}
|
|
* jsr lowercstr
|
|
*
|
|
* cstrlen Get the length of a c string
|
|
* {push address of c string on stack}
|
|
* jsr cstrlen
|
|
* {return with len of string in acc}
|
|
*
|
|
* copycstr Copy one string to another. Assumes an alloccstr has been
|
|
* performed on destination.
|
|
*
|
|
* cmpcstr Compare two c strings. Return 0 if equal, -1 if less than,
|
|
* +1 if greater
|
|
*
|
|
* cmpdcstr Compare two downshifted c strings. Return 0 if equal,
|
|
* -1 if less than, +1 if greater
|
|
*
|
|
* c2gsstr Allocate memory, then convert a c string to a GS/OS string
|
|
* (caller must dispose when done)
|
|
*
|
|
* catcstr Takes two strings, concats into a newly created string.
|
|
*
|
|
* nullfree Call ~DISPOSE if pointer is not NULL
|
|
*
|
|
* newlineX Print a carriage return and a newline, unless "newline" shell
|
|
* var is set.
|
|
*
|
|
* getenv Get value of indicated environment variable; pass in addr of a
|
|
* GS/OS string, and pass back addr of allocated GS/OS result
|
|
* buffer (with null byte added at end).
|
|
* subroutine (4:var)
|
|
* return 4:ptr
|
|
*
|
|
* rmemcpy
|
|
* subroutine (2:num,4:src,4:dest)
|
|
*
|
|
**************************************************************************
|
|
|
|
mcopy /obj/gno/bin/gsh/shellutil.mac
|
|
|
|
dummyshellutil start ; ends up in .root
|
|
end
|
|
|
|
setcom 60
|
|
|
|
;=========================================================================
|
|
;
|
|
; Convert the accumulator to lower case.
|
|
;
|
|
;=========================================================================
|
|
|
|
tolower START
|
|
|
|
cmp #'A'
|
|
bcc done
|
|
cmp #'Z'+1
|
|
bcs done
|
|
adc #'a'-'A'
|
|
done rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Convert ':' to '/'
|
|
;
|
|
;=========================================================================
|
|
|
|
toslash START
|
|
|
|
cmp #':'
|
|
bne done
|
|
lda #'/'
|
|
done rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Convert a c string to lower case
|
|
;
|
|
;=========================================================================
|
|
|
|
lowercstr START
|
|
|
|
space equ 1
|
|
p equ space+2
|
|
end equ p+4
|
|
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
short a
|
|
|
|
ldy #-1
|
|
loop iny
|
|
lda [p],y
|
|
beq done
|
|
cmp #'A'
|
|
bcc loop
|
|
cmp #'Z'+1
|
|
bcs loop
|
|
adc #'a'-'A'
|
|
sta [p],y
|
|
bra loop
|
|
|
|
done rep #$21
|
|
longa on
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
adc #end-3
|
|
tcs
|
|
|
|
rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Get the length of a c string.
|
|
;
|
|
;=========================================================================
|
|
|
|
cstrlen START
|
|
|
|
space equ 1
|
|
p equ space+2
|
|
end equ p+4
|
|
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
short a
|
|
|
|
ldy #0
|
|
loop lda [p],y
|
|
beq done
|
|
iny
|
|
bra loop
|
|
|
|
done rep #$21
|
|
longa on
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
adc #end-3
|
|
tcs
|
|
|
|
tya
|
|
|
|
rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Copy one string to another. Assumes an alloccstr has been performed on
|
|
; destination.
|
|
;
|
|
;=========================================================================
|
|
|
|
copycstr START
|
|
|
|
space equ 1
|
|
q equ space+2
|
|
p equ q+4
|
|
end equ p+4
|
|
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
short a
|
|
|
|
ldy #0
|
|
loop lda [p],y
|
|
beq done
|
|
sta [q],y
|
|
iny
|
|
bra loop
|
|
|
|
done sta [q],y
|
|
|
|
rep #$21
|
|
longa on
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
adc #end-3
|
|
tcs
|
|
|
|
rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Compare two c strings. Return 0 if equal, -1 if less than, +1 greater
|
|
;
|
|
;=========================================================================
|
|
|
|
cmpcstr START
|
|
|
|
space equ 1
|
|
q equ space+2
|
|
p equ q+4
|
|
end equ p+4
|
|
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
short a
|
|
|
|
ldx #0
|
|
|
|
ldy #0
|
|
strloop lda [p],y
|
|
beq strchk
|
|
cmp [q],y
|
|
bne notequal
|
|
iny
|
|
bra strloop
|
|
|
|
strchk lda [q],y
|
|
beq done
|
|
|
|
lessthan dex
|
|
bra done
|
|
|
|
notequal bcc lessthan
|
|
inx
|
|
|
|
done rep #$21
|
|
longa on
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
adc #end-3
|
|
tcs
|
|
|
|
txa
|
|
rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Compare two downshifted c strings. Return 0 if ==, -1 if <, +1 >
|
|
;
|
|
;=========================================================================
|
|
|
|
cmpdcstr START
|
|
|
|
hold equ 1
|
|
space equ hold+2
|
|
q equ space+2
|
|
p equ q+4
|
|
end equ p+4
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
ldx #0
|
|
|
|
ldy #0
|
|
strloop lda [q],y
|
|
and #$FF
|
|
jsr tolower
|
|
sta hold
|
|
lda [p],y
|
|
and #$FF
|
|
beq strchk
|
|
jsr tolower
|
|
cmp hold
|
|
bne notequal
|
|
iny
|
|
bra strloop
|
|
|
|
strchk lda hold
|
|
beq done
|
|
|
|
lessthan dex
|
|
bra done
|
|
|
|
notequal bcc lessthan
|
|
inx
|
|
|
|
done anop
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-3
|
|
tcs
|
|
|
|
txa
|
|
rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Convert a c string to a GS/OS string (don't forget to dispose when done)
|
|
;
|
|
;=========================================================================
|
|
|
|
c2gsstr START
|
|
|
|
len equ 1
|
|
gstr equ len+2
|
|
space equ gstr+4
|
|
cstr equ space+2
|
|
end equ cstr+4
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
pei (cstr+2)
|
|
pei (cstr)
|
|
jsr cstrlen
|
|
sta len
|
|
adc #3
|
|
pea 0
|
|
pha
|
|
~NEW
|
|
sta gstr
|
|
stx gstr+2
|
|
incad @xa
|
|
incad @xa
|
|
pei (cstr+2)
|
|
pei (cstr)
|
|
phx
|
|
pha
|
|
jsr copycstr
|
|
lda len
|
|
sta [gstr]
|
|
|
|
ldx gstr+2
|
|
ldy gstr
|
|
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
adc #end-3
|
|
tcs
|
|
|
|
tya
|
|
rts
|
|
|
|
END
|
|
|
|
;=========================================================================
|
|
;
|
|
; Takes two strings, concats into a newly created string.
|
|
;
|
|
;=========================================================================
|
|
|
|
catcstr START
|
|
|
|
new equ 1
|
|
space equ new+4
|
|
q equ space+2
|
|
p equ q+4
|
|
end equ p+4
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
pei (p+2)
|
|
pei (p)
|
|
jsr cstrlen
|
|
pha
|
|
pei (q+2)
|
|
pei (q)
|
|
jsr cstrlen
|
|
adc 1,s
|
|
inc a
|
|
inc a
|
|
plx
|
|
pea 0
|
|
pha
|
|
~NEW
|
|
sta new
|
|
stx new+2
|
|
|
|
ldy #0
|
|
copy1 lda [p],y
|
|
and #$FF
|
|
beq copy2
|
|
sta [new],y
|
|
iny
|
|
bra copy1
|
|
copy2 lda [q]
|
|
and #$FF
|
|
sta [new],y
|
|
beq done
|
|
iny
|
|
incad q
|
|
bra copy2
|
|
|
|
done ldx new+2
|
|
ldy new
|
|
lda space
|
|
sta end-2
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-3
|
|
tcs
|
|
|
|
tya
|
|
rts
|
|
|
|
END
|
|
|
|
;=====================================================================
|
|
;
|
|
; call ~DISPOSE if pointer is not NULL
|
|
;
|
|
;=====================================================================
|
|
|
|
nullfree START
|
|
|
|
lda 4,s Hold address
|
|
tay parameter in
|
|
lda 6,s X and Y registers.
|
|
tax
|
|
lda 2,s Move return
|
|
sta 6,s address on
|
|
lda 1,s the stack.
|
|
sta 5,s
|
|
tya Put address
|
|
sta 1,s parameter back
|
|
txa on the stack.
|
|
sta 3,s
|
|
|
|
ora 1,s If address is NULL,
|
|
bne ok
|
|
plx clean up stack
|
|
plx
|
|
rtl and return to caller.
|
|
|
|
ok ~DISPOSE NOTE: macro locks/unlocks mem mutex
|
|
|
|
rtl
|
|
|
|
END
|
|
|
|
;=====================================================================
|
|
;
|
|
; Data area that holds memory manager mutual exclusion key,
|
|
; which is referenced in the ~NEW and ~DISPOSE macros
|
|
;
|
|
;=====================================================================
|
|
memglobal DATA
|
|
memmutex key
|
|
END
|
|
|
|
;=====================================================================
|
|
;
|
|
; Print a carriage return and a newline, unless "newline" shell var
|
|
; is set.
|
|
;
|
|
;=====================================================================
|
|
|
|
newlineX START
|
|
|
|
using vardata
|
|
|
|
lda varnewline
|
|
beq newline
|
|
rts
|
|
|
|
;=====================================================================
|
|
;
|
|
; Print a carriage return and a newline
|
|
;
|
|
;=====================================================================
|
|
|
|
newline ENTRY
|
|
|
|
lda #13
|
|
jmp putchar
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* Quick little routine for reading variables and converting to
|
|
* null terminated strings. We could probably just link the Orca/C
|
|
* library getenv(), but lets stay Orca-free, after all, that's why this
|
|
* is written in assembly! :)
|
|
*
|
|
* For gsh 2.0: pass in addr of a GS/OS string, and pass back addr of
|
|
* allocated GS/OS result buffer (with null byte added at end), not c-strings.
|
|
*
|
|
**************************************************************************
|
|
|
|
getenv START
|
|
|
|
len equ 1
|
|
retval equ len+2
|
|
space equ retval+4
|
|
var equ space+3
|
|
end equ var+4
|
|
|
|
; subroutine (4:var),space
|
|
|
|
tsc
|
|
sec
|
|
sbc #space-1
|
|
tcs
|
|
phd
|
|
tcd
|
|
|
|
lock mutex
|
|
;
|
|
; Get the variable's length using ReadVariableGS
|
|
; Set up parameter block:
|
|
mv4 var,RVname Addr of name, from user.
|
|
ld4 TempResultBuf,RVresult Use temporary result buf.
|
|
ReadVariableGS ReadVar Get length.
|
|
;
|
|
; Allocate memory for value string
|
|
;
|
|
lda TempRBlen Get length of value.
|
|
bne notnull Return null if 0.
|
|
sta retval
|
|
sta retval+2
|
|
bra exit
|
|
|
|
notnull inc2 a Add 4 bytes for result buf len words.
|
|
inc2 a
|
|
sta len Save result buf len.
|
|
inc a Add 1 more for terminating null byte.
|
|
pea 0
|
|
pha
|
|
~NEW Request the memory.
|
|
sta RVresult Store address in ReadVariable
|
|
stx RVresult+2 parameter block and
|
|
sta retval direct page pointer.
|
|
stx retval+2
|
|
ora retval+2 If address == NULL,
|
|
beq exit return NULL to user.
|
|
|
|
lda len Store result buffer length
|
|
sta [retval] at beginning of buf.
|
|
;
|
|
; Read the full value into the allocated memory
|
|
;
|
|
ReadVariableGS ReadVar
|
|
;
|
|
; Add null byte at end of text to make it work as a C string
|
|
;
|
|
ldy TempRBlen Get length of value,
|
|
iny4 + 4 (for length words at start)
|
|
lda #0 Store zero at end of string.
|
|
short a
|
|
sta [retval],y
|
|
long a
|
|
;
|
|
; All done.
|
|
;
|
|
exit unlock mutex
|
|
|
|
ldy retval
|
|
ldx retval+2
|
|
|
|
lda space+1
|
|
sta end-2
|
|
lda space
|
|
sta end-3
|
|
pld
|
|
tsc
|
|
clc
|
|
adc #end-4
|
|
tcs
|
|
tya
|
|
|
|
rtl
|
|
|
|
mutex key
|
|
|
|
; Parameter block for shell ReadVariableGS call (p 423 in ORCA/M manual)
|
|
ReadVar anop
|
|
dc i2'3' pCount
|
|
RVname ds 4 Pointer to name (passed by user)
|
|
RVresult ds 4 GS/OS Output buffer ptr
|
|
RVexpflag ds 2 export flag
|
|
|
|
; GS/OS result buffer for getting the full length of the PATH env var.
|
|
TempResultBuf dc i2'5' Only five bytes total.
|
|
TempRBlen ds 2 Value's length returned here.
|
|
ds 1 Only 1 byte for value.
|
|
|
|
END
|
|
|
|
**************************************************************************
|
|
*
|
|
* Copy src bytes to destination address
|
|
*
|
|
**************************************************************************
|
|
|
|
rmemcpy START
|
|
subroutine (2:num,4:src,4:dest),0
|
|
|
|
ldy num Get length of src.
|
|
beq done Done if == 0.
|
|
tya
|
|
dey
|
|
bit #1
|
|
bne odd
|
|
dey
|
|
bra lp1
|
|
odd short m
|
|
lda [src],y
|
|
sta [dest],y
|
|
long m
|
|
dey
|
|
dey
|
|
bmi done
|
|
lp1 lda [src],y
|
|
sta [dest],y
|
|
dey
|
|
dey
|
|
bpl lp1
|
|
done return
|
|
END
|