Added environment routines

git-svn-id: svn://svn.cc65.org/cc65/trunk@3483 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2005-04-21 21:26:15 +00:00
parent 142636504f
commit e0319679f0
5 changed files with 362 additions and 0 deletions

View File

@ -79,6 +79,7 @@ C_OBJS = _afailed.o \
# From assembly source-files
S_OBJS = _cwd.o \
_environ.o \
_fdesc.o \
_file.o \
_fopen.o \
@ -112,6 +113,7 @@ S_OBJS = _cwd.o \
fwrite.o \
getcpu.o \
getcwd.o \
getenv.o \
isalnum.o \
isalpha.o \
isblank.o \
@ -140,11 +142,13 @@ S_OBJS = _cwd.o \
oserrcheck.o \
printf.o \
putchar.o \
putenv.o \
rand.o \
raise.o \
remove.o \
rename.o \
scanf.o \
searchenv.o \
setjmp.o \
signal.o \
sigtable.o \

30
libsrc/common/_environ.s Normal file
View File

@ -0,0 +1,30 @@
;
; Ullrich von Bassewitz, 2005-04-21
;
; extern char** _environ;
;
;
; __environ is a pointer to the environment.
; __envcount is the number of entries in the environment.
; __envsize is the size of the allocated array.
;
; The maximum number of environment entries is 64. putenv() will set errno
; to ENOMEM when trying to increase the number beyond this limit.
;
.export __environ, __envcount, __envsize
.import initenv
.constructor env_init
env_init := initenv
.bss
__environ:
.addr 0
__envcount:
.byte 0
__envsize:
.byte 0

46
libsrc/common/getenv.s Normal file
View File

@ -0,0 +1,46 @@
;
; Ullrich von Bassewitz, 2005-04-21
;
; char* __fastcall__ getenv (const char* name);
;
; Beware: putenv() knows about zero page usage in this module!
;
.export _getenv
.import __environ, __envcount
.import searchenv
.import return0
.import ptr1:zp, ptr3:zp, tmp1:zp
.code
;----------------------------------------------------------------------------
; getenv()
.proc _getenv
sta ptr1
stx ptr1+1 ; Save name
; Search for the string in the environment. searchenv will set the N flag if
; the string is not found, otherwise X contains the index of the entry, ptr3
; contains the entry and Y the offset of the '=' in the string.
jsr searchenv
bpl found
jmp return0 ; Not found, return NULL
; Found the entry. Calculate the pointer to the right side of the environment
; variable. Because we want to skip the '=', we will set the carry.
found: ldx ptr3+1 ; High byte of result
tya
sec
adc ptr3
bcc @L9
inx
@L9: rts
.endproc

198
libsrc/common/putenv.s Normal file
View File

@ -0,0 +1,198 @@
;
; Ullrich von Bassewitz, 2005-04-21
;
; int putenv (char* s);
;
; Note: The function will place s into the environment, *not* a copy!
;
.export _putenv
.import _malloc, _free
.import searchenv, copyenvptr
.import __environ, __envcount, __envsize
.import seterrno, return0
.import ptr1:zp, ptr2:zp, ptr3:zp, tmp1:zp
.include "errno.inc"
.macpack cpu
.code
;----------------------------------------------------------------------------
; putenv()
.proc _putenv
sta ptr1
sta name
stx ptr1+1 ; Save name
stx name+1
; Loop over the name to find the '='. If there is no '=', set errno to EINVAL
; and return an error.
ldy #$FF
@L0: iny
lda (ptr1),y
bne @L1
lda #EINVAL
jmp error ; End of string without '=' found
@L1: cmp #'='
bne @L0
; Remember the offset of the equal sign and replace it by a zero.
.if (.cpu .bitand ::CPU_ISET_65SC02)
phy
stz (ptr1),y
.else
sty tmp1
lda #$00
sta (ptr1),y
.endif
; Search for the string in the environment. searchenv will set the N flag if
; the string is not found, otherwise X contains the index of the entry, ptr2
; contains the entry and Y the offset of the '=' in the string. ptr3 will
; point to the environment.
jsr searchenv
; Before doing anything else, restore the old environment string.
.if (.cpu .bitand ::CPU_ISET_65SC02)
ply
.else
ldy tmp1
.endif
lda #'='
sta (ptr1),y
; Check the result of searchenv
txa ; Did we find the entry?
bpl addentry ; Jump if yes
; We didn't find the entry, so we have to add a new one. Before doing so, we
; must check if the size of the _environ array must be increased.
; Note: There must be one additional slot for the final NULL entry.
ldx __envcount
inx
cpx __envsize
bcc addnewentry ; Jump if space enough
; We need to increase the size of the environ array. Calculate the new size.
; We will not support a size larger than 64 entries, double the size with
; each overflow, and the starting size is 8 entries.
lda __envsize
bne @L2
lda #4 ; Start with 4*2 entries
@L2: asl a ; Double current size
bmi nomem ; Bail out if > 64
sta newsize ; Remember the new size
; Call malloc() and store the result in ptr2
asl a ; Make words
ldx #$00
jsr _malloc
sta ptr2
stx ptr2+1
; Check the result of malloc
ora ptr2+1
beq nomem
; Copy the old environment pointer to ptr3, and the new one to __environ.
ldx #1
@L3: lda __environ,x
sta ptr3,x
lda ptr2,x
sta __environ,x
dex
bpl @L3
; Use the new size.
lda newsize
sta __envsize
; Copy the old environment data into the new space.
lda __envcount
asl a
tay
jmp @L5
@L4: lda (ptr3),y
sta (ptr2),y
@L5: dey
bpl @L4
; Free the old environment space
lda ptr3
ldx ptr3+1
jsr _free
; Since free() has destroyed ptr2, we need another copy ...
jsr copyenvptr ; Copy __environ to ptr2
; Bump the environment count and remember it in X. Add the final NULL entry.
addnewentry:
inc __envcount
ldx __envcount
txa
asl a
tay
lda #$00
sta (ptr2),y
iny
sta (ptr2),y
; The index of the new entry is the old environment count.
dex
txa
; Add the new entry to the slot with index in X. The pointer to the environment
; is already in ptr2, either by a call to searchenv, or by above code.
addentry:
asl a
tay
lda name
sta (ptr2),y
iny
lda name+1
sta (ptr2),y
; Done
jmp return0
; Error entries
nomem: lda #ENOMEM
error: jsr seterrno
lda #$FF ; Return -1
tax
rts
.endproc
;----------------------------------------------------------------------------
; data
.bss
name: .addr 0 ; Pointer to name
newsize: .byte 0 ; New environment size

84
libsrc/common/searchenv.s Normal file
View File

@ -0,0 +1,84 @@
;
; Ullrich von Bassewitz, 2005-04-21
;
; Search the environment for a string.
;
.export searchenv, copyenvptr
.import __environ, __envcount
.import ptr1:zp, ptr2:zp, ptr3:zp
.code
;----------------------------------------------------------------------------
; searchenv:
;
; ptr1 must contain the string to search for. On exit, the N flag will tell
; if the entry was found, and X will contain the index of the environment
; string in the environment (a negative value if the entry was not found).
; On success, ptr3 will contain the entry and Y the offset of the '=' within
; the string.
.proc searchenv
; Copy the pointer to the environment to the zero page
jsr copyenvptr
; Loop over all environment entries trying to find the requested one.
ldx __envcount
@L0: dex
bmi @L9 ; Out of entries
; Since the maximum number of entries is 64, the index can only be 63, so
; the following shift cannot overflow and the carry is clear.
txa
asl a ; Mul by two for word access
tay
lda (ptr2),y
sta ptr3
iny
lda (ptr2),y
sta ptr3+1
; ptr1 points to name, ptr3 points to the next environment entry. Compare the
; two. The following loop limits the length of name to 255 bytes.
ldy #$00
@L1: lda (ptr1),y
beq @L2 ; Jump on end of name
cmp (ptr3),y
bne @L0 ; Next environment entry
iny
bne @L1
; End of name reached, check if the environment entry contains a '=' char
@L2: lda (ptr3),y
cmp #'='
bne @L0 ; Next environment entry
; Done. The function result is in X and the N flag is set correctly.
@L9: rts
.endproc
;----------------------------------------------------------------------------
; copyenvptr: Copy _environ to ptr2
;
.proc copyenvptr
lda __environ
sta ptr2
lda __environ+1
sta ptr2+1
rts
.endproc