mirror of
https://github.com/cc65/cc65.git
synced 2024-11-05 08:05:51 +00:00
5c2eebcda1
git-svn-id: svn://svn.cc65.org/cc65/trunk@3488 b7a2c559-68d2-44c3-8de9-860c34a00d81
188 lines
4.4 KiB
ArmAsm
188 lines
4.4 KiB
ArmAsm
;
|
|
; 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"
|
|
|
|
.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.
|
|
|
|
sty tmp1
|
|
lda #$00
|
|
sta (ptr1),y
|
|
|
|
; 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.
|
|
|
|
ldy tmp1
|
|
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
|
|
|