|
|
Microsoft OS/2 SDK 03-01-1988
; Created by Microsoft Corp. 1986
name cpgrepsub
retlen equ 2 ; Size of return address on stack
dgroup group _data
extrn _casesen: word ; Case-sensitivity flag
extrn _stringlist: word ; Table of string lists
extrn _target: byte ; Target string
extrn _targetlen: word ; Length of target string
extrn _transtab: byte ; Translation table for _findlist
; This segment is puposely word-aligned. See note
; in _findlist below.
_text segment word public 'code'
assume cs:_text, ds:dgroup, es:nothing, ss:dgroup
; char *findone(buffer,bufend)
; char *buffer /* Buffer in which to search */
; char *bufend; /* End of buffer */
;
; NOTE: targetlen MUST BE greater than zero
buffer equ word ptr [bp+retlen+2]
bufend equ word ptr [bp+retlen+4]
EVEN
public _findone
_findone proc near
push bp
mov bp,sp
push di
push si
push es
push ds ; ES = DS
pop es
mov cx,bufend ; CX = end of buffer
mov di,buffer ; ES:DI = buffer
sub cx,di ; CX = length of buffer
jbe sfnomatch ; length less than or equal to zero
mov dx,_targetlen ; DX = length of target
dec dx ; Decrement it
sub cx,dx ; target must fit in buffer
jbe sfnomatch ; (no match if buffer too short)
; CX = buffer length
; DX = target length (minus first character)
; ES:DI = buffer pointer
sf0: jcxz sfnomatch ; No match if count zero
mov si,offset dgroup:_target ; DS:SI = target
lodsb ; AL = first byte of target
repne scasb ; Look for first character
jne sfnomatch ; jump if not found
mov bx,cx ; BX = buffer length
mov ax,di ; AX = buffer pointer
mov cx,dx ; Get count for cmpsb
or cx,cx ; Zero? (JCXZ doesn't set flag)
je sf1 ; yes, skip compare
repe cmpsb ; Do string compare
sf1: mov di,ax ; DI = buffer pointer
mov cx,bx ; CX = buffer length
jne sf0 ; Loop if no match
dec ax ; AX = offset of start of match
jmp short sf4
sfnomatch:
xor ax,ax ; No match
sf4: pop es
pop si
pop di
pop bp
ret
_findone endp
; int revfind(s,c,slen)
; char *s; /* String to search */
; int c; /* Char to search for */
; int slen; /* Length of s */
s equ [bp+retlen+2]
c equ [bp+retlen+4]
slen equ [bp+retlen+6]
EVEN
public _revfind
_revfind proc near
push bp
mov bp,sp
push di
push es
push ds
pop es
mov di,s
mov ax,c
mov cx,slen
jcxz rf1
std
repne scasb
cld
mov cx,s
jne rf0
inc di
rf0: sub cx,di
rf1: mov ax,cx
pop es
pop di
pop bp
ret
_revfind endp
; int countlines(start,finish)
; char *start;
; char *finish;
start equ [bp+retlen+2]
finish equ [bp+retlen+4]
EVEN
public _countlines
_countlines proc near
push bp
mov bp,sp
push di
push es
push ds
pop es
xor dx,dx ; Accumulate count in DX
mov di,start ; ES:DI points to start
mov cx,finish ; Put length in CX
sub cx,di
jbe cl1 ; branch if no bytes
mov al,0Ah ; Search for linefeeds
cl0: jcxz cl1 ; Exit loop if count zero
repne scasb ; Do search
jne cl1 ; branch if none found
inc dx ; Increment count
jmp short cl0 ; Loop
cl1: mov ax,dx ; Return line count in AX
pop es
pop di
pop bp
ret
_countlines endp
; char *findlist(buffer,bufend)
; char *buffer; /* Buffer to search */
; char *bufend; /* End of buffer */
savesi equ word ptr [bp-2]
endbyte equ byte ptr [bp-4]
stringnode struc
s_alt dw ? ; List of alternate portions
s_suf dw ? ; Pointer to suffix string list
s_must dw ? ; Length of portion that must match
stringnode ends
EVEN
flworker dw findsubi, findsub ; Worker dispatch table
public _findlist
_findlist proc near
ASSUME DS:DGROUP, ES:NOTHING, SS:DGROUP
push bp
mov bp,sp
sub sp,4 ; Make room for local vars
push di
push si
push ds
pop es
ASSUME ES:DGROUP
; We mark the end of our search buffer with 0FFh so that
; any comparisons that might run past the end of the buffer
; will fail on the 0FFh. We choose 0FFh so that if the
; comparison fails on it, it will always appear as though
; the string in the buffer is greater that the string in
; the search list. This will prevent us from stopping
; the search too soon. Of course, we must restore the byte
; when we're done.
mov bx,bufend ; BX = end of buffer
mov al,0FFh ; End marker
xchg byte ptr [bx],al ; AL = byte after end of buffer
mov endbyte,al ; Save the byte
mov cx,bx ; CX = end of buffer
mov si,buffer ; SI = buffer
sub cx,si ; CX = buffer length
jbe fl1 ; no match if empty buffer
mov bx,offset dgroup:_transtab ; BX = translation table address
mov di,_casesen ; Get flag
shl di,1 ; Scale to word index
call cs:flworker[di] ; Call helper
jc fl1 ; branch if no match
; We have a match
;
; SI = offset of first character past end of matched string
; savesi = offset of first character past start of matched string
mov ax,savesi ; AX = 1st char past start
dec ax ; AX = start of matched string
jmp short fl2
; We did not find a match
fl1:
xor ax,ax ; Return NULL
; Restore end byte before leaving
fl2:
mov bx,bufend ; BX = end of buffer
mov dl,endbyte ; DL = end byte
mov [bx],dl ; Restore byte
pop si
pop di
mov sp,bp
pop bp
ret
_findlist endp
;*** findsub - case-sensitive worker for _findlist
;
; This function does most of the work for
; case-sensitive multi-string searches.
;
; ENTRY BX = address of translation table
; CX = number of bytes left in buffer
; DS:SI = buffer pointer
; SS:BP = pointer to stack frame for _findlist
; EXIT Carry set
; No match
; Carry clear
; DS:SI = pointer to first character after match
; USES AX, CX, DX, DI, SI, Flags
EVEN
public findsub, fs0, fs1, fs2, fs3, fs4, fs5, fs6
findsub proc near
ASSUME DS:DGROUP, ES:DGROUP, SS:DGROUP
fs0:
xor ax,ax ; AH = 0
; AH = 0
; BX = address of translation table
; CX = number of bytes left in buffer
; SI = buffer pointer
; DS = ES = SS = DGROUP
fs1:
lodsb ; Character in AL
xlat byte ptr [bx] ; Translate character to index
or al,al ; Zero means invalid 1st byte
loopz fs1 ; if so, try next character
; Either the zero bit is set, meaning the buffer is empty,
; or the zero bit is clear, meaning we have a valid first
; character. Either way, CX has been decremented.
jz fs6 ; branch if buffer empty
mov savesi,si ; Save buffer pointer
shl ax,1 ; Scale to word index
mov di,ax
mov di,_stringlist[di] ; DI points to string record
or di,di ; One byte match? (OR clears carry)
jz fs3 ; yes, skip ahead
; Loop to search for match.
; BX = address of translation table
; DI = pointer to string record
; SI = pointer into buffer
fs2:
mov cx,[di].s_must ; CX = length of string
sub di,cx ; DI = pointer to string
mov dx,si ; Save pointer to start of suffix
repe cmpsb ; Strings match?
ja fs4 ; no, try alternate if follows
jb fs5 ; no, cannot be in this list
add di,cx ; DI = pointer to string record
mov di,[di].s_suf ; Get pointer to suffix string list
or di,di ; Is there one? (OR clears carry)
jnz fs2 ; yes, keep looking
; Match found
fs3:
ret ; no, we have a match
; Try alternate suffix
fs4:
add di,cx ; DI = pointer to string record
mov di,[di].s_alt ; Get pointer to alternate
mov si,dx ; Restore SI to start of suffix
or di,di ; Is there one?
jnz fs2 ; yes, loop
; Try new first character
fs5:
mov cx,bufend ; CX = end of buffer
mov si,savesi ; Restore SI to saved value
sub cx,si ; CX = length of buffer
ja short fs0 ; Try next character in buffer
; No match
fs6:
stc ; No match
ret
findsub endp
;*** findsubi - case-insensitive worker for _findlist
;
; This function does most of the work for
; case-insensitive multi-string searches.
;
; ENTRY BX = address of translation table
; CX = number of bytes left in buffer
; DS:SI = buffer pointer
; SS:BP = pointer to stack frame for _findlist
; EXIT Carry set
; No match
; Carry clear
; DS:SI = pointer to first character after match
; USES AX, CX, DX, DI, SI, Flags
EVEN
public findsubi
findsubi proc near
ASSUME DS:DGROUP, ES:DGROUP, SS:DGROUP
fsi0:
xor ax,ax ; AH = 0
; AH = 0
; BX = address of translation table
; CX = number of bytes left in buffer
; SI = buffer pointer
; DS = ES = SS = DGROUP
fsi1:
lodsb ; Character in AL
xlat byte ptr [bx] ; Translate character to index
or al,al ; Zero means invalid 1st byte
loopz fsi1 ; if so, try next character
; Either the zero bit is set, meaning the buffer is empty,
; or the zero bit is clear, meaning we have a valid first
; character. Either way, CX has been decremented.
jz fsi7 ; branch if buffer empty
mov savesi,si ; Save buffer pointer
shl ax,1 ; Scale to word index
mov di,ax
mov di,_stringlist[di] ; DI points to string record
or di,di ; One byte match? (OR clears carry)
jz fsi4 ; yes, skip ahead
; Loop to search for match.
; BX = address of translation table
; DI = pointer to string record
; SI = pointer into buffer
fsi2:
mov cx,[di].s_must ; CX = length of string
sub di,cx ; DI = pointer to string
mov dx,si ; Save pointer to start of suffix
fsi3: lodsb ; Byte in AL, SI = SI + 1
mov ah,[di] ; Byte in AH, DI = DI + 1
inc di
or ax,2020h ; Fold bytes onto lower case
cmp al,ah ; Compare bytes
loope fsi3 ; Loop while same
ja fsi5 ; no, try alternate if follows
jb fsi6 ; no, cannot be in this list
add di,cx ; DI = pointer to string record
mov di,[di].s_suf ; Get pointer to suffix string list
or di,di ; Is there one? (OR clears carry)
jnz fsi2 ; yes, keep looking
; Match found
fsi4:
ret ; no, we have a match
; Try alternate suffix
fsi5:
add di,cx ; DI = pointer to string record
mov di,[di].s_alt ; Get pointer to alternate
mov si,dx ; Restore SI to start of suffix
or di,di ; Is there one?
jnz fsi2 ; yes, loop
; Try new first character
fsi6:
mov cx,bufend ; CX = end of buffer
mov si,savesi ; Restore SI to saved value
sub cx,si ; CX = length of buffer
ja short fsi0 ; Try next character in buffer
; No match
fsi7:
stc ; No match
ret
findsubi endp
; int strnspn(s,t,n)
; char *s; /* String to search */
; char *t; /* Target list */
; int n; /* Length of s */
s equ word ptr [bp+retlen+2]
t equ word ptr [bp+retlen+4]
n equ word ptr [bp+retlen+6]
EVEN
public _strnspn
_strnspn proc near
push bp
mov bp,sp
push di
push si
push ds
pop es
cld
mov bx,t ; BX = t
mov di,bx ; DI = t
xor al,al ; Search for 0 byte
mov cx,0FFFFh
repne scasb
dec di ; Back up to 0
sub di,bx ; DI = length of t
jz spn1 ; Done if length of t is 0
mov dx,di ; DX = length of t
mov si,s ; SI = s
mov cx,n ; CX = length of s
jcxz spn1 ; Check for null string
push bp
spn0: lodsb ; AL = next char in s
mov bp,cx ; BP = length of s
mov cx,dx ; CX = length of t
mov di,bx ; DI = t
repne scasb ; Scan until match found
mov cx,bp ; CX = length of s
loope spn0 ; Loop if match found
pop bp
je spn1 ; Skip ahead if end of s reached
dec si ; Back up one char
spn1: sub si,s ; SI = length of prefix
mov ax,si ; AX = length of prefix
pop si
pop di
pop bp
ret
_strnspn endp
; int strncspn(s,t,n)
; char *s; /* String to search */
; char *t; /* Target list */
; int n; /* Length of s */
EVEN
public _strncspn
_strncspn proc near
push bp
mov bp,sp
push di
push si
push ds
pop es
cld
mov bx,t ; BX = t
mov di,bx ; DI = t
xor al,al ; Search for 0 byte
mov cx,0FFFFh
repne scasb
dec di ; Back up to 0
sub di,bx ; DI = length of t
mov ax,n ; Assume length of t is 0
jz cspn2 ; Done if length of t is 0
mov dx,di ; DX = length of t
mov si,s ; SI = s
mov cx,ax ; CX = length of s
jcxz cspn1 ; Check for null string
push bp
cspn0: lodsb ; AL = next char in s
mov bp,cx ; BP = length of s
mov cx,dx ; CX = length of t
mov di,bx ; DI = t
repne scasb ; Scan until match found
mov cx,bp ; CX = length of s
loopne cspn0 ; Loop if match not found
pop bp
jne cspn1 ; Skip ahead if end of s reached
dec si ; Back up one char
cspn1: sub si,s ; SI = length of prefix
mov ax,si ; AX = length of prefix
cspn2: pop si
pop di
pop bp
ret
_strncspn endp
; cmpsen - case-sensitive comparison
;
; ENTRY DS:SI = buffer
; ES:DI = string
; CX = length of string
; EXIT CX = length of string unused
; DI = unused portion of string
; Z set
; match found
; Z clear
; no match
; USES CX, DI, SI, Flags
EVEN
cmpsen proc near
repe cmpsb
ret
cmpsen endp
; cmpinsen - case-insensitive comparison
;
; ENTRY DS:SI = buffer
; ES:DI = string
; CX = length of string
; EXIT CX = length of string unused
; DI = unused portion of string
; Z set
; match found
; Z clear
; no match
; USES AX, CX, DI, SI, Flags
EVEN
cmpinsen proc near
cmpi0: lodsb ; Byte in AL, SI = SI + 1
mov ah,[di] ; Byte in AH, DI = DI + 1
inc di
or ax,2020h ; Fold bytes onto lower case
cmp al,ah ; Compare bytes
loope cmpi0 ; Loop while same
ret
cmpinsen endp
; void matchstrings(s1,s2,len,nmatched,leg)
; char *s1; /* First string */
; char *s2; /* Second string */
; int len; /* Length */
; int *nmatched; /* Number of bytes matched */
; int *leg; /* Less than, equal, greater than */
cm_s1 equ word ptr [bp+retlen+2]
cm_s2 equ word ptr [bp+retlen+4]
cm_len equ word ptr [bp+retlen+6]
cm_nmatched equ word ptr [bp+retlen+8]
cm_leg equ word ptr [bp+retlen+10]
EVEN
public _matchstrings
_matchstrings proc near
ASSUME DS:DGROUP, ES:NOTHING, SS:DGROUP
push bp
mov bp,sp
push di
push si
push ds
pop es
ASSUME ES:DGROUP
mov di,cm_s2
mov si,cm_s1
mov cx,cm_len
cmp _casesen,0
je cm0
call cmpsen
jmp short cm1
cm0: call cmpinsen
cm1: mov bx,cm_leg
mov word ptr [bx],0 ; Assume equal
jz cm2 ; yes, skip ahead
mov word ptr [bx],1 ; Assume greater than
jg cm1a ; yes, skip ahead
mov word ptr [bx],-1 ; Less than
cm1a: dec si
cm2: sub si,cm_s1
mov bx,cm_nmatched
mov [bx],si
pop si
pop di
pop bp
ret
_matchstrings endp
; int strcmp(s1,s2)
; char *s1; /* First string */
; char *s2; /* Second string */
public _strcmp
_strcmp proc near
push bp
mov bp,sp
push di
push si
push ds
pop es
mov si,[bp+4] ; DS:SI = s1
mov di,[bp+6] ; ES:DI = s2
sc0: lodsb ; AL = *s1++
scasb ; AL - *s2++
jne sc1 ; branch if no match
or al,al ; End of s1?
jne sc0 ; no, loop
cbw ; AX = 0
jmp short sc2 ; Exit
sc1: mov ax,1 ; Assume s1 > s2
jg sc2 ; yes, branch
neg ax ; s1 < s2
sc2: pop si
pop di
pop bp
ret
_strcmp endp
public _bpt
_bpt proc near
int 3
ret
_bpt endp
_text ends
_data segment word public 'data'
_data ends
end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.