1003 lines
24 KiB
NASM
1003 lines
24 KiB
NASM
;
|
|
; Copyright (c) Mix Software 1988
|
|
;
|
|
; -------------------------------------------------------
|
|
; strcat(string1, string2) - concatenate strings
|
|
; strncat(string1, string2, n) - concatenate strings
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strcat
|
|
DEF strcat
|
|
DEF strncat
|
|
IF UPPER
|
|
DEF STRCAT
|
|
DEF STRNCAT
|
|
ENDIF
|
|
;
|
|
strcat equ $
|
|
STRCAT PUSH BP
|
|
MOV BP,SP
|
|
MOV CX,-1 ; no limit on length
|
|
CAT MOV DI,[BP][%PARM1]
|
|
MOV SI,[BP][%PARM2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
CLD
|
|
XOR AX,AX
|
|
PUSH CX
|
|
MOV CX,-1
|
|
REPNZ ; search for zero on string 1
|
|
SCASB
|
|
POP CX
|
|
DEC DI ; overwrite the '\0' terminator
|
|
COPY LODSB
|
|
STOSB
|
|
TEST AL,AL
|
|
JZ DONE
|
|
LOOP COPY
|
|
MOV %[DI],%0
|
|
DONE MOV AX,[BP][%PARM1] ; result is pointer to string1
|
|
POP BP
|
|
RETSEG
|
|
strncat equ $
|
|
STRNCAT PUSH BP
|
|
MOV BP,SP
|
|
MOV CX,[BP][%PARM3] ; cx = limit on length
|
|
JCXZ DONE
|
|
JMPS CAT
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strchr(string1, c) - search string for character
|
|
; -------------------------------------------------------
|
|
; char *strchr(s, c)
|
|
; char *s;
|
|
; int c;
|
|
;
|
|
; Purpose: Searches for first occurrence of c in s
|
|
; Returns: Pointer to c if s contains c
|
|
; NULL if s does not contain c
|
|
;
|
|
;
|
|
IDT strchr
|
|
DEF strchr
|
|
IF UPPER
|
|
DEF STRCHR
|
|
ENDIF
|
|
;
|
|
strchr equ $
|
|
STRCHR PUSH BP
|
|
MOV BP,SP
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV DI,[BP][%PARM1]
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ
|
|
SCASB
|
|
NOT CX ; CX = length including '\0'
|
|
MOV DI,[BP][%PARM1]
|
|
MOV AL,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
JNZ NOFIND
|
|
DEC DI
|
|
MOV AX,DI
|
|
POP BP
|
|
RETSEG
|
|
NOFIND XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; index(string1, c) - search string for character
|
|
; -------------------------------------------------------
|
|
; char *index(s, c)
|
|
; char *s;
|
|
; int c;
|
|
;
|
|
; Purpose: Searches for first occurrence of c in s
|
|
; Returns: Pointer to c if s contains c
|
|
; NULL if s does not contain c
|
|
;
|
|
;
|
|
IDT index
|
|
IF UPPER
|
|
DEF INDEX
|
|
ENDIF
|
|
DEF index
|
|
;
|
|
index equ $
|
|
INDEX PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
MOV DX,[BP][%PARM2]
|
|
CLD
|
|
CMP LODSB
|
|
CMP AL,DL
|
|
JZ FOUND
|
|
TEST AL,AL
|
|
JNZ CMP
|
|
XOR AX,AX ; Not found
|
|
POP BP
|
|
RETSEG
|
|
FOUND DEC SI ; Return pointer to c
|
|
MOV AX,SI
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strrchr(string, c) - search string for last occurance of c
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strrchr
|
|
DEF strrchr
|
|
IF UPPER
|
|
DEF STRRCHR
|
|
ENDIF
|
|
;
|
|
strrchr equ $
|
|
STRRCHR PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM1]
|
|
CLD
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; find end of string
|
|
SCASB
|
|
NOT CX
|
|
STD
|
|
MOV DI,[BP][%PARM1]
|
|
ADD DI,CX
|
|
DEC DI
|
|
MOV AX,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
CLD
|
|
JZ FOUND
|
|
XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
FOUND INC DI ; Return pointer to c
|
|
MOV AX,DI
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; rindex(string, c) - search string for last occurance of c
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT rindex
|
|
IF UPPER
|
|
DEF RINDEX
|
|
ENDIF
|
|
DEF rindex
|
|
;
|
|
rindex equ $
|
|
RINDEX PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM1]
|
|
CLD
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; find end of string
|
|
SCASB
|
|
NOT CX
|
|
STD
|
|
MOV DI,[BP][%PARM1]
|
|
ADD DI,CX
|
|
DEC DI
|
|
MOV AX,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
CLD
|
|
JZ FOUND
|
|
XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
FOUND INC DI ; Return pointer to c
|
|
MOV AX,DI
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strcmp(string1, string2) - compare strings
|
|
; strncmp(string1, string2,n) - compare strings
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strncmp
|
|
DEF strncmp
|
|
IF UPPER
|
|
DEF STRNCMP
|
|
ENDIF
|
|
;
|
|
strncmp equ $
|
|
STRNCMP MOV BX,SP
|
|
MOV CX,[BX][%PARM3-2]
|
|
JCXZ EQUAL
|
|
MOV SI,[BX][%PARM1-2]
|
|
MOV DI,[BX][%PARM2-2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV DX,DI
|
|
XOR AX,AX
|
|
MOV BX,CX
|
|
REPNZ ; search for zero on string 1
|
|
SCASB
|
|
NEG CX
|
|
ADD CX,BX
|
|
MOV DI,DX
|
|
REPZ
|
|
CMPSB
|
|
MOV AL,%[SI][%-1]
|
|
SUB AL,%[DI][%-1]
|
|
CBW
|
|
RETSEG
|
|
EQUAL XOR AX,AX
|
|
RETSEG
|
|
END
|
|
;
|
|
IDT strcmp
|
|
DEF strcmp
|
|
IF UPPER
|
|
DEF STRCMP
|
|
ENDIF
|
|
strcmp equ $
|
|
STRCMP MOV BX,SP
|
|
MOV SI,[BX][%PARM1-2]
|
|
MOV DI,[BX][%PARM2-2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
CLD
|
|
MOV DX,DI
|
|
XOR AX,AX
|
|
MOV CX,-1
|
|
REPNZ ; search for zero on string 1
|
|
SCASB
|
|
INC CX
|
|
NEG CX
|
|
MOV DI,DX
|
|
REPZ
|
|
CMPSB
|
|
MOV AL,%[SI][%-1]
|
|
SUB AL,%[DI][%-1]
|
|
CBW
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strcmpi(string1, string2) - compare strings, ignore case
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strcmpi
|
|
DEF strcmpi
|
|
DEF stricmp
|
|
DEF strnicmp
|
|
IF UPPER
|
|
DEF STRCMPI
|
|
DEF STRICMP
|
|
DEF STRNICMP
|
|
ENDIF
|
|
;
|
|
strcmpi EQU $
|
|
stricmp EQU $
|
|
STRICMP EQU $
|
|
STRCMPI PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
MOV DI,[BP][%PARM2]
|
|
MOV CX,-1
|
|
CMP LODSB
|
|
MOV BL,[DI]
|
|
INC DI
|
|
TEST AL,AL ; end of string1?
|
|
JZ END1
|
|
TEST BL,BL
|
|
JZ END1
|
|
CMP AL,BL
|
|
JNZ NOTEQUAL
|
|
NEXT LOOP CMP
|
|
EQUAL XOR AX,AX ; strings are equal
|
|
POP BP
|
|
RETSEG
|
|
END1 XOR AH,AH ; end of both?
|
|
XOR BH,BH
|
|
SUB AX,BX
|
|
POP BP
|
|
RETSEG
|
|
NOTEQUAL CMP AL,'A'
|
|
JB NOTAL
|
|
CMP AL,'Z'
|
|
JA NOTAL
|
|
ADD AL,'a'-'A'
|
|
NOTAL CMP BL,'A'
|
|
JB NOTBL
|
|
CMP BL,'Z'
|
|
JA NOTBL
|
|
ADD BL,'a'-'A'
|
|
NOTBL CMP AL,BL
|
|
JZ NEXT
|
|
MOV AL,[SI][%-1]
|
|
MOV BL,[DI][%-1]
|
|
JMPS END1
|
|
strnicmp equ $
|
|
STRNICMP PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
MOV DI,[BP][%PARM2]
|
|
MOV CX,[BP][%PARM3]
|
|
JCXZ EQUAL
|
|
JMPS CMP
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strcpy(string1, string2) - copy strings
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strcpy
|
|
IF UPPER
|
|
DEF STRCPY
|
|
ENDIF
|
|
DEF strcpy
|
|
;
|
|
strcpy equ $
|
|
STRCPY MOV BX,SP
|
|
MOV SI,[BX][%PARM2-2]
|
|
MOV DI,SI
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AX,AX
|
|
CLD
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
MOV DI,[BX][%PARM1-2]
|
|
MOV AX,DI
|
|
REP
|
|
MOVSB
|
|
RETSEG
|
|
END
|
|
;
|
|
IDT stpcpy
|
|
DEF stpcpy
|
|
stpcpy MOV BX,SP
|
|
MOV SI,[BX][%PARM2-2]
|
|
MOV DI,SI
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AX,AX
|
|
CLD
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
MOV DI,[BX][%PARM1-2]
|
|
MOV AX,DI
|
|
ADD AX,CX
|
|
DEC AX
|
|
REP
|
|
MOVSB
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strncpy(string1, string2, n) - copy string
|
|
; copy exactly n characters from string2 to string1
|
|
; if n < length of string2, no null is appended
|
|
; if n > length of string2, string1 padded with '\0'
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strncpy
|
|
DEF strncpy
|
|
IF UPPER
|
|
DEF STRNCPY
|
|
ENDIF
|
|
;
|
|
strncpy equ $
|
|
STRNCPY PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM1]
|
|
MOV SI,[BP][%PARM2]
|
|
MOV CX,[BP][%PARM3]
|
|
JCXZ DONE
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
CLD
|
|
COPY LODSB
|
|
STOSB
|
|
TEST AL,AL
|
|
JZ ENDSTR
|
|
LOOP COPY
|
|
DONE MOV AX,[BP][%PARM1]
|
|
POP BP
|
|
RETSEG
|
|
ENDSTR DEC CX
|
|
JCXZ DONE
|
|
XOR AX,AX
|
|
REP
|
|
STOSB
|
|
JMPS DONE
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; int strspn(s1, s2)
|
|
; char *s1, *s2;
|
|
;
|
|
; Purpose: Searches from beginning of s1
|
|
; until a character NOT in s2 is found
|
|
; Returns: Length of string segment in s1 consisting
|
|
; entirely of characters contained in s2
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strspn
|
|
DEF strspn
|
|
IF UPPER
|
|
DEF STRSPN
|
|
ENDIF
|
|
;
|
|
strspn equ $
|
|
STRSPN PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
MOV DI,[BP][%PARM2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; get length of string2
|
|
SCASB
|
|
NEG CX
|
|
DEC CX
|
|
MOV BX,CX
|
|
XOR DX,DX ; initial index
|
|
JCXZ DONE
|
|
NEXTCH LODSB
|
|
TEST AL,AL
|
|
JZ DONE
|
|
MOV CX,BX
|
|
MOV DI,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
JNZ DONE
|
|
INC DX
|
|
JMPS NEXTCH
|
|
DONE MOV AX,DX
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; int strcspn(s1, s2)
|
|
; char *s1, *s2;
|
|
;
|
|
; Purpose: Searches from beginning of s1
|
|
; until a character in s2 is found
|
|
; Returns: Length of string segment in s1 consisting
|
|
; entirely of characters NOT contained in s2
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strcspn
|
|
IF UPPER
|
|
DEF STRCSPN
|
|
ENDIF
|
|
DEF strcspn
|
|
;
|
|
strcspn equ $
|
|
STRCSPN PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
MOV DI,[BP][%PARM2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; get length of string2
|
|
SCASB
|
|
NOT CX
|
|
MOV BX,CX
|
|
XOR DX,DX ; initial index
|
|
JCXZ DONE
|
|
NEXTCH LODSB
|
|
TEST AL,AL
|
|
JZ DONE
|
|
MOV CX,BX
|
|
MOV DI,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
JZ DONE
|
|
INC DX
|
|
JMPS NEXTCH
|
|
DONE MOV AX,DX
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; int strpbrk(s1, s2)
|
|
; char *s1, *s2;
|
|
;
|
|
; Purpose: Searches from beginning of s1
|
|
; until a character in s2 is found
|
|
; Returns: pointer to first character found
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strpbrk
|
|
IF UPPER
|
|
DEF STRPBRK
|
|
ENDIF
|
|
DEF strpbrk
|
|
;
|
|
strpbrk equ $
|
|
STRPBRK PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
MOV DI,[BP][%PARM2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; get length of string2
|
|
SCASB
|
|
NOT CX
|
|
MOV BX,CX
|
|
JCXZ DONE
|
|
NEXTCH LODSB
|
|
TEST AL,AL
|
|
JZ NONE
|
|
MOV CX,BX
|
|
MOV DI,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
JZ DONE
|
|
JMPS NEXTCH
|
|
DONE DEC SI
|
|
MOV AX,SI
|
|
POP BP
|
|
RETSEG
|
|
NONE XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strrev(string) - reverse a string
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strrev
|
|
DEF strrev
|
|
IF UPPER
|
|
DEF STRREV
|
|
ENDIF
|
|
;
|
|
strrev equ $
|
|
STRREV PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM1]
|
|
CLD
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; find end of string
|
|
SCASB
|
|
SUB DI,%2
|
|
MOV SI,[BP][%PARM1]
|
|
REV CMP SI,DI
|
|
JAE DONE
|
|
MOV AL,%[DI]
|
|
XCHG AL,%[SI]
|
|
MOV %[DI],AL
|
|
INC SI
|
|
DEC DI
|
|
JMPS REV
|
|
DONE MOV AX,[BP][%PARM1]
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strsave(string) - copy to heap, NULL if no space
|
|
; strdup(string) - copy to heap, NULL if no space
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strdup
|
|
DEF strdup
|
|
DEF strsave
|
|
IF UPPER
|
|
DEF STRDUP
|
|
DEF STRSAVE
|
|
ENDIF
|
|
FREF malloc
|
|
strsave equ $
|
|
strdup equ $
|
|
STRSAVE EQU $
|
|
STRDUP PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM1]
|
|
TEST DI,DI
|
|
JZ NULL
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ ; get length of string2
|
|
SCASB
|
|
NEG CX
|
|
PUSH CX
|
|
PUSH CX
|
|
CALLFAR malloc
|
|
ADD SP,%2
|
|
POP CX
|
|
TEST AX,AX ; Null?
|
|
JZ DONE
|
|
MOV DI,AX
|
|
MOV SI,[BP][%PARM1]
|
|
REP
|
|
MOVSB
|
|
DONE POP BP
|
|
RETSEG
|
|
NULL XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strlwr(string) - convert all uppercase letters in
|
|
; string to lower case
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strlwr
|
|
DEF strlwr
|
|
IF UPPER
|
|
DEF STRLWR
|
|
ENDIF
|
|
;
|
|
strlwr equ $
|
|
STRLWR PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
CHECK MOV AL,%[SI]
|
|
TEST AL,AL
|
|
JZ DONE
|
|
CMP AL,'A'
|
|
JB OK
|
|
CMP AL,'Z'
|
|
JA OK
|
|
ADD AL,'a'-'A'
|
|
MOV %[SI],AL
|
|
OK INC SI
|
|
JMPS CHECK
|
|
DONE MOV AX,[BP][%PARM1]
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strupr(string) - convert all lower case letters in
|
|
; string to upper case
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strupr
|
|
DEF strupr
|
|
IF UPPER
|
|
DEF STRUPR
|
|
ENDIF
|
|
;
|
|
strupr equ $
|
|
STRUPR PUSH BP
|
|
MOV BP,SP
|
|
MOV SI,[BP][%PARM1]
|
|
CHECK MOV AL,%[SI]
|
|
TEST AL,AL
|
|
JZ DONE
|
|
CMP AL,'a'
|
|
JB OK
|
|
CMP AL,'z'
|
|
JA OK
|
|
ADD AL,'A'-'a'
|
|
MOV %[SI],AL
|
|
OK INC SI
|
|
JMPS CHECK
|
|
DONE MOV AX,[BP][%PARM1]
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; strset(string,c) - set all but '\0' to c
|
|
; strnset(string,c,n) - set up to n or '\0' to c
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strset
|
|
DEF strset
|
|
DEF strnset
|
|
IF UPPER
|
|
DEF STRSET
|
|
DEF STRNSET
|
|
ENDIF
|
|
;
|
|
strset equ $
|
|
STRSET PUSH BP
|
|
MOV BP,SP
|
|
MOV CX,-1 ; no limit on length
|
|
SET MOV SI,[BP][%PARM1]
|
|
MOV BX,[BP][%PARM2]
|
|
NEXT MOV AL,%[SI]
|
|
TEST AL,AL
|
|
JZ DONE
|
|
MOV %[SI],BL
|
|
INC SI
|
|
LOOP NEXT
|
|
DONE MOV AX,[BP][%PARM1] ; result is pointer to string1
|
|
POP BP
|
|
RETSEG
|
|
strnset equ $
|
|
STRNSET PUSH BP
|
|
MOV BP,SP
|
|
MOV CX,[BP][%PARM3] ; cx = limit on length
|
|
JCXZ DONE
|
|
JMPS SET
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; int strlen(s)
|
|
; char *s;
|
|
; Purpose: Returns the length of the string, not
|
|
; including the NULL character
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strlen
|
|
DEF strlen
|
|
IF UPPER
|
|
DEF STRLEN
|
|
ENDIF
|
|
;
|
|
strlen equ $
|
|
STRLEN MOV BX,SP
|
|
MOV DI,[BX][%PARM1-2]
|
|
CMP DI,%0
|
|
JZ NULL
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
DEC CX
|
|
MOV AX,CX
|
|
RETFAR
|
|
NULL XOR AX,AX
|
|
RETFAR
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; int strstr(s1, s2)
|
|
; char *s1, *s2;
|
|
;
|
|
; Purpose: Searches s1 for the first occurrence
|
|
; of s2
|
|
; Returns: pointer to substring if found,
|
|
; NULL if not found
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strstr
|
|
DEF strstr
|
|
IF UPPER
|
|
DEF STRSTR
|
|
ENDIF
|
|
;
|
|
strstr equ $
|
|
STRSTR PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM1]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
DEC CX
|
|
MOV DX,CX ; DX is length of s1
|
|
MOV DI,[BP][%PARM2]
|
|
MOV CX,-1
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
DEC CX ; CX is length of s2
|
|
CMP CX,DX
|
|
JA NOFIND ; s2 is longer than s1
|
|
MOV AX,[BP][%PARM1] ; initial s1 pointer
|
|
JCXZ FOUND ; length of s2 is zero
|
|
MOV BX,CX ; save s2 length
|
|
SUB DX,BX ; number of positions to try
|
|
INC DX
|
|
NEXTPOS MOV CX,BX ; length of s2
|
|
MOV SI,[BP][%PARM2] ; start of s2
|
|
MOV DI,AX ; current position in s1
|
|
REPZ
|
|
CMPSB ; compare
|
|
JZ FOUND ; strings match
|
|
INC AX ; try next position
|
|
DEC DX
|
|
JNZ NEXTPOS
|
|
NOFIND XOR AX,AX
|
|
FOUND POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; int stristr(s1, s2)
|
|
; char *s1, *s2;
|
|
;
|
|
; Purpose: Searches s1 for the first occurrence
|
|
; of s2 (case is ignored)
|
|
; Returns: pointer to substring if found,
|
|
; NULL if not found
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT stristr
|
|
DEF stristr
|
|
IF UPPER
|
|
DEF STRISTR
|
|
ENDIF
|
|
;
|
|
stristr equ $
|
|
STRISTR PUSH BP
|
|
MOV BP,SP
|
|
SUB SP,%2
|
|
MOV DI,[BP][%PARM1]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
CLD
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
DEC CX
|
|
MOV DX,CX ; DX is length of s1
|
|
MOV DI,[BP][%PARM2]
|
|
MOV CX,-1
|
|
REPNZ
|
|
SCASB
|
|
NOT CX
|
|
DEC CX ; CX is length of s2
|
|
CMP CX,DX
|
|
JA NOFIND ; s2 is longer than s1
|
|
MOV AX,[BP][%PARM1] ; initial s1 pointer
|
|
JCXZ FOUND ; length of s2 is zero
|
|
MOV BX,CX ; save s2 length
|
|
SUB DX,BX ; number of positions to try
|
|
INC DX
|
|
MOV [BP][%-2],DX
|
|
NEXTPOS MOV CX,BX ; length of s2
|
|
MOV SI,[BP][%PARM2] ; start of s2
|
|
MOV DI,AX ; current position in s1
|
|
COMP REPZ
|
|
CMPSB ; compare
|
|
JZ FOUND ; strings match
|
|
MOV DL,[SI][%-1]
|
|
MOV DH,[DI][%-1]
|
|
AND DX,>DFDF
|
|
CMP DL,DH
|
|
JNZ TRYNXT
|
|
CMP DL,'A'
|
|
JB TRYNXT
|
|
CMP DL,'Z'
|
|
JA TRYNXT
|
|
JCXZ FOUND
|
|
JMPS COMP
|
|
TRYNXT INC AX ; try next position
|
|
DEC [BP][%-2]
|
|
JNZ NEXTPOS
|
|
NOFIND XOR AX,AX
|
|
FOUND MOV SP,BP
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; -------------------------------------------------------
|
|
; char *strtok(s1, s2)
|
|
; char *s1, *s2;
|
|
;
|
|
; Purpose: Searches for the beginning of the next token
|
|
; in s1. A token is a sequence of one or more
|
|
; characters in s1 separated from the next token
|
|
; by a sequence of one or more characters contained
|
|
; in s2. S1 must point to a string of tokens for
|
|
; the first call to strtok. Subsequent calls
|
|
; can specify a NULL value for s1 to return the next
|
|
; token in the string.
|
|
;
|
|
; Returns: Pointer to next token in s1
|
|
; NULL if there are no more tokens in s1
|
|
; -------------------------------------------------------
|
|
;
|
|
IDT strtok
|
|
IF UPPER
|
|
DEF STRTOK
|
|
ENDIF
|
|
DEF strtok
|
|
;
|
|
DORG 0
|
|
STRPTR DW 0
|
|
ORG $
|
|
strtok equ $
|
|
STRTOK PUSH BP
|
|
MOV BP,SP
|
|
MOV DI,[BP][%PARM2]
|
|
MOV AX,DS
|
|
MOV ES,AX
|
|
CLD
|
|
MOV CX,-1
|
|
XOR AL,AL
|
|
REPNZ
|
|
SCASB ; Find length of s2
|
|
NOT CX
|
|
JCXZ NOS2 ; Return null if s2 is empty
|
|
MOV DX,CX ; save length of s2
|
|
MOV SI,[BP][%PARM1]
|
|
TEST SI,SI ; is s1 null?
|
|
JNZ NEXTCH
|
|
MOV SI,[STRPTR]
|
|
TEST SI,SI
|
|
JZ EMPTY ; no previous string
|
|
NEXTCH LODSB ; get s1 character
|
|
TEST AL,AL
|
|
JZ EMPTY ; end of s1
|
|
MOV CX,DX
|
|
MOV DI,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB ; check in delimiter set
|
|
JZ NEXTCH
|
|
MOV BX,SI ; address of first non-delimiter
|
|
DEC BX
|
|
TOKCH LODSB
|
|
TEST AL,AL
|
|
JZ ENDS1
|
|
MOV CX,DX
|
|
MOV DI,[BP][%PARM2]
|
|
REPNZ
|
|
SCASB
|
|
JNZ TOKCH ; not a delimiter
|
|
MOV [STRPTR],SI
|
|
MOV %[SI][%-1],%0 ; terminate token
|
|
MOV AX,BX
|
|
POP BP
|
|
RETSEG
|
|
EMPTY XOR AX,AX
|
|
MOV [STRPTR],AX
|
|
POP BP
|
|
RETSEG
|
|
NOS2 MOV CX,[BP][%PARM1]
|
|
MOV [STRPTR],CX
|
|
XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
ENDS1 MOV AX,BX
|
|
MOV [STRPTR],0
|
|
POP BP
|
|
RETSEG
|
|
END
|