home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
rxfiles.zip
/
rxshvenv.asm
< prev
next >
Wrap
Assembly Source File
|
1997-08-15
|
11KB
|
307 lines
;-----------------------------------------------------------------------
; rxshvenv.ASM for rxshenv.RX by ML /AT /Fe rxshvenv.RX rxshvenv.ASM
;
; Usage in a REXX script: RXSHVENV( "stem" ), sets stem.1, etc. to name
; of 1st, etc. environment variable. RESULT = stem.0 is the number of
; environment variables set. RESULT = 0 indicates errors like invalid
; stem name or no more memory to store stem.x in shared variable pool.
;
; Note: PC DOS 7 REXX allocates SHV memory under the PID of whatever
; current process (like RXSVHENV). After termination this new memory
; is freed by the OS, results are lost. To correct this misbehaviour
; RXSHVENV replaces in all OS memory blocks (except from its own PSP)
; its PID by its loader (i.e. REXX) before termination. For unknown
; reasons simply changing the current PID before calling SHVENTRY by
; undocumented OS function 50h does not work as expected.
;-----------------------------------------------------------------------
code segment para public 'CODE'
assume cs:code, ds:code, es:code, ss:code
RXSTR struct
RxLen dw ?
RxPtr dd ?
RXSTR ends
PRXSTR TYPEDEF far ptr RXSTR
SHVBLOCK struct
ShvNext dd ?
ShvNam RXSTR <>
ShvVal RXSTR <>
ShvNamL dw ?
ShvValL dw ?
ShvCode db ?
ShvRet db ?
SHVBLOCK ends
org 16h
RXpid dw ? ;_psp:0x16 parent (REXX) pid
org 2Ch
envseg dw ? ;_psp:0x2C environment segment
org 54h
DOSREXX4 dd ? ;_psp:0x54 'REXX' signature
SHVENTRY dd ? ;_psp:0x58 shared variable handler
org 82h
RXARGC dw ? ;_psp:0x82 number of arguments
RXARGV PRXSTR ? ;_psp:0x84 arg.s (length, pointer)
RXRESULT dd ? ;_psp:0x88 RESULT buffer (256 bytes)
org 100h ;COM entry point at CS:100
start: jmp stack ;set stack, release memory
total dw (0) ;counter environment strings
stem db 256 dup (0) ;target stem from caller
stemp dw (0) ;pointer behind '.' in stem
shvcom SHVBLOCK <0,<0,0>,<0,0>,0,0,3,0>
ifndef SHV_OKAY ;SHV broken: works with my PID
strat dw (0) ;memory allocation strategy
umbstate db (0) ;undoc.: UMB linkage 0 or 1
endif ;SHV_OKAY
;-----------------------------------------------------------------------
main proc near ;enter after initialization
cmp word ptr DOSREXX4+2,'XX'
jne badarg
cmp RXARGC,1 ;missing argument
je gotarg
badarg: mov al,1 ;REXX function error
jmp exit
gotarg: lds si,RXARGV
mov cx,RXSTR.RxLen[si]
jcxz badarg ;target stem empty
cmp cx,250
jnbe badarg ;target stem too long
lds si,RXSTR.RxPtr[si]
mov di,offset stem ;ES:DI stem buffer
rep movsb ;copy argument to stem
mov al,'.' ;'.' compound variable
stosb
push es
pop ds ;restore own DS
ifndef SHV_OKAY ;SHV broken: works with my PID
mov ax,5800h ;get alloc. strategy
int 21h
mov strat,ax ;for restore at exit
mov ax,5802h ;get UMB link state
int 21h
mov umbstate,al ;for restore at exit
mov ax,5803h ;set UMB link state
mov bx,0001h ;try to link in UMBs
int 21h
mov ax,5801h ;set alloc. strategy
mov bx,0081h ;best fit allocation
int 21h ;81h = try UMB first
endif ;SHV_OKAY
mov stemp,di ;save stem pointer
mov es,envseg ;ES = environment
xor si,si
next: mov dx,si
mov di,si
call strlen
jcxz done ;CX = length (0 last)
add si,cx
inc si ;next ES variable
mov al,'='
repnz scasb
mov byte ptr es:[di-1],0
call inctotal ;stem.i => stem.i+1
call shvset ;ES:DX var. name
cmp cl,1
jbe next
jmp full ;give up after error
done: les di,RXRESULT ;ES:DI result
mov dx,di ;ES:DX result
mov si,stemp ;DS:SI total (ASCIIZ)
result: lodsb
stosb
cmp al,0
je stem0 ;end of string
jmp result
stem0: mov bx,stemp
mov word ptr [bx],'0'
call shvset ;ES:DX result
cmp cl,1
jbe okay ;stem.0 = result
full: les di,RXRESULT ;invalidate result
mov word ptr es:[di],'0'
okay:
ifndef SHV_OKAY ;SHV broken: works with my PID
mov es,envseg
mov ah,49h ;free memory block
int 21h
mov ah,52h ;get list of list
int 21h
mov bx,es:[bx-2] ;first MCB in chain
mov cx,cs ;CX = CS = my own PID
mov dx,RXpid ;DX = parent REXX PID
nextmcb: mov es,bx
xor bx,bx ;ES:BX = MCB
cmp es:[bx+1],cx ;"my" MCB (CS = owner) ?
jne skipmcb ; no -> don't patch it
mov es:[bx+1],dx ; yes -> patch REXX PID
skipmcb: cmp byte ptr es:[bx+0],'Z'
je lastmcb ;last MCB in chain
mov ax,es
mov bx,es:[bx+3] ;BX = MCB size (paras)
add bx,ax
inc bx ;next MCB in chain
jmp nextmcb
lastmcb: dec cx
mov es,cx ;patch back own PSP MCB
mov es:[bx+1],cs ;(freed by termination)
mov ax,5801h ;set alloc. strategy
mov bx,strat ;reset REXX strategy
int 21h ;(sanity)
mov ax,5803h ;set UMB link state
mov bl,umbstate ;reset REXX UMB link
int 21h ;(sanity)
endif ;SHV_OKAY
xor ax,ax ;REXX function okay
exit: mov ah,4Ch ;terminate with RC AL
int 21h
main endp
;-----------------------------------------------------------------------
shvset proc near ;set shv variable (nam stem, val ES:DX)
mov word ptr shvcom.ShvVal.RxPtr+0,dx
mov word ptr shvcom.ShvVal.RxPtr+2,es
call strlen
mov shvcom.ShvVal.RxLen,cx
push es ;modifies AX, BX, CX, DX
push ds ;keep SI, DI, DS, ES
push ds
pop es
mov dx,offset stem ;ES:DX variable name
call strlen ;new length for name
pop ds
pop es
mov word ptr shvcom.ShvNam.RxPtr+0,dx
mov word ptr shvcom.ShvNam.RxPtr+2,ds
mov shvcom.ShvNam.RxLen,cx
mov shvcom.ShvCode,3
mov dx,offset shvcom
push ds
push dx
call dword ptr SHVENTRY
pop bx
pop bx
xor cx,cx ;0 set, 1 new, else bad
mov cl,shvcom.ShvRet
ret
shvset endp
;-----------------------------------------------------------------------
inctotal proc near ;increment stem counter
mov bx,stemp ;modifies AX, BX, CX
inc total
mov ax,total ;AX = counter 1..9999
mov cl,100 ;AL = quotient 0.. 99
div cl ;AH = remainder 0.. 99
mov ch,ah ;save remainder
mov cl,'0' ;search non-zero mask
aam ;adjust quotient 0..99
xchg ah,al
or al,al ;search for non-zero
jz lt_1000
or al,cl
mov [bx],al
inc bx
xor cl,cl ;clear search mask CL
lt_1000: mov al,ah
mov ah,ch ;restore remainder
or al,'0'
cmp al,cl ;search for non-zero
je lt_0100
xor cl,cl ;clear search mask CL
mov [bx],al
inc bx ;e.g. 2 of total 1234
lt_0100: mov al,ah
aam ;adjust remainder 0..99
xchg al,ah
or al,'0'
cmp al,cl ;search for non-zero
je lt_0010
mov [bx],al
inc bx ;e.g. 3 of total 1234
lt_0010: mov al,ah
or al,'0'
mov [bx],al ;e.g. 4 of total 1234
ret
inctotal endp
;-----------------------------------------------------------------------
strlen proc near ;return length ASCIIZ string ES:DX
xchg di,dx ;modifies AX, CX
mov cx,di ;keep DX, DI, ES
not cx ;terminate search at segment limit
push di ;this will work for length < 64 KB
xor al,al
repne scasb ;search NUL
mov cx,di ;DI points behind NUL (or is NULL)
pop di ;restore DI
sub cx,di ;length inclusive NUL
dec cx ;length exclusive NUL
xchg dx,di ;restore DX
ret ;returns CX string length
strlen endp
;-----------------------------------------------------------------------
align 16
stkparas equ 32 ;stack size 512 = 32 * 16
stack label near ;initialise *.com program
mov bx,offset stack + 16 * stkparas
mov sp,bx ;new stack 100h above init
mov cl,4
shr bx,cl ;used number of paragraphs:
mov ah,4ah ;modify allocated memory to
int 21h ;needed size i.e. free rest
jmp main ;current SP must be beyond
;-----------------------------------------------------------------------
code ends
end start ;program entry point