summaryrefslogtreecommitdiffstats
path: root/private/crt32/string/i386
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/string/i386')
-rw-r--r--private/crt32/string/i386/memccpy.asm103
-rw-r--r--private/crt32/string/i386/memchr.asm96
-rw-r--r--private/crt32/string/i386/memcmp.asm101
-rw-r--r--private/crt32/string/i386/memcpy.asm354
-rw-r--r--private/crt32/string/i386/memicmp.asm132
-rw-r--r--private/crt32/string/i386/memmove.asm19
-rw-r--r--private/crt32/string/i386/memset.asm127
-rw-r--r--private/crt32/string/i386/strcat.asm155
-rw-r--r--private/crt32/string/i386/strchr.asm94
-rw-r--r--private/crt32/string/i386/strcmp.asm104
-rw-r--r--private/crt32/string/i386/strcspn.asm19
-rw-r--r--private/crt32/string/i386/strdup.asm126
-rw-r--r--private/crt32/string/i386/stricmp.asm127
-rw-r--r--private/crt32/string/i386/strlen.asm84
-rw-r--r--private/crt32/string/i386/strlwr.asm104
-rw-r--r--private/crt32/string/i386/strncat.asm117
-rw-r--r--private/crt32/string/i386/strncmp.asm120
-rw-r--r--private/crt32/string/i386/strncpy.asm108
-rw-r--r--private/crt32/string/i386/strnicmp.asm153
-rw-r--r--private/crt32/string/i386/strnset.asm104
-rw-r--r--private/crt32/string/i386/strpbrk.asm19
-rw-r--r--private/crt32/string/i386/strrchr.asm105
-rw-r--r--private/crt32/string/i386/strrev.asm121
-rw-r--r--private/crt32/string/i386/strset.asm93
-rw-r--r--private/crt32/string/i386/strspn.asm277
-rw-r--r--private/crt32/string/i386/strstr.asm135
-rw-r--r--private/crt32/string/i386/strupr.asm104
27 files changed, 3201 insertions, 0 deletions
diff --git a/private/crt32/string/i386/memccpy.asm b/private/crt32/string/i386/memccpy.asm
new file mode 100644
index 000000000..728f4ce23
--- /dev/null
+++ b/private/crt32/string/i386/memccpy.asm
@@ -0,0 +1,103 @@
+ page ,132
+ title memccpy - copy bytes until character found
+;***
+;memccpy.asm - copy bytes until a character is found
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _memccpy() - copies bytes until a specifed character
+; is found, or a maximum number of characters have been copied.
+;
+;Revision History:
+; 05-16-84 RN initial version
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 adjustments
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-17-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+; 10-27-92 SKS Avoid using a MASM keyword ("C") as a parameter name
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_memccpy(dest, src, _c, count) - copy bytes until character found
+;
+;Purpose:
+; Copies bytes from src to dest until count bytes have been
+; copied, or up to and including the character _c, whichever
+; comes first.
+;
+; Algorithm:
+; char *
+; _memccpy (dest, sorc, _c, count)
+; char *dest, *sorc, _c;
+; unsigned int count;
+; {
+; while (count && (*dest++ = *sorc++) != _c)
+; count--;
+;
+; return(count ? dest : NULL);
+; }
+;
+;Entry:
+; char *dest - pointer to memory to receive copy
+; char *src - source of bytes
+; char _c - character to stop copy at
+; int count - max number of bytes to copy
+;
+;Exit:
+; returns pointer to byte immediately after _c in dest;
+; returns NULL if _c was never found
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _memccpy
+_memccpy proc \
+ uses edi esi, \
+ dest:ptr byte, \
+ sorc:ptr byte, \
+ _c:byte, \
+ count:IWORD
+
+ mov edi,dest ; di = dest
+ mov esi,sorc ; si = source
+
+ mov ah,_c ; ah = byte to look for
+ mov ecx,count ; cx = max byte count
+ jecxz short retnull ; don't do loop if nothing to move
+
+lupe:
+ lodsb ; get byte into al and kick si
+ stosb ; store byte from al and kick di
+ cmp al,ah ; see if we just moved the byte
+ je short toend ; end of string
+
+ loop lupe ; dec cx & jmp to lupe if nonzero
+ ; else drop out & return NULL
+retnull:
+ xor edi,edi ; null pointer
+toend:
+ mov eax,edi ; return value
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_memccpy endp
+ end
diff --git a/private/crt32/string/i386/memchr.asm b/private/crt32/string/i386/memchr.asm
new file mode 100644
index 000000000..3e20583c2
--- /dev/null
+++ b/private/crt32/string/i386/memchr.asm
@@ -0,0 +1,96 @@
+ page ,132
+ title memchr - search memory for a given character
+;***
+;memchr.asm - search block of memory for a given character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines memchr() - search memory until a character is
+; found or a limit is reached.
+;
+;Revision History:
+; 05-16-84 RN initial version
+; 07-20-87 SKS rewritten for speed
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *memchr(buf, chr, cnt) - search memory for given character.
+;
+;Purpose:
+; Searched at buf for the given character, stopping when chr is
+; first found or cnt bytes have been searched through.
+;
+; Algorithm:
+; char *
+; memchr (buf, chr, cnt)
+; char *buf;
+; int chr;
+; unsigned cnt;
+; {
+; while (cnt && *buf++ != c)
+; cnt--;
+; return(cnt ? --buf : NULL);
+; }
+;
+;Entry:
+; char *buf - memory buffer to be searched
+; char chr - character to search for
+; unsigned cnt - max number of bytes to search
+;
+;Exit:
+; returns pointer to first occurence of chr in buf
+; returns NULL if chr not found in the first cnt bytes
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public memchr
+memchr proc \
+ buf:ptr, \
+ chr:byte, \
+ cnt:IWORD
+
+ xor eax,eax ; return NULL if cnt == 0
+
+ mov ecx,(cnt) ; cx = count
+ jecxz short empty
+
+ push edi ; Preserve DI
+
+ mov edi,buf ; di = buffer
+ mov al,chr ; al = search char
+
+ repne scasb ; scan for byte
+ mov eax,0 ; assume not found (ax=NULL)
+ jne short done ; not found -- return NULL
+ lea eax,[edi-1] ; found - return address of matching byte
+done:
+ pop edi ; Restore DI
+empty:
+
+ifdef _STDCALL_
+ ret DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+memchr endp
+ end
diff --git a/private/crt32/string/i386/memcmp.asm b/private/crt32/string/i386/memcmp.asm
new file mode 100644
index 000000000..cd419fd2e
--- /dev/null
+++ b/private/crt32/string/i386/memcmp.asm
@@ -0,0 +1,101 @@
+ page ,132
+ title memcmp - compare to blocks of memory
+;***
+;memcmp.asm - compare two blocks of memory
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines memcmp() - compare two memory blocks lexically and
+; find their order.
+;
+;Revision History:
+; 05-16-83 RN initial version
+; 07-20-87 SKS rewritten for speed
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int memcmp(buf1, buf2, count) - compare memory for lexical order
+;
+;Purpose:
+; Compares count bytes of memory starting at buf1 and buf2
+; and find if equal or which one is first in lexical order.
+;
+; Algorithm:
+; int
+; memcmp (buf1, buf2, count)
+; char *buf1, *buf2;
+; unsigned count;
+; {
+; if (!count)
+; return(0);
+; while (--count && *buf1 == *buf2)
+; {
+; buf1++;
+; buf2++;
+; }
+; return(*buf1 - *buf2);
+; }
+;
+;Entry:
+; char *buf1, *buf2 - pointers to memory sections to compare
+; unsigned count - length of sections to compare
+;
+;Exit:
+; returns -1 if buf1 < buf2
+; returns 0 if buf1 == buf2
+; returns +1 if buf1 > buf2
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public memcmp
+memcmp proc \
+ uses edi esi, \
+ buf1:ptr byte, \
+ buf2:ptr byte, \
+ count:IWORD
+
+ mov esi,buf1 ; si = buf1
+ mov edi,buf2 ; di = buf2
+
+;
+; choose ds:si=buf1 and es:di=buf2 so that the CARRY flag
+; gets the right way by the REP CMPSB instruction below.
+;
+ xor eax,eax
+ mov ecx,count
+ jecxz short done
+
+ repe cmpsb ; compare while equal, at most "count" bytes
+ je short done ; buf1 == buf2? (AX = 0)
+ ; buf1 < buf2 buf1 > buf2
+ sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0
+ sbb eax,-1 ; AX=-1 AX=1
+done:
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+memcmp endp
+ end
diff --git a/private/crt32/string/i386/memcpy.asm b/private/crt32/string/i386/memcpy.asm
new file mode 100644
index 000000000..4cde3cf72
--- /dev/null
+++ b/private/crt32/string/i386/memcpy.asm
@@ -0,0 +1,354 @@
+ page ,132
+ title memcpy - Copy source memory bytes to destination
+;***
+;memcpy.asm - contains memcpy and memmove routines
+;
+; Copyright (c) 1986-1991, Microsoft Corporation. All right reserved.
+;
+;Purpose:
+; memcpy() copies a source memory buffer to a destination buffer.
+; Overlapping buffers are not treated specially, so propogation may occur.
+; memmove() copies a source memory buffer to a destination buffer.
+; Overlapping buffers are treated specially, to avoid propogation.
+;
+;Revision History:
+; 02-06-87 JCR Added memmove entry
+; 04-08-87 JCR Conditionalized memmove/memcpy entries
+; 06-30-87 SKS Rewritten for speed and size
+; 08-21-87 SKS Fix return value for overlapping copies
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Minor 386 corrections/enhancements
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+; 11-13-92 SRW Make it fast with unaligned arguments
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+M_EXIT macro
+ mov eax,[dst] ; return pointer to destination
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+ endm ; M_EXIT
+
+ CODESEG
+
+page
+;***
+;memcpy - Copy source buffer to destination buffer
+;
+;Purpose:
+; memcpy() copies a source memory buffer to a destination memory buffer.
+; This routine does NOT recognize overlapping buffers, and thus can lead
+; to propogation.
+; For cases where propogation must be avoided, memmove() must be used.
+;
+; Algorithm:
+;
+; void * memcpy(void * dst, void * src, size_t count)
+; {
+; void * ret = dst;
+;
+; /*
+; * copy from lower addresses to higher addresses
+; */
+; while (count--)
+; *dst++ = *src++;
+;
+; return(ret);
+; }
+;
+;memmove - Copy source buffer to destination buffer
+;
+;Purpose:
+; memmove() copies a source memory buffer to a destination memory buffer.
+; This routine recognize overlapping buffers to avoid propogation.
+; For cases where propogation is not a problem, memcpy() can be used.
+;
+; Algorithm:
+;
+; void * memmove(void * dst, void * src, size_t count)
+; {
+; void * ret = dst;
+;
+; if (dst <= src || dst >= (src + count)) {
+; /*
+; * Non-Overlapping Buffers
+; * copy from lower addresses to higher addresses
+; */
+; while (count--)
+; *dst++ = *src++;
+; }
+; else {
+; /*
+; * Overlapping Buffers
+; * copy from higher addresses to lower addresses
+; */
+; dst += count - 1;
+; src += count - 1;
+;
+; while (count--)
+; *dst-- = *src--;
+; }
+;
+; return(ret);
+; }
+;
+;
+;Entry:
+; void *dst = pointer to destination buffer
+; const void *src = pointer to source buffer
+; size_t count = number of bytes to copy
+;
+;Exit:
+; Returns a pointer to the destination buffer in AX/DX:AX
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;*******************************************************************************
+
+ifdef MEM_MOVE
+ _MEM_ equ <memmove>
+else
+ _MEM_ equ <memcpy>
+endif
+
+% public _MEM_
+_MEM_ proc \
+ uses edi esi, \
+ dst:ptr byte, \
+ src:ptr byte, \
+ count:IWORD
+
+ ; destination pointer
+ ; source pointer
+ ; number of bytes to copy
+
+ mov esi,[src] ; esi = source
+ mov edi,[dst] ; edi = dest
+ mov ecx,[count] ; ecx = number of bytes to move
+
+;
+; Check for overlapping buffers:
+; If (dst <= src) Or (dst >= src + Count) Then
+; Do normal (Upwards) Copy
+; Else
+; Do Downwards Copy to avoid propagation
+;
+
+ cmp edi,esi ; dst <= src ?
+ jbe short CopyUp ; yes, copy toward higher addresses
+
+ mov eax,esi
+ add eax,ecx
+ cmp edi,eax ; dst >= (src + count) ?
+ jnae CopyDown ; no, copy toward lower addresses
+
+;
+; Copy toward higher addresses.
+;
+CopyUp:
+
+;
+; The algorithm for forward moves is to align the destination to a dword
+; boundary and so we can move dwords with an aligned destination. This
+; occurs in 3 steps.
+;
+; - move x = ((4 - Dest & 3) & 3) bytes
+; - move y = ((L-x) >> 2) dwords
+; - move (L - x - y*4) bytes
+;
+ test edi,11b ; destination dword aligned?
+ jnz short byterampup ; if we are not dword aligned already, align
+
+ mov edx,ecx ; byte count
+ and edx,11b ; trailing byte count
+ shr ecx,2 ; shift down to dword count
+ rep movsd ; move all of our dwords
+
+ jmp dword ptr TrailingVecs[edx*4]
+
+ align @WordSize
+TrailingVecs dd Trail0, Trail1, Trail2, Trail3
+
+ align @WordSize
+Trail3:
+ mov ax,[esi]
+ mov [edi],ax
+ mov al,[esi+2]
+ mov [edi+2],al
+
+ M_EXIT
+
+ align @WordSize
+Trail2:
+ mov ax,[esi]
+ mov [edi],ax
+
+ M_EXIT
+
+ align @WordSize
+Trail1:
+ mov al,[esi]
+ mov [edi],al
+
+Trail0:
+ M_EXIT
+
+;
+; Code to do optimal memory copies for non-dword-aligned destinations.
+;
+ align @WordSize
+byterampup:
+
+; The following length check is done for two reasons:
+;
+; 1. to ensure that the actual move length is greater than any possiale
+; alignment move, and
+;
+; 2. to skip the multiple move logic for small moves where it would
+; be faster to move the bytes with one instruction.
+;
+; Leading bytes could be handled faster via split-out optimizations and
+; a jump table (as trailing bytes are), at the cost of size.
+;
+; At this point, ECX is the # of bytes to copy, and EDX is the # of leading
+; bytes to copy.
+;
+ cmp ecx,12 ; check for reasonable length
+ jbe short ShortMove ; do short move if appropriate
+ mov edx,edi
+ neg edx
+ and edx,11b ; # of leading bytes
+ sub ecx,edx ; subtract out leading bytes
+ mov eax,ecx ; # of bytes remaining after leading
+ mov ecx,edx ; # of leading bytes
+ rep movsb ; copy leading bytes
+ mov ecx,eax ; compute number of dwords to move
+ and eax,11b ; # of trailing bytes
+ shr ecx,2 ; # of whole dwords
+ rep movsd ; move whole dwords
+ jmp dword ptr TrailingVecs[eax*4] ; copy trailing bytes
+
+;
+; Simple copy, byte at a time. This could be faster with a jump table and
+; split-out optimizations, copying as much as possible a dword/word at a
+; time and using MOV with displacements, but such short cases are unlikely
+; to be called often (it seems silly to call a function to copy less than
+; three dwords).
+;
+ align @WordSize
+ShortMove:
+ rep movsb
+
+ M_EXIT
+
+;
+; Copy down to avoid propogation in overlapping buffers.
+;
+ align @WordSize
+CopyDown:
+ std ; Set Direction Flag = Down
+ add esi,ecx ; point to byte after end of source buffer
+ add edi,ecx ; point to byte after end of dest buffer
+;
+; See if the destination start is dword aligned
+;
+
+ test edi,11b
+ jnz short byterampup_copydown ; not dword aligned
+;
+; Destination start is dword aligned
+;
+ mov edx,ecx ; set aside count of bytes to copy
+ and edx,11b ; # of trailing bytes to copy
+ sub esi,4 ; point to start of first dword to copy
+ sub edi,4 ; point to start of first dword to copy to
+ shr ecx,2 ; dwords to copy
+ rep movsd ; copy as many dwords as possible
+ jmp dword ptr TrailingVecs_copydown[edx*4] ;do any trailing bytes
+
+ align @WordSize
+TrailingVecs_copydown label dword
+ dd Trail0_copydown
+ dd Trail1_copydown
+ dd Trail2_copydown
+ dd Trail3_copydown
+
+ align @WordSize
+Trail3_copydown:
+ mov ax,[esi+2]
+ mov [edi+2],ax
+ mov al,[esi+1]
+ mov [edi+1],al
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+ align @WordSize
+Trail2_copydown:
+ mov ax,[esi+2]
+ mov [edi+2],ax
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+ align @WordSize
+Trail1_copydown:
+ mov al,[esi+3]
+ mov [edi+3],al
+Trail0_copydown:
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+;
+; Destination start is not dword aligned.
+;
+; Leading bytes could be handled faster via split-out optimizations and
+; a jump table (as trailing bytes are), at the cost of size.
+;
+; At this point, ECX is the # of bytes to copy, and EDX is the # of leading
+; bytes to copy.
+;
+ align @WordSize
+byterampup_copydown:
+ dec esi ; point to first leading src byte
+ dec edi ; point to first leading dest byte
+ cmp ecx,12 ; check for reasonable length
+ jbe short ShortMove_copydown ; do short move if appropriate
+ neg edx
+ and edx,11b
+ sub ecx,edx ; # of bytes after leading bytes
+ mov eax,ecx ; set aside # of bytes remaining
+ mov ecx,edx ; # of leading bytes
+ rep movsb ; copy leading odd bytes
+ mov ecx,eax ; # of remaining bytes
+ and eax,11b ; # of trailing bytes
+ sub esi,3 ; point to start of first whole src dword
+ sub edi,3 ; point to start of first whole dest dword
+ shr ecx,2 ; # of whole dwords
+ rep movsd ; copy whole dwords
+ jmp dword ptr TrailingVecs_copydown[eax*4]
+
+ align @WordSize
+ShortMove_copydown:
+ rep movsb
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+_MEM_ endp
+ end
+
+
diff --git a/private/crt32/string/i386/memicmp.asm b/private/crt32/string/i386/memicmp.asm
new file mode 100644
index 000000000..e87427660
--- /dev/null
+++ b/private/crt32/string/i386/memicmp.asm
@@ -0,0 +1,132 @@
+ page ,132
+ title memicmp - compare blocks of memory, ignore case
+;***
+;memicmp.asm - compare memory, ignore case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _memicmp() - compare two blocks of memory for lexical
+; order. Case is ignored in the comparison.
+;
+;Revision History:
+; 05-16-83 RN initial version
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Cleanup...
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-17-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int _memicmp(first, last, count) - compare two blocks of memory, ignore case
+;
+;Purpose:
+; Compares count bytes of the two blocks of memory stored at first
+; and last. The characters are converted to lowercase before
+; comparing (not permanently), so case is ignored in the search.
+;
+; Algorithm:
+; int
+; _memicmp (first, last, count)
+; char *first, *last;
+; unsigned count;
+; {
+; if (!count)
+; return(0);
+; while (--count && tolower(*first) == tolower(*last))
+; {
+; first++;
+; last++;
+; }
+; return(tolower(*first) - tolower(*last));
+; }
+;
+;Entry:
+; char *first, *last - memory buffers to compare
+; unsigned count - maximum length to compare
+;
+;Exit:
+; returns <0 if first < last
+; returns 0 if first == last
+; returns >0 if first > last
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _memicmp
+_memicmp proc \
+ uses edi esi ebx, \
+ first:ptr byte, \
+ last:ptr byte, \
+ count:IWORD
+
+ mov esi,[first] ; si = first
+ mov edi,[last] ; di = last
+
+ mov ecx,[count] ; cx = count
+ jecxz short toend ; if count=0, nothing to do
+
+ mov bh,'A'
+ mov bl,'Z'
+ mov dh,'a'-'A' ; add to cap to make lower
+
+lupe:
+ mov ah,[esi] ; ah = *first
+ mov al,[edi] ; al = *last
+ inc esi ; first++
+ inc edi ; last++
+ cmp ah,bh ; ah < 'A' ??
+ jb short skip1
+
+ cmp ah,bl ; ah > 'Z' ??
+ ja short skip1
+
+ add ah,dh ; make lower case
+
+skip1:
+ cmp al,bh ; al < 'A' ??
+ jb short skip2
+
+ cmp al,bl ; al > 'Z' ??
+ ja short skip2
+
+ add al,dh ; make lower case
+
+skip2:
+ cmp ah,al ; *first == *last ??
+ jne short differ ; nope, found mismatched chars
+
+ loop lupe
+ jmp short toend ; cx = 0, return 0
+
+differ:
+ mov ecx,-1 ; assume last is bigger
+ ; *** can't use "or ecx,-1" due to flags ***
+ jb short toend ; last is, in fact, bigger (return -1)
+ neg ecx ; first is bigger (return 1)
+
+toend:
+ mov eax,ecx ; move return value to ax
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_memicmp endp
+ end
diff --git a/private/crt32/string/i386/memmove.asm b/private/crt32/string/i386/memmove.asm
new file mode 100644
index 000000000..39863a1db
--- /dev/null
+++ b/private/crt32/string/i386/memmove.asm
@@ -0,0 +1,19 @@
+;***
+;memmove.asm -
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; memmove() copies a source memory buffer to a destination buffer.
+; Overlapping buffers are treated specially, to avoid propogation.
+;
+; NOTE: This stub module scheme is compatible with NT build
+; procedure.
+;
+;Revision History:
+; 09-25-91 JCR Stub module created.
+;
+;*******************************************************************************
+
+MEM_MOVE EQU 1
+INCLUDE I386\MEMCPY.ASM
diff --git a/private/crt32/string/i386/memset.asm b/private/crt32/string/i386/memset.asm
new file mode 100644
index 000000000..6a6f2ca58
--- /dev/null
+++ b/private/crt32/string/i386/memset.asm
@@ -0,0 +1,127 @@
+ page ,132
+ title memset - set sections of memory all to one byte
+;***
+;memset.asm - set a section of memory to all one byte
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; contains the memset() routine
+;
+;Revision History:
+; 05-07-84 RN initial version
+; 06-30-87 SKS faster algorithm
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Enable word alignment code for all models/CPUs,
+; Some code improvement
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-27-88 JCR More optimization (dword alignment, no ebx usage, etc)
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *memset(dst, val, count) - sets "count" bytes at "dst" to "val"
+;
+;Purpose:
+; Sets the first "count" bytes of the memory starting
+; at "dst" to the character value "val".
+;
+; Algorithm:
+; char *
+; memset (dst, val, count)
+; char *dst;
+; char val;
+; unsigned int count;
+; {
+; char *start = dst;
+;
+; while (count--)
+; *dst++ = val;
+; return(start);
+; }
+;
+;Entry:
+; char *dst - pointer to memory to fill with val
+; char val - value to put in dst bytes
+; int count - number of bytes of dst to fill
+;
+;Exit:
+; returns dst, with filled bytes
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public memset
+memset proc \
+ uses edi, \
+ dst:ptr byte, \
+ value:byte, \
+ count:IWORD
+
+ mov ecx,[count] ; cx = count
+ jecxz short toend ; if no work to do
+
+ ; set all 4 bytes of eax to [value]
+ mov al,[value] ; the byte value to be stored
+ mov ah,al ; store it as a word
+ mov edx,eax ; lo 16 bits dx=ax=val/val
+ ror eax,16 ; move val/val to hi 16-bits
+ mov ax,dx ; eax = all 4 bytes = [value]
+
+; Align address on dword boundary
+
+ mov edi,[dst] ; di = dest pointer
+ mov edx,edi ; dx = di = *dst
+ neg edx
+ and edx,(ISIZE-1) ; dx = # bytes before dword boundary
+ jz short dwords ; jump if address already aligned
+
+ cmp ecx,edx ; count >= # leading bytes??
+ jb short tail ; nope, just move ecx bytes
+
+ sub ecx,edx ; cx = adjusted count (for later)
+ xchg ecx,edx ; cx = leading byte count / dx = adjusted count
+ rep stosb ; store leading bytes
+ mov ecx,edx ; cx = count of remaining bytes
+ ;jecxz short toend ; jump out if nothing left to do
+
+; Move dword-sized blocks
+
+dwords:
+ mov edx,ecx ; save original count
+ shr ecx,ISHIFT ; cx = dword count
+ rep stos IWORD ptr [edi] ; fill 'em up
+ mov ecx,edx ; retrieve original byte count
+
+; Move remaining bytes
+
+tail: ; store remaining 1,2, or 3 bytes
+ and ecx,(ISIZE-1) ; get byte count
+ rep stosb ; store remaining bytes, if necessary
+
+; Done
+
+toend:
+ mov eax,[dst] ; return dest pointer
+
+ifdef _STDCALL_
+ ret DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+memset endp
+ end
diff --git a/private/crt32/string/i386/strcat.asm b/private/crt32/string/i386/strcat.asm
new file mode 100644
index 000000000..9781440c1
--- /dev/null
+++ b/private/crt32/string/i386/strcat.asm
@@ -0,0 +1,155 @@
+ page ,132
+ title strcat - concatenate (append) one string to another
+;***
+;strcat.asm - contains strcat() and strcpy() routines
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRCAT concatenates (appends) a copy of the source string to the
+; end of the destination string, returning the destination string.
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 07-27-88 SJM Rewritten to be 386-specific and to include strcpy
+; 08-29-88 JCR 386 cleanup...
+; 10-07-88 JCR Correct off-by-1 strcat bug; optimize ecx=-1
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+
+page
+;***
+;char *strcat(dst, src) - concatenate (append) one string to another
+;
+;Purpose:
+; Concatenates src onto the end of dest. Assumes enough
+; space in dest.
+;
+; Algorithm:
+; char * strcat (char * dst, char * src)
+; {
+; char * cp = dst;
+;
+; while( *cp )
+; ++cp; /* Find end of dst */
+; while( *cp++ = *src++ )
+; ; /* Copy src to end of dst */
+; return( dst );
+; }
+;
+;Entry:
+; char *dst - string to which "src" is to be appended
+; const char *src - string to be appended to the end of "dst"
+;
+;Exit:
+; The address of "dst" in AX/DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+page
+;***
+;char *strcpy(dst, src) - copy one string over another
+;
+;Purpose:
+; Copies the string src into the spot specified by
+; dest; assumes enough room.
+;
+; Algorithm:
+; char * strcpy (char * dst, char * src)
+; {
+; char * cp = dst;
+;
+; while( *cp++ = *src++ )
+; ; /* Copy src over dst */
+; return( dst );
+; }
+;
+;Entry:
+; char * dst - string over which "src" is to be copied
+; const char * src - string to be copied over "dst"
+;
+;Exit:
+; The address of "dst" in AX/DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;*******************************************************************************
+
+
+ CODESEG
+
+% public strcat, strcpy ; make both functions available
+
+strcat label proc ;--- strcat ---
+
+ clc ; carry clear = append
+ jmp short _docat
+
+ align @wordsize ; want to come in on a nice boundary...
+strcpy label proc ;--- strcpy ---
+
+ stc ; carry set = don't append to end of string
+ ;fall thru
+
+
+; --- Common code ---
+
+_docat proc private \
+ uses esi edi, \
+ dst:ptr byte, \
+ src:ptr byte
+
+ mov edi, dst ; di = dest pointer
+ jc short @F ; jump if not appending
+
+ ; now skip to end of destination string
+
+ xor eax, eax ; search for the null terminator
+ or ecx,-1 ; ecx = -1
+repne scasb
+ dec edi ; edi points to null terminator
+
+ ; copy source string
+
+@@: mov esi, src
+ xchg esi, edi ; now ds:esi->dst and es:edi->src
+ xor eax, eax ; search for null
+ or ecx,-1 ; ecx = -1
+
+repne scasb ; find the length of the src string
+ not ecx
+ sub edi, ecx
+ xchg esi, edi ; now es:edi->dst and ds:esi->src
+
+ mov eax, ecx
+ shr ecx, ISHIFT ; get the double-word count
+rep movsd
+ and eax, (ISIZE-1) ; get the byte cound
+ xchg ecx, eax
+rep movsb ; move remaining bytes, if any
+ mov eax, dst ; returned address
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_docat endp
+ end
diff --git a/private/crt32/string/i386/strchr.asm b/private/crt32/string/i386/strchr.asm
new file mode 100644
index 000000000..b2b6a5b56
--- /dev/null
+++ b/private/crt32/string/i386/strchr.asm
@@ -0,0 +1,94 @@
+ page ,132
+ title strchr - search string for given character
+;***
+;strchr.asm - search a string for a given character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strchr() - search a string for a character
+;
+;Revision History:
+; 10-27-83 RN initial version
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strchr(string, c) - search a string for a character
+;
+;Purpose:
+; Searches a string for a given character, which may be the
+; null character '\0'.
+;
+; Algorithm:
+; char *
+; strchr (string, ch)
+; char *string, ch;
+; {
+; while (*string && *string != ch)
+; string++;
+; if (*string == ch)
+; return(string);
+; return((char *)0);
+; }
+;
+;Entry:
+; char *string - string to search in
+; char c - character to search for
+;
+;Exit:
+; returns pointer to the first occurence of c in string
+; returns NULL if c does not occur in string
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strchr
+strchr proc \
+ uses edi, \
+ string:ptr char, \
+ chr:byte
+
+ mov edi,[string] ; edi = string
+
+ push edi ; save string pointer
+ xor eax,eax ; null byte to search for
+ mov ecx, -1
+repne scasb ; find string length by scanning for null
+ not ecx ; cx = length of string
+ mov al,[chr] ; al=byte to search for
+ pop edi ; restore saved string pointer
+repne scasb ; find that byte (if it exists)!
+ ; edi points one past byte which stopped scan
+ dec edi ; edi points to byte which stopped scan
+
+ cmp [edi],al ; take one last look to be sure
+ je short retdi ; return edi if it matches
+ xor edi,edi ; no match, so return NULL
+retdi:
+ mov eax,edi ; ret value: pointer to matching byte
+
+ifdef _STDCALL_
+ ret DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strchr endp
+ end
diff --git a/private/crt32/string/i386/strcmp.asm b/private/crt32/string/i386/strcmp.asm
new file mode 100644
index 000000000..6024848b5
--- /dev/null
+++ b/private/crt32/string/i386/strcmp.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strcmp.asm - compare two strings
+;***
+;strcmp.asm - routine to compare two strings (for equal, less, or greater)
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRCMP compares two strings and returns an integer
+; to indicate whether the first is less than the second, the two are
+; equal, or whether the first is greater than the second, respectively.
+; Comparison is done byte by byte on an UNSIGNED basis, which is to
+; say that Null (0) is less than any other character (1-255).
+;
+;Revision History:
+; 04-21-87 SKS Module rewritten to be fast and small
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;strcmp - compare two strings, returning less than, equal to, or greater than
+;
+;Purpose:
+; Compares two string, determining their lexical order. Unsigned
+; comparison is used.
+;
+; Algorithm:
+; int strcmp ( src , dst )
+; unsigned char *src;
+; unsigned char *dst;
+; {
+; int ret = 0 ;
+;
+; while( ! (ret = *src - *dst) && *dst)
+; ++src, ++dst;
+;
+; if ( ret < 0 )
+; ret = -1 ;
+; else if ( ret > 0 )
+; ret = 1 ;
+;
+; return( ret );
+; }
+;
+;Entry:
+; const char * src - string for left-hand side of comparison
+; const char * dst - string for right-hand side of comparison
+;
+;Exit:
+; AX < 0, 0, or >0, indicating whether the first string is
+; Less than, Equal to, or Greater than the second string.
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ .lall
+
+ public strcmp
+strcmp proc \
+ uses edi esi, \
+ src:ptr byte, \
+ dst:ptr byte
+
+
+ mov esi,[src] ; si = source
+ xor eax,eax ; mingle register instr with mem instr.
+ mov edi,[dst] ; di = dest
+
+ or ecx,-1 ; cx = -1
+ repne scasb ; compute length of "dst"
+ not ecx ; CX = strlen(dst)+1
+ sub edi,ecx ; restore DI = dst
+ repe cmpsb ; compare while equal, at most length of "dst"
+ je short toend ; dst == src? (AX = 0)
+ ; dst < src dst > src
+ sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0
+ sbb eax,-1 ; AX=-1 AX=1
+toend:
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strcmp endp
+ end
diff --git a/private/crt32/string/i386/strcspn.asm b/private/crt32/string/i386/strcspn.asm
new file mode 100644
index 000000000..39554147f
--- /dev/null
+++ b/private/crt32/string/i386/strcspn.asm
@@ -0,0 +1,19 @@
+;***
+;strcspn.asm -
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strcspn()- finds the length of the initial substring of
+; a string consisting entirely of characters not in a control string.
+;
+; NOTE: This stub module scheme is compatible with NT build
+; procedure.
+;
+;Revision History:
+; 09-25-91 JCR Stub module created.
+;
+;*******************************************************************************
+
+SSTRCSPN EQU 1
+INCLUDE I386\STRSPN.ASM
diff --git a/private/crt32/string/i386/strdup.asm b/private/crt32/string/i386/strdup.asm
new file mode 100644
index 000000000..04f388e4a
--- /dev/null
+++ b/private/crt32/string/i386/strdup.asm
@@ -0,0 +1,126 @@
+ page ,132
+ title strdup - duplicate string in malloc'd memory
+;***
+;strdup.asm - duplicate a string in malloc'd memory
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strdup() - grab new memory, and duplicate the string into it.
+;
+;Revision History:
+; 10-27-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+ extrn strlen:proc
+ extrn strcpy:proc
+ extrn malloc:proc
+
+
+page
+;***
+;char *_strdup(string) - duplicate string into malloc'd memory
+;
+;Purpose:
+; Allocates enough storage via malloc() for a copy of the
+; string, copies the string into the new memory, and returns
+; a pointer to it.
+;
+; Algorithm:
+; char *
+; _strdup (string)
+; char *string;
+; {
+; char *memory;
+;
+; if (!string)
+; return(NULL);
+; if (memory = malloc(strlen(string) + 1))
+; return(strcpy(memory,string));
+; return(NULL);
+; }
+;
+;Entry:
+; char *string - string to copy into new memory
+;
+;Exit:
+; returns a pointer to the newly allocated storage with the
+; string in it.
+; returns NULL if enough memory could not be allocated, or
+; string was NULL.
+;
+;Uses:
+; eax, edx
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+% public _strdup
+_strdup proc \
+ uses edi, \
+ string:ptr byte
+
+
+ mov edi,[string] ; edi=pointer to string
+ push edi ; stack parameter: string pointer
+ call strlen ; eax = string length
+
+ifndef _STDCALL_
+ pop edx ; caller cleans stack (_cdecl)
+;else
+ ; callee cleaned stack (_stdcall)
+endif
+
+ inc eax ; need space for null byte too
+ push eax ; stack parameter: string length (with null)
+ call malloc ; eax = pointer to space
+
+ifndef _STDCALL_
+ pop edx ; caller cleans stack (_cdecl)
+;else
+ ; callee cleaned stack (_stdcall)
+endif
+
+ or eax,eax ; offset == NULL ??
+ jz short toend ; error -- couldn't malloc space
+
+okay:
+ push edi ; push address of original string
+ push eax ; push address of dest string
+ ; source string addr is still on stack
+ call strcpy ; duplicate the string
+
+ifndef _STDCALL_
+ pop edx ; caller cleans stack (_cdecl)
+ pop edx
+;else
+ ; callee cleaned stack (_stdcall)
+endif
+
+ ; pointer to duplicate is in eax
+
+toend: ; eax = return value
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strdup endp
+ end
diff --git a/private/crt32/string/i386/stricmp.asm b/private/crt32/string/i386/stricmp.asm
new file mode 100644
index 000000000..80f384701
--- /dev/null
+++ b/private/crt32/string/i386/stricmp.asm
@@ -0,0 +1,127 @@
+ page ,132
+ title stricmp
+;***
+;strcmp.asm - contains case-insensitive string comparision routine
+; _stricmp/_strcmpi
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; contains _stricmpi(), also known as _strcmpi()
+;
+;Revision History:
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-10-88 JCR Added strcmpi() entry for compatiblity with early revs
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-27-88 JCR Shuffled regs so no need to save/restore ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int _stricmp(dst, src), _strcmpi(dst, src) - compare strings, ignore case
+;
+;Purpose:
+; _stricmp/_strcmpi perform a case-insensitive string comparision.
+; For differences, upper case letters are mapped to lower case.
+; Thus, "abc_" < "ABCD" since "_" < "d".
+;
+; Algorithm:
+;
+; int _strcmpi (char * dst, char * src)
+; {
+; int f,l;
+;
+; do {
+; f = tolower(*dst);
+; l = tolower(*src);
+; dst++;
+; src++;
+; } while (f && f == l);
+;
+; return(f - l);
+; }
+;
+;Entry:
+; char *dst, *src - strings to compare
+;
+;Exit:
+; AX = -1 if dst < src
+; AX = 0 if dst = src
+; AX = +1 if dst > src
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strcmpi ; alternate entry point for compatibility
+_strcmpi label proc
+
+ public _stricmp
+_stricmp proc \
+ uses esi, \
+ dst:ptr, \
+ src:ptr
+
+
+ mov esi,[src] ; SI = src
+ mov edx,[dst] ; DX = dst
+ mov al,-1 ; fall into loop
+
+chk_null:
+ or al,al
+ jz short done
+again:
+ lodsb ; al = next source byte
+ mov ah,[edx] ; ah = next dest byte
+ inc edx
+
+ cmp ah,al ; first try case-sensitive comparision
+ je short chk_null ; match
+
+ sub al,'A'
+ cmp al,'Z'-'A'+1
+ sbb cl,cl
+ and cl,'a'-'A'
+ add al,cl
+ add al,'A' ; tolower(*dst)
+
+ xchg ah,al ; operations on AL are shorter than AH
+
+ sub al,'A'
+ cmp al,'Z'-'A'+1
+ sbb cl,cl
+ and cl,'a'-'A'
+ add al,cl
+ add al,'A' ; tolower(*src)
+
+ cmp al,ah ; inverse of above comparison -- AL & AH are swapped
+ je short chk_null
+ ; dst < src dst > src
+ sbb al,al ; AL=-1, CY=1 AL=0, CY=0
+ sbb al,-1 ; AL=-1 AL=1
+done:
+ movsx eax,al ; extend al to eax
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_stricmp endp
+ end
diff --git a/private/crt32/string/i386/strlen.asm b/private/crt32/string/i386/strlen.asm
new file mode 100644
index 000000000..4ea531018
--- /dev/null
+++ b/private/crt32/string/i386/strlen.asm
@@ -0,0 +1,84 @@
+ page ,132
+ title strlen - return the length of a null-terminated string
+;***
+;strlen.asm - contains strlen() routine
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; strlen returns the length of a null-terminated string,
+; not including the null byte itself.
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-02-88 SJM Add 32 bit code, use cruntime vs cmacros
+; 08-23-88 JCR 386 cleanup
+; 10-05-88 GJF Fixed off-by-2 error.
+; 10-10-88 JCR Minor improvement
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;strlen - return the length of a null-terminated string
+;
+;Purpose:
+; Finds the length in bytes of the given string, not including
+; the final null character.
+;
+; Algorithm:
+; int strlen (const char * str)
+; {
+; int length = 0;
+;
+; while( *str++ )
+; ++length;
+;
+; return( length );
+; }
+;
+;Entry:
+; const char * str - string whose length is to be computed
+;
+;Exit:
+; AX = length of the string "str", exclusive of the final null byte
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strlen
+strlen proc \
+ uses edi, \
+ string:ptr byte
+
+ mov edi,string ; edi -> string
+ xor eax,eax ; null byte
+ or ecx,-1 ; set ecx to -1
+repne scasb ; scan for null, ecx = -(1+strlen(str))
+ not ecx
+ dec ecx ; ecx = strlen(str)
+ mov eax,ecx ; eax = strlen(str)
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strlen endp
+ end
diff --git a/private/crt32/string/i386/strlwr.asm b/private/crt32/string/i386/strlwr.asm
new file mode 100644
index 000000000..edec61eb3
--- /dev/null
+++ b/private/crt32/string/i386/strlwr.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strlwr - map string to lower-case
+;***
+;strlwr.asm - routine to map lower-case characters in a string to upper-case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRLWR converts upper-case characters in a null-terminated string
+; to their lower-case equivalents. Conversion is done in place and
+; characters other than upper-case letters are not modified.
+;
+; This function modifies only 7-bit ASCII characters
+; in the range 0x41 through 0x5A ('A' through 'Z').
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Minor optimization
+; 10-10-88 JCR Changed an 'xchg' to 'mov'
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strlwr(string) - map upper-case characters in a string to lower-case
+;
+;Purpose:
+; Converts all the upper case characters in a string to lower case,
+; in place.
+;
+; Algorithm:
+; char * _strlwr (char * string)
+; {
+; char * cp = string;
+;
+; while( *cp )
+; {
+; if ('A' <= *cp && *cp <= 'Z')
+; *cp += 'a' - 'A';
+; ++cp;
+; }
+; return(string);
+; }
+;
+;Entry:
+; char *string - string to change to lower case
+;
+;Exit:
+; The input string address is returned in AX or DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strlwr
+_strlwr proc \
+ string:ptr byte
+
+
+ mov ecx,[string] ; ecx = *string
+ mov edx,ecx ; save return value
+ jmp short first_char; jump into the loop
+
+ align @WordSize
+check_char:
+ sub al,'A' ; 'A' <= al <= 'Z' ?
+ cmp al,'Z'-'A'+1
+ jnb short next_char
+ add al,'a' ; map to lower case
+ mov [ecx],al ; and store new value
+next_char:
+ inc ecx ; bump pointer
+first_char:
+ mov al,[ecx] ; get next character
+ or al,al
+ jnz short check_char
+
+done:
+ mov eax,edx ; AX = return value ("string")
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strlwr endp
+ end
diff --git a/private/crt32/string/i386/strncat.asm b/private/crt32/string/i386/strncat.asm
new file mode 100644
index 000000000..b6060bb12
--- /dev/null
+++ b/private/crt32/string/i386/strncat.asm
@@ -0,0 +1,117 @@
+ page ,132
+ title strncat - append n chars of string1 to string2
+;***
+;strncat.asm - append n chars of string to new string
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strncat() - appends n characters of string onto
+; end of other string
+;
+;Revision History:
+; 10-25-83 RN initial version
+; 08-05-87 SKS Fixed bug: extra null was stored if n > strlen(back)
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strncat(front, back, count) - append count chars of back onto front
+;
+;Purpose:
+; Appends at most count characters of the string back onto the
+; end of front, and ALWAYS terminates with a null character.
+; If count is greater than the length of back, the length of back
+; is used instead. (Unlike strncpy, this routine does not pad out
+; to count characters).
+;
+; Algorithm:
+; char *
+; strncat (front, back, count)
+; char *front, *back;
+; unsigned count;
+; {
+; char *start = front;
+;
+; while (*front++)
+; ;
+; front--;
+; while (count--)
+; if (!(*front++ = *back++))
+; return(start);
+; *front = '\0';
+; return(start);
+; }
+;
+;Entry:
+; char *front - string to append onto
+; char *back - string to append
+; unsigned count - count of max characters to append
+;
+;Exit:
+; returns a pointer to string appended onto (front).
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strncat
+strncat proc \
+ uses edi esi, \
+ front:ptr byte, \
+ back:ptr byte, \
+ count:IWORD
+
+
+ mov edi,[front] ; di=pointer to dest
+
+ mov edx,edi ; save return value in dx
+ xor eax,eax ; search value: null byte (assumed zero below!)
+ or ecx,-1 ; cx = -1, so won't stop scan
+repne scasb ; find null byte
+ dec edi ; di points to dest null terminator
+ mov esi,edi ; si " " " " "
+
+ mov edi,[back] ; di points to source
+
+ push edi ; save back pointer
+ mov ecx,[count] ; cx = count bytes negatively
+repne scasb ; find null byte & get source length
+ jne short nonull
+ inc ecx ; do NOT count null byte in length
+nonull:
+ ; cx=count of difference in bytes in source
+ ; with reference (without null)
+ sub ecx,[count] ; take the difference of bytes counted to expected
+ neg ecx ; away from expected
+ mov edi,esi ; di=pointer to dest null terminator
+ pop esi ; restore pointer to source
+rep movsb ; concatenate the strings
+ ; WARNING: AL must be zero at this point!
+ stosb ; attach null byte
+
+ mov eax,edx ; return value: dest addr
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strncat endp
+ end
diff --git a/private/crt32/string/i386/strncmp.asm b/private/crt32/string/i386/strncmp.asm
new file mode 100644
index 000000000..15b187651
--- /dev/null
+++ b/private/crt32/string/i386/strncmp.asm
@@ -0,0 +1,120 @@
+ page ,132
+ title strncmp - compare first n chars of two strings
+;***
+;strncmp.asm - compare first n characters of two strings
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strncmp() - compare first n characters of two strings
+; for lexical order.
+;
+;Revision History:
+; 10-26-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int strncmp(first, last, count) - compare first count chars of strings
+;
+;Purpose:
+; Compares two strings for lexical order. The comparison stops
+; after: (1) a difference between the strings is found, (2) the end
+; of the strings is reached, or (3) count characters have been
+; compared.
+;
+; Algorithm:
+; int
+; strncmp (first, last, count)
+; char *first, *last;
+; unsigned count;
+; {
+; if (!count)
+; return(0);
+; while (--count && *first && *first == *last)
+; {
+; first++;
+; last++;
+; }
+; return(*first - *last);
+; }
+;
+;Entry:
+; char *first, *last - strings to compare
+; unsigned count - maximum number of characters to compare
+;
+;Exit:
+; returns <0 if first < last
+; returns 0 if first == last
+; returns >0 if first > last
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strncmp
+strncmp proc \
+ uses edi esi ebx, \
+ first:ptr byte, \
+ last:ptr byte, \
+ count:IWORD
+
+
+ mov ecx,[count] ; cx=max number of bytes to compare
+ jecxz short toend ; it's as if strings are equal
+
+ mov ebx,ecx ; bx saves count
+
+ mov edi,[first] ; di=first pointer (es=segment part)
+
+ mov esi,edi ; si saves first pointer
+ xor eax,eax ; ax=0
+repne scasb ; count bytes
+ neg ecx ; cx=count - strlen
+ add ecx,ebx ; strlen + count - strlen
+
+okay:
+ mov edi,esi ; restore first pointer
+ mov esi,[last] ; si = last pointer
+repe cmpsb ; compare strings
+ mov al,[esi-1]
+ xor ecx,ecx ; set return value = 0
+
+ cmp al,[edi-1] ; last-first
+ ja short lastbig ; <last is bigger>
+ je short toend ; <equal>
+ ;jb short firstbig ; <first is bigger>
+
+firstbig:
+ dec ecx ; first string is bigger
+ dec ecx ; make FFFE so 'not' will give 0001
+
+lastbig: ; last string is bigger
+ not ecx ; return -1
+
+toend:
+ mov eax,ecx ; return value
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strncmp endp
+ end
diff --git a/private/crt32/string/i386/strncpy.asm b/private/crt32/string/i386/strncpy.asm
new file mode 100644
index 000000000..fcf882553
--- /dev/null
+++ b/private/crt32/string/i386/strncpy.asm
@@ -0,0 +1,108 @@
+ page ,132
+ title strncpy - copy at most n characters of string
+;***
+;strncpy.asm - copy at most n characters of string
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strncpy() - copy at most n characters of string
+;
+;Revision History:
+; 10-25-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strncpy(dest, source, count) - copy at most n characters
+;
+;Purpose:
+; Copies count characters from the source string to the
+; destination. If count is less than the length of source,
+; NO NULL CHARACTER is put onto the end of the copied string.
+; If count is greater than the length of sources, dest is padded
+; with null characters to length count.
+;
+; Algorithm:
+; char *
+; strncpy (dest, source, count)
+; char *dest, *source;
+; unsigned count;
+; {
+; char *start = dest;
+;
+; while (count && (*dest++ = *source++))
+; count--;
+; if (count)
+; while (--count)
+; *dest++ = '\0';
+; return(start);
+; }
+;
+;Entry:
+; char *dest - pointer to spot to copy source, enough space
+; is assumed.
+; char *source - source string for copy
+; unsigned count - characters to copy
+;
+;Exit:
+; returns dest, with the character copied there.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strncpy
+strncpy proc \
+ uses edi esi, \
+ dest:ptr byte, \
+ sorc:ptr byte, \
+ count:IWORD
+
+
+ mov edi,[dest] ; di=pointer to dest
+ mov esi,[sorc] ; si=pointer to source
+
+ mov edx,edi ; dx saves dest pointer
+ mov ecx,[count] ; get the max char count
+ jecxz short toend ; don't do loop if nothing to move
+
+lupe:
+ lodsb ; get byte into al and kick si
+ or al,al ; see if we just moved a null
+ jz short outlupe ; end of string
+
+ stosb ; store byte from al and kick di
+ loop lupe ; dec cx & jmp to lupe if nonzero
+ ; else drop out
+outlupe:
+ xor al,al ; null byte to store
+rep stosb ; store null for all cx>0
+
+toend:
+ mov eax,edx ; return value: dest addr
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strncpy endp
+ end
diff --git a/private/crt32/string/i386/strnicmp.asm b/private/crt32/string/i386/strnicmp.asm
new file mode 100644
index 000000000..cec5ec5a6
--- /dev/null
+++ b/private/crt32/string/i386/strnicmp.asm
@@ -0,0 +1,153 @@
+ page ,132
+ title strnicmp - compare n chars of strings, ignore case
+;***
+;strnicmp.asm - compare n chars of strings, ignoring case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strnicmp() - Compares at most n characters of two strings,
+; without regard to case.
+;
+;Revision History:
+; 04-04-85 RN initial version
+; 07-11-85 TC zeroed cx, to allow correct return value if not equal
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup and improved return value sequence
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+
+page
+;***
+;int _strnicmp(first, last, count) - compares count char of strings, ignore case
+;
+;Purpose:
+; Compare the two strings for lexical order. Stops the comparison
+; when the following occurs: (1) strings differ, (2) the end of the
+; strings is reached, or (3) count characters have been compared.
+; For the purposes of the comparison, upper case characters are
+; converted to lower case.
+;
+; Algorithm:
+; int
+; _strncmpi (first, last, count)
+; char *first, *last;
+; unsigned int count;
+; {
+; int f,l;
+; int result = 0;
+;
+; if (count) {
+; do {
+; f = tolower(*first);
+; l = tolower(*last);
+; first++;
+; last++;
+; } while (--count && f && l && f == l);
+; result = f - l;
+; }
+; return(result);
+; }
+;
+;Entry:
+; char *first, *last - strings to compare
+; unsigned count - maximum number of characters to compare
+;
+;Exit:
+; returns <0 if first < last
+; returns 0 if first == last
+; returns >0 if first > last
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strnicmp
+_strnicmp proc \
+ uses edi esi ebx, \
+ first:ptr byte, \
+ last:ptr byte, \
+ count:IWORD
+
+
+ mov esi,[first] ; si = first string
+ mov edi,[last] ; di = last string
+
+ mov ecx,[count] ; cx = byte count
+ jecxz short toend ; if count=0
+
+ mov bh,'A'
+ mov bl,'Z'
+ mov dh,'a'-'A' ; add to cap to make lower
+
+lupe:
+ mov ah,[esi] ; *first
+ mov al,[edi] ; *last
+
+ or ah,ah ; see if *first is null
+ jz short eject ; jump if so
+
+ or al,al ; see if *last is null
+ jz short eject ; jump if so
+
+ inc esi ; first++
+ inc edi ; last++
+
+ cmp ah,bh ; 'A'
+ jb short skip1
+
+ cmp ah,bl ; 'Z'
+ ja short skip1
+
+ add ah,dh ; make lower case
+
+skip1:
+ cmp al,bh ; 'A'
+ jb short skip2
+
+ cmp al,bl ; 'Z'
+ ja short skip2
+
+ add al,dh ; make lower case
+
+skip2:
+ cmp ah,al ; *first == *last ??
+ jne short differ
+
+ loop lupe
+
+eject:
+ xor ecx,ecx
+ cmp ah,al ; compare the (possibly) differing bytes
+ je short toend ; both zero; return 0
+
+differ:
+ mov ecx,-1 ; assume last is bigger (* can't use 'or' *)
+ jb short toend ; last is, in fact, bigger (return -1)
+ neg ecx ; first is bigger (return 1)
+
+toend:
+ mov eax,ecx
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strnicmp endp
+ end
diff --git a/private/crt32/string/i386/strnset.asm b/private/crt32/string/i386/strnset.asm
new file mode 100644
index 000000000..ae8a1248d
--- /dev/null
+++ b/private/crt32/string/i386/strnset.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strnset - set first n characters to one char.
+;***
+;strnset.asm - set first n characters to single character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strnset() - sets at most the first n characters of a string
+; to a given character.
+;
+;Revision History:
+; 11-18-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 05-23-88 WAJ If count = strlen(string)+1 then strlen+1 bytes were set.
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strnset(string, val, count) - set at most count characters to val
+;
+;Purpose:
+; Sets the first count characters of string the character value.
+; If the length of string is less than count, the length of
+; string is used in place of n.
+;
+; Algorithm:
+; char *
+; _strnset (string, val, count)
+; char *string,val;
+; unsigned int count;
+; {
+; char *start = string;
+;
+; while (count-- && *string)
+; *string++ = val;
+; return(start);
+; }
+;
+;Entry:
+; char *string - string to set characters in
+; char val - character to fill with
+; unsigned count - count of characters to fill
+;
+;Exit:
+; returns string, now filled with count copies of val.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strnset
+_strnset proc \
+ uses edi ebx, \
+ string:ptr byte, \
+ val:byte, \
+ count:IWORD
+
+
+ mov edi,[string] ; di = string
+ mov edx,edi ; dx=string addr; save return value
+ mov ebx,[count] ; cx = max chars to set
+ xor eax,eax ; null byte
+ mov ecx,ebx
+ jecxz short done ; zero length specified
+
+repne scasb ; find null byte & count bytes in cx
+ jne short nonull ; null not found
+ inc ecx ; don't want the null
+
+nonull:
+ sub ebx,ecx ; bx=strlen (not null)
+ mov ecx,ebx ; cx=strlen (not null)
+
+ mov edi,edx ; restore string pointer
+ mov al,val ; byte value
+rep stosb ; fill 'er up
+
+done:
+ mov eax,edx ; return value: string addr
+
+ifdef _STDCALL_
+ ret DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strnset endp
+ end
diff --git a/private/crt32/string/i386/strpbrk.asm b/private/crt32/string/i386/strpbrk.asm
new file mode 100644
index 000000000..1ccde4d0b
--- /dev/null
+++ b/private/crt32/string/i386/strpbrk.asm
@@ -0,0 +1,19 @@
+;***
+;strpbrk.asm -
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strpbrk()- finds the index of the first character in a string
+; that is not in a control string
+;
+; NOTE: This stub module scheme is compatible with NT build
+; procedure.
+;
+;Revision History:
+; 09-25-91 JCR Stub module created.
+;
+;*******************************************************************************
+
+SSTRPBRK EQU 1
+INCLUDE I386\STRSPN.ASM
diff --git a/private/crt32/string/i386/strrchr.asm b/private/crt32/string/i386/strrchr.asm
new file mode 100644
index 000000000..3808b7b8b
--- /dev/null
+++ b/private/crt32/string/i386/strrchr.asm
@@ -0,0 +1,105 @@
+ page ,132
+ title strrchr - find last occurence of character in string
+;***
+;strrchr.asm - find last occurrence of character in string
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strrchr() - find the last occurrence of a given character
+; in a string.
+;
+;Revision History:
+; 10-27-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strrchr(string, ch) - find last occurrence of ch in string
+;
+;Purpose:
+; Finds the last occurrence of ch in string. The terminating
+; null character is used as part of the search.
+;
+; Algorithm:
+; char *
+; strrchr (string, ch)
+; char *string, ch;
+; {
+; char *start = string;
+;
+; while (*string++)
+; ;
+; while (--string != start && *string != ch)
+; ;
+; if (*string == ch)
+; return(string);
+; return(NULL);
+; }
+;
+;Entry:
+; char *string - string to search in
+; char ch - character to search for
+;
+;Exit:
+; returns a pointer to the last occurrence of ch in the given
+; string
+; returns NULL if ch does not occurr in the string
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strrchr
+strrchr proc \
+ uses edi, \
+ string:ptr byte, \
+ chr:byte
+
+ mov edi,[string] ; di = string
+ xor eax,eax ; al=null byte
+ or ecx,-1 ; cx = -1
+repne scasb ; find the null & count bytes
+ inc ecx ; cx=-byte count (with null)
+ neg ecx ; cx=+byte count (with null)
+ dec edi ; di points to terminal null
+ mov al,chr ; al=search byte
+ std ; count 'down' on string this time
+repne scasb ; find that byte
+ inc edi ; di points to byte which stopped scan
+
+ cmp [edi],al ; see if we have a hit
+ je short returndi ; yes, point to byte
+
+ xor eax,eax ; no, return NULL
+ jmp short toend ; do return sequence
+
+returndi:
+ mov eax,edi ; ax=pointer to byte
+
+toend:
+ cld
+
+ifdef _STDCALL_
+ ret DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strrchr endp
+ end
diff --git a/private/crt32/string/i386/strrev.asm b/private/crt32/string/i386/strrev.asm
new file mode 100644
index 000000000..09071834e
--- /dev/null
+++ b/private/crt32/string/i386/strrev.asm
@@ -0,0 +1,121 @@
+ page ,132
+ title strrev - reverse a string in place
+;***
+;strrev.asm - reverse a string in place
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strrev() - reverse a string in place (not including
+; '\0' character)
+;
+;Revision History:
+; 10-26-83 RN initial version
+; 07-16-87 JCR Added check for empty string (fixes large model bug)
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup, minor alterations
+; 10-26-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strrev(string) - reverse a string in place
+;
+;Purpose:
+; Reverses the order of characters in the string. The terminating
+; null character remains in place.
+;
+; Algorithm:
+; char *
+; _strrev (string)
+; char *string;
+; {
+; char *start = string;
+; char *left = string;
+; char ch;
+;
+; while (*string++)
+; ;
+; string -= 2;
+; while (left < string)
+; {
+; ch = *left;
+; *left++ = *string;
+; *string-- = ch;
+; }
+; return(start);
+; }
+;
+; NOTE: There is a check for an empty string in the following code.
+; Normally, this would fall out of the "cmp si,di" instruction in the
+; loop portion of the routine. However, if the offset of the empty
+; string is 0 (as it could be in large model), then the cmp does not
+; catch the empty string and the routine essentially hangs (i.e., loops
+; moving bytes one at a time FFFFh times). An explicit empty string
+; check corrects this.
+;
+;Entry:
+; char *string - string to reverse
+;
+;Exit:
+; returns string - now with reversed characters
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strrev
+_strrev proc \
+ uses edi esi, \
+ string:ptr byte
+
+ mov edi,[string] ; di = string
+ mov edx,edi ; dx=pointer to string; save return value
+
+ mov esi,edi ; si=pointer to string
+ xor eax,eax ; search value (null)
+ or ecx,-1 ; cx = -1
+repne scasb ; find null
+ cmp ecx,-2 ; is string empty? (if offset value is 0, the
+ je short done ; cmp below will not catch it and we'll hang).
+
+ dec edi ; string is not empty, move di pointer back
+ dec edi ; di points to last non-null byte
+
+lupe:
+ cmp esi,edi ; see if pointers have crossed yet
+ jae short done ; exit when pointers meet (or cross)
+
+ mov ah,[esi] ; get front byte...
+ mov al,[edi] ; and end byte
+ mov [esi],al ; put end byte in front...
+ mov [edi],ah ; and front byte at end
+ inc esi ; front moves up...
+ dec edi ; and end moves down
+ jmp short lupe ; keep switching bytes
+
+done:
+ mov eax,edx ; return value: string addr
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strrev endp
+ end
diff --git a/private/crt32/string/i386/strset.asm b/private/crt32/string/i386/strset.asm
new file mode 100644
index 000000000..8446a0812
--- /dev/null
+++ b/private/crt32/string/i386/strset.asm
@@ -0,0 +1,93 @@
+ page ,132
+ title strset - set all characters of string to character
+;***
+;strset.asm - sets all charcaters of string to given character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strset() - sets all of the characters in a string (except
+; the '\0') equal to a given character.
+;
+;Revision History:
+; 11-18-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strset(string, val) - sets all of string to val
+;
+;Purpose:
+; Sets all of characters in string (except the terminating '/0'
+; character) equal to val.
+;
+; Algorithm:
+; char *
+; _strset (string, val)
+; char *string;
+; char val;
+; {
+; char *start = string;
+;
+; while (*string)
+; *string++ = val;
+; return(start);
+; }
+;
+;Entry:
+; char *string - string to modify
+; char val - value to fill string with
+;
+;Exit:
+; returns string -- now filled with val's
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strset
+_strset proc \
+ uses edi, \
+ string:ptr byte, \
+ val:byte
+
+
+ mov edi,[string] ; di = string
+ mov edx,edi ; dx=string addr; save return value
+
+ xor eax,eax ; ax = 0
+ or ecx,-1 ; cx = -1
+repne scasb ; scan string & count bytes
+ inc ecx
+ inc ecx ; cx=-strlen
+ neg ecx ; cx=strlen
+ mov al,[val] ; al = byte value to store
+ mov edi,edx ; di=string addr
+rep stosb
+
+ mov eax,edx ; return value: string addr
+
+ifdef _STDCALL_
+ ret DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strset endp
+ end
diff --git a/private/crt32/string/i386/strspn.asm b/private/crt32/string/i386/strspn.asm
new file mode 100644
index 000000000..803e4a223
--- /dev/null
+++ b/private/crt32/string/i386/strspn.asm
@@ -0,0 +1,277 @@
+ page ,132
+ title strspn - search for init substring of chars from control str
+;***
+;strspn.asm - find length of initial substring of chars from a control string
+;
+; Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strspn() - finds the length of the initial substring of
+; a string consisting entirely of characters from a control string.
+;
+; defines strcspn()- finds the length of the initial substring of
+; a string consisting entirely of characters not in a control string.
+;
+; defines strpbrk()- finds the index of the first character in a string
+; that is not in a control string
+;
+;Revision History:
+; 10-28-83 RN initial version
+; 06-30-87 SKS Faster version -- also reentrant
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-02-88 SJM Created 386-specific version.
+; 08-23-88 JCR 386 cleanup
+; 10-10-88 JCR Misc bug fixes
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+; 09-25-91 JCR Build "strspn" if no other directives are given
+; 01-17-92 GJF Fixed build of "strspn".
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int strspn(string, control) - find init substring of control chars
+;
+;Purpose:
+; Finds the index of the first character in string that does belong
+; to the set of characters specified by control. This is
+; equivalent to the length of the initial substring of string that
+; consists entirely of characters from control. The '\0' character
+; that terminates control is not considered in the matching process.
+;
+; Algorithm:
+; int
+; strspn (string, control)
+; unsigned char *string, *control;
+; {
+; unsigned char map[32];
+; int count;
+;
+; for (count = 0; count < 32; count++)
+; map[count] = 0;
+; while (*control)
+; {
+; map[*control >> 3] |= (1 << (*control & 7));
+; control++;
+; }
+; if (*string)
+; {
+; while (map[*string >> 3] & (1 << (*string & 7)))
+; {
+; count++;
+; string++;
+; }
+; return(count);
+; }
+; return(0);
+; }
+;
+;Entry:
+; char *string - string to search
+; char *control - string containing characters not to search for
+;
+;Exit:
+; returns index of first char in string not in control
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+;***
+;int strcspn(string, control) - search for init substring w/o control chars
+;
+;Purpose:
+; returns the index of the first character in string that belongs
+; to the set of characters specified by control. This is equivalent
+; to the length of the length of the initial substring of string
+; composed entirely of characters not in control. Null chars not
+; considered.
+;
+; Algorithm:
+; int
+; strcspn (string, control)
+; unsigned char *string, *control;
+; {
+; unsigned char map[32];
+; int count;
+;
+; for (count = 0; count < 32; count++)
+; map[count] = 0;
+; while (*control)
+; {
+; map[*control >> 3] |= (1 << (*control & 7));
+; control++;
+; }
+; map[0] |= 1;
+; while (!(map[*string >> 3] & (1 << (*string & 7))))
+; {
+; count++;
+; string++;
+; }
+; return(count);
+; }
+;
+;Entry:
+; char *string - string to search
+; char *control - set of characters not allowed in init substring
+;
+;Exit:
+; returns the index of the first char in string
+; that is in the set of characters specified by control.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+;***
+;char *strpbrk(string, control) - scans string for a character from control
+;
+;Purpose:
+; Finds the first occurence in string of any character from
+; the control string.
+;
+; Algorithm:
+; char *
+; strpbrk (string, control)
+; unsigned char *string, *control;
+; {
+; unsigned char map[32];
+; int count;
+;
+; for (count = 0; count < 32; count++)
+; map[count] = 0;
+; while (*control)
+; {
+; map[*control >> 3] |= (1 << (*control & 7));
+; control++;
+; }
+; while (*string)
+; {
+; if (map[*string >> 3] & (1 << (*string & 7)))
+; return(string);
+; string++;
+; }
+; return(NULL);
+; }
+;
+;Entry:
+; char *string - string to search in
+; char *control - string containing characters to search for
+;
+;Exit:
+; returns a pointer to the first character from control found
+; in string.
+; returns NULL if string and control have no characters in common.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+
+ifdef SSTRCSPN
+
+ _STRSPN_ equ <strcspn>
+
+elseifdef SSTRPBRK
+
+ _STRSPN_ equ <strpbrk>
+
+else
+
+; Default is to build strspn()
+
+ SSTRSPN equ 1
+ _STRSPN_ equ <strspn>
+
+endif
+
+% public _STRSPN_
+
+ CODESEG
+
+_STRSPN_ proc \
+ uses edi esi, \
+ string:ptr byte, \
+ control:ptr byte
+
+ local map[8]:dword ; 8*4*8 = 256 bits
+
+; Zero out char bit map
+
+ mov ecx, 8 ; clear the 256 bits
+ xor eax, eax
+ lea edi, [map]
+rep stosd
+
+; Set control char bits in map
+
+ mov esi,control ; si = control string
+
+ align @WordSize
+lab listnext ; init char bit map
+ lodsb
+ or al,al
+ jz short listdone
+ bts map, eax
+ jmp short listnext
+
+lab listdone
+
+; Loop through comparing source string with control bits
+
+ mov esi, string ; si = string
+
+_ifnd SSTRPBRK <dec ecx> ; set ecx to -1
+
+ align @WordSize
+lab dstnext
+
+_ifnd SSTRPBRK <inc ecx>
+
+ lodsb
+ or al,al
+ jz short dstdone
+ bt map, eax
+
+ifdef SSTRSPN
+ jc short dstnext ; strspn: found char, continue
+elseifdef SSTRCSPN
+ jnc short dstnext ; strcspn: did not find char, continue
+elseifdef SSTRPBRK
+ jnc short dstnext ; strpbrk: did not find char, continue
+ lea eax,[esi-1] ; found char, return address of it
+ jmp short done
+endif
+
+; Return code
+
+lab dstdone
+
+ifndef SSTRPBRK
+ mov eax,ecx ; strspn/strcspn: return index
+else
+ xor eax,eax ; strpbrk: no chars in common, return NULL
+done:
+
+endif
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_STRSPN_ endp
+ end
diff --git a/private/crt32/string/i386/strstr.asm b/private/crt32/string/i386/strstr.asm
new file mode 100644
index 000000000..81a9b76bd
--- /dev/null
+++ b/private/crt32/string/i386/strstr.asm
@@ -0,0 +1,135 @@
+ page ,132
+ title strstr - search for one string inside another
+;***
+;strstr.asm - search for one string inside another
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strstr() - search for one string inside another
+;
+;Revision History:
+; 02-02-88 SKS Rewritten from scratch. Now works correctly with
+; strings > 32 KB in length. Also smaller and faster.
+; 03-01-88 SKS Ensure that ES = DS right away (Small/Medium models)
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-18-88 PHG Corrected return value when src is empty string
+; to conform with ANSI.
+; 08-23-88 JCR Minor 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strstr(string1, string2) - search for string2 in string1
+;
+;Purpose:
+; finds the first occurrence of string2 in string1
+;
+;Entry:
+; char *string1 - string to search in
+; char *string2 - string to search for
+;
+;Exit:
+; returns a pointer to the first occurrence of string2 in
+; string1, or NULL if string2 does not occur in string1
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strstr
+strstr proc \
+ uses esi edi ebx, \
+ dst:ptr byte, \
+ src:ptr byte
+
+ local srclen:IWORD
+
+
+ mov edi, (src) ; di = src
+ xor eax,eax ; Scan for null at end of (src)
+ or ecx,-1 ; cx = -1
+repnz scasb
+ not ecx
+ dec ecx
+ jecxz short empty_src ; src == "" ?
+ dec ecx ; CX = strlen(src)-1
+ mov (srclen),ecx
+
+ mov edi,(dst)
+ mov ebx,edi ; BX will keep the current offset into (dst)
+
+ xor eax,eax ; Scan for null at end of (dst)
+ or ecx,-1 ; cx = -1
+repnz scasb
+ not ecx
+ dec ecx ; CX = strlen(dst)
+
+ mov edx,ecx ; Save strlen(dst) in DX
+
+ sub edx,(srclen) ; DX = strlen(dst) - (strlen(src)-1)
+ jbe short not_found ; strlen(dst) <= (strlen(src)-1)
+ ; target is longer than source?
+ mov edi,ebx ; restore ES:DI = (dst)
+
+findnext:
+ mov esi,IWORD ptr (src)
+ lodsb ; Get the first byte of the source
+ mov edi,ebx ; restore position in source
+ mov ecx,edx ; count of possible starting bytes in src
+;
+; CX, DX = number of bytes left in source where target can still fit
+; DI, BX = current position in (dst)
+; DS:SI = (src) + 1
+; AL = *(src)
+;
+
+repne scasb ; find next occurrence of *(target) in dst
+ jne short not_found ; out of string -- return NULL
+
+ mov edx,ecx ; update count of acceptable bytes left in dst
+ mov ebx,edi ; save current offset in dst
+
+ mov ecx,(srclen)
+ jecxz short match ; single character src string?
+
+repe cmpsb
+ jne short findnext
+
+;
+; Match! Return (BX-1)
+;
+match:
+ lea eax,[ebx-1]
+ jmp short retval
+
+empty_src: ; empty src string, return dst (ANSI mandated)
+ mov eax,(dst) ; eax = dst
+ jmp short retval ; return
+
+not_found:
+ xor eax,eax
+
+retval:
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strstr endp
+ end
diff --git a/private/crt32/string/i386/strupr.asm b/private/crt32/string/i386/strupr.asm
new file mode 100644
index 000000000..c8b66243f
--- /dev/null
+++ b/private/crt32/string/i386/strupr.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strupr - map string to upper-case
+;***
+;strupr.asm - routine to map lower-case characters in a string to upper-case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; _strupr() converts lower-case characters in a null-terminated string
+; to their upper-case equivalents. Conversion is done in place and
+; characters other than lower-case letters are not modified.
+;
+; This function modifies only 7-bit ASCII characters
+; in the range 0x61 through 0x7A ('a' through 'z').
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Minor optimization
+; 10-10-88 JCR Changed an 'xchg' to 'mov'
+; 10-26-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strupr(string) - map lower-case characters in a string to upper-case
+;
+;Purpose:
+; Converts all the lower case characters in string to upper case
+; in place.
+;
+; Algorithm:
+; char * _strupr (char * string)
+; {
+; char * cp = string;
+;
+; while( *cp )
+; {
+; if ('a' <= *cp && *cp <= 'z')
+; *cp += 'A' - 'a';
+; ++cp;
+; }
+; return(string);
+; }
+;
+;Entry:
+; char *string - string to change to upper case
+;
+;Exit:
+; The input string address is returned in AX or DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strupr
+_strupr proc \
+ string:ptr byte
+
+
+ mov ecx,[string] ; cx = *string
+ mov edx,ecx ; save return value
+ jmp short first_char; jump into the loop
+
+ align @WordSize
+check_char:
+ sub al,'a' ; 'a' <= al <= 'z' ?
+ cmp al,'z'-'a'+1
+ jnb short next_char
+ add al,'A' ; map to upper case
+ mov [ecx],al ; and store new value
+next_char:
+ inc ecx ; bump pointer
+first_char:
+ mov al,[ecx] ; get next character
+ or al,al
+ jnz short check_char
+
+done:
+ mov eax,edx ; ax = return value ("string")
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strupr endp
+ end