summaryrefslogtreecommitdiffstats
path: root/private/crt32/string
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/string
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/crt32/string')
-rw-r--r--private/crt32/string/alpha/strcat.c63
-rw-r--r--private/crt32/string/alpha/strcmps.s357
-rw-r--r--private/crt32/string/alpha/strcpys.s257
-rw-r--r--private/crt32/string/alpha/strlens.s95
-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
-rw-r--r--private/crt32/string/makefile6
-rw-r--r--private/crt32/string/makefile.inc9
-rw-r--r--private/crt32/string/memccpy.c59
-rw-r--r--private/crt32/string/memchr.c57
-rw-r--r--private/crt32/string/memcmp.c65
-rw-r--r--private/crt32/string/memcpy.c80
-rw-r--r--private/crt32/string/memicmp.c77
-rw-r--r--private/crt32/string/memmove.c93
-rw-r--r--private/crt32/string/memset.c70
-rw-r--r--private/crt32/string/mips/memcmpm.s125
-rw-r--r--private/crt32/string/mips/memcmpt.c334
-rw-r--r--private/crt32/string/mips/memcpym.s298
-rw-r--r--private/crt32/string/mips/memorym.s1218
-rw-r--r--private/crt32/string/mips/memsetm.s105
-rw-r--r--private/crt32/string/mips/memsett.c20
-rw-r--r--private/crt32/string/mips/strcatm.s98
-rw-r--r--private/crt32/string/mips/strchrm.s26
-rw-r--r--private/crt32/string/mips/strchrt.c20
-rw-r--r--private/crt32/string/mips/strcmpm.s50
-rw-r--r--private/crt32/string/mips/strcpym.s148
-rw-r--r--private/crt32/string/mips/strcpyt.c23
-rw-r--r--private/crt32/string/mips/strlenm.s19
-rw-r--r--private/crt32/string/mips/strrchrm.s24
-rw-r--r--private/crt32/string/mips/strrchrt.c20
-rw-r--r--private/crt32/string/mips/wcscmpm.s67
-rw-r--r--private/crt32/string/mips/wcscmpt.c62
-rw-r--r--private/crt32/string/mips/wcscpym.s139
-rw-r--r--private/crt32/string/mips/wcslenm.s45
-rw-r--r--private/crt32/string/ppc/memccpyp.s78
-rw-r--r--private/crt32/string/ppc/memchrp.s74
-rw-r--r--private/crt32/string/ppc/memcmpp.s71
-rw-r--r--private/crt32/string/ppc/strcatp.s137
-rw-r--r--private/crt32/string/ppc/strchrp.s70
-rw-r--r--private/crt32/string/ppc/strcmpp.s74
-rw-r--r--private/crt32/string/ppc/stricmpp.s89
-rw-r--r--private/crt32/string/ppc/strlenp.s164
-rw-r--r--private/crt32/string/ppc/strrchrp.s87
-rw-r--r--private/crt32/string/sources175
-rw-r--r--private/crt32/string/strcat.c90
-rw-r--r--private/crt32/string/strchr.c52
-rw-r--r--private/crt32/string/strcmp.c68
-rw-r--r--private/crt32/string/strcoll.c103
-rw-r--r--private/crt32/string/strcspn.c2
-rw-r--r--private/crt32/string/strdup.c60
-rw-r--r--private/crt32/string/stricmp.c80
-rw-r--r--private/crt32/string/stricoll.c95
-rw-r--r--private/crt32/string/strlen.c54
-rw-r--r--private/crt32/string/strlwr.c137
-rw-r--r--private/crt32/string/strncat.c63
-rw-r--r--private/crt32/string/strncmp.c61
-rw-r--r--private/crt32/string/strncpy.c59
-rw-r--r--private/crt32/string/strnicmp.c76
-rw-r--r--private/crt32/string/strnset.c54
-rw-r--r--private/crt32/string/strpbrk.c2
-rw-r--r--private/crt32/string/strrchr.c59
-rw-r--r--private/crt32/string/strrev.c58
-rw-r--r--private/crt32/string/strset.c58
-rw-r--r--private/crt32/string/strspn.c179
-rw-r--r--private/crt32/string/strstr.c68
-rw-r--r--private/crt32/string/strtok.c125
-rw-r--r--private/crt32/string/strupr.c138
-rw-r--r--private/crt32/string/strxfrm.c149
-rw-r--r--private/crt32/string/wcscat.c87
-rw-r--r--private/crt32/string/wcschr.c48
-rw-r--r--private/crt32/string/wcscmp.c59
-rw-r--r--private/crt32/string/wcscoll.c70
-rw-r--r--private/crt32/string/wcscspn.c61
-rw-r--r--private/crt32/string/wcsdup.c57
-rw-r--r--private/crt32/string/wcsicmp.c90
-rw-r--r--private/crt32/string/wcsicoll.c73
-rw-r--r--private/crt32/string/wcslen.c45
-rw-r--r--private/crt32/string/wcslwr.c100
-rw-r--r--private/crt32/string/wcsncat.c61
-rw-r--r--private/crt32/string/wcsncmp.c57
-rw-r--r--private/crt32/string/wcsncpy.c57
-rw-r--r--private/crt32/string/wcsnicmp.c91
-rw-r--r--private/crt32/string/wcsnset.c51
-rw-r--r--private/crt32/string/wcspbrk.c56
-rw-r--r--private/crt32/string/wcsrchr.c56
-rw-r--r--private/crt32/string/wcsrev.c56
-rw-r--r--private/crt32/string/wcsset.c51
-rw-r--r--private/crt32/string/wcsspn.c67
-rw-r--r--private/crt32/string/wcsstr.c62
-rw-r--r--private/crt32/string/wcstok.c174
-rw-r--r--private/crt32/string/wcsupr.c104
-rw-r--r--private/crt32/string/wcsxfrm.c126
117 files changed, 11998 insertions, 0 deletions
diff --git a/private/crt32/string/alpha/strcat.c b/private/crt32/string/alpha/strcat.c
new file mode 100644
index 000000000..307b83837
--- /dev/null
+++ b/private/crt32/string/alpha/strcat.c
@@ -0,0 +1,63 @@
+/***
+*strcat.c - contains strcat()
+*
+* 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-29-94 DEC Removed strcpy
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up strcat() a bit (got rid of call to strcpy()).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strcat)
+#endif /* ndef _CRUISER_ */
+
+/***
+*char *strcat(dst, src) - concatenate (append) one string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*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"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strcat (
+ char * dst,
+ const char * src
+ )
+{
+ char * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
diff --git a/private/crt32/string/alpha/strcmps.s b/private/crt32/string/alpha/strcmps.s
new file mode 100644
index 000000000..0c7859727
--- /dev/null
+++ b/private/crt32/string/alpha/strcmps.s
@@ -0,0 +1,357 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strcmp().
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ # Add decc$ prefixes.
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+//
+// Although the spec says the return value may be <0/0/>0, we now return
+// -1/0/+1 to reduce NT combatibility problems.
+//
+
+ .globl strcmp
+ .ent strcmp
+
+ # r16 = A
+ # r17 = B
+ # returns r0<0 if A<B, R0=0 if A=B, r0>0 if A>B (unsigned chars)
+ # destroys r16-r21, r27-r28
+ #
+
+strcmp:
+ .set noat
+ .set noreorder
+
+ .frame $30, 0, $26
+
+ ldq_u $27, ($16) # Get first A QW
+ and $16, 7, $21 # Alignment of A
+
+ ldq_u $18, ($17) # Get first B QW
+ and $17, 7, $20 # Alignment of B
+
+ subq $20, $21, $0 # B_alignment geq A_alignment?
+
+ cmpbge $31, $27, $19 # Any nulls in A?
+
+ insql $27, $0, $28 # Position A like B if B_align geq
+ bgt $0, more_a # Skip if enough A bytes available
+
+ srl $19, $21, $19 # Discard nulls preceding start of A
+ bne $0, more_b # Go handle opposite mismatch
+
+match: xor $27, $18, $28 # Do A and B differ?
+
+ mskqh $28, $21, $28 # Ignore differences before start
+
+ sll $19, $21, $0 # Line up nulls with differences
+ bne $19, null # Skip out if nulls seen
+
+loop_s: bne $28, diff # Skip out if difference seen
+ ldq_u $27, 8($16) # Get next A QW
+
+ ldq_u $18, 8($17) # Get next B QW
+ addq $16, 8, $16 # Bump A pointer
+
+ addq $17, 8, $17 # Bump B pointer
+
+ cmpbge $31, $27, $0 # Any nulls in A?
+
+ xor $27, $18, $28 # Do A and B differ?
+ beq $0, loop_s # Repeat if no nulls
+
+ # Enter here if null seen.
+ # r0 = mask of nulls
+ # r27= A
+ # r18 = B
+ # r28= xor
+ #
+null: subq $0, 1, $19 # Flip bits up thru first null
+
+ cmpbge $31, $28, $28 # Mask of 1's where A=B
+
+ xor $0, $19, $0 # Mask of 1's thru first null
+
+ andnot $0, $28, $0 # Differences thru first null
+
+ cmpbge $27, $18, $27 # Mask of 1's where A >= B
+ beq $0, done # Exit with R0=0 if no differences
+
+ subq $31, $0, $19 # R19<0, first diff=1, others=0
+
+ and $27, $0, $28 # Mask of A>B thru first null
+
+ and $28, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+done: ret $31, ($26) # All done
+
+ # Enter here if difference seen, but no nulls.
+ # r27= A
+ # r18 = B
+ # R28= xor
+ #
+diff: cmpbge $31, $28, $21 # Where is A = B?
+
+ cmpbge $27, $18, $0 # Where is A >= B?
+
+ subq $21, 255, $19 # R19<0, first diff=1, others=0
+
+ andnot $0, $21, $28 # Mask of A > B
+
+ and $28, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+ ret $31, ($26)
+
+ #.align quad
+
+ # Enter here if A and B alignments differ, and B's is greater (so there are
+ # more A bytes in its first QW than B bytes in its first QW).
+
+more_a: srl $19, $21, $19 # Discard nulls preceding start of A
+
+ xor $28, $18, $21 # Do A and B differ?
+
+ mskqh $21, $20, $21 # Discard diffs preceding start of B
+ bne $19, null_a # Skip if A has nulls
+
+ mov $18, $19 # Put B where common code expects
+
+ bne $21, diff_d # Handle diffs in B
+
+ ldq_u $18, 8($17) # No nulls in A or B, get next QW of B
+ addq $17, 8, $17 # Bump B pointer
+
+ insqh $27, $0, $28 # Position high part of A like B
+
+ #stall
+
+ mskql $18, $0, $19 # Keep low part of B
+
+ # Loop comparing A and B when alignment differs.
+ # Register use:
+ # r16 --> A
+ # r17 --> B
+ # r27 = QW of A
+ # r28 = current piece of A
+ # r18 = QW of B
+ # r19 = current piece of B
+ # r0 = alignment difference (B-A)
+ # r21 = xor of pieces
+ # r20 = mask of null locations
+ #
+ # If a string contains a null, we are careful not to read the following
+ # quadword in that string. But we are willing to read the quadword that
+ # follows the first difference, because this read-ahead improves performance.
+ #
+loop_d: xor $28, $19, $21 # Do A and B pieces differ?
+ ldq_u $27, 8($16) # Get next QW of A
+
+ cmpbge $31, $18, $20 # Any nulls in B?
+ bne $21, diff_d # Skip if difference seen
+
+ent_d: mskqh $18, $0, $19 # Trim B for next compare
+
+ insql $27, $0, $28 # Position A like B
+
+ addq $16, 8, $16 # Bump A pointer
+ bne $20, null_d # Skip if null seen in B
+
+ xor $28, $19, $21 # Do A and B pieces differ?
+ ldq_u $18, 8($17) # Get next QW of B
+
+ cmpbge $31, $27, $20 # Any nulls in A?
+ bne $21, diff_d # Skip if difference seen
+
+ insqh $27, $0, $28 # Position A for next compare
+
+ mskql $18, $0, $19 # Trim B like A
+
+ addq $17, 8, $17 # Bump B pointer
+ beq $20, loop_d # Repeat if no nulls in A
+
+ # We saw a null in A. Since we've already compared the lower part with B,
+ # and B had no nulls, the null is in the upper part of A. We've moved that
+ # part of A to the lower part of r28. Re-compare so the mask of nulls will
+ # be positioned properly for the following code.
+ #
+ cmpbge $31, $28, $20 # Find nulls in repositioned A
+
+ # Null seen and alignments differ.
+ # r28 = positioned A
+ # r19 = positioned B
+ # r20 = mask of nulls
+ # r21 = xor (at entry null_e)
+ #
+ #.odd
+null_d: xor $28, $19, $21 # Where do A and B differ?
+
+null_e: subq $20, 1, $27 # Flip bits up thru first null
+
+ cmpbge $31, $21, $18 # Mask of 1's where A=B
+
+ xor $20, $27, $0 # Mask of 1's thru first null
+
+ andnot $0, $18, $0 # Differences thru first null
+
+ cmpbge $28, $19, $27 # Mask of 1's where A >= B
+ beq $0, done_d # Exit with R0=0 if no differences
+
+ subq $31, $0, $19 # R19<0, first diff=1, others=0
+
+ and $27, $0, $0 # Mask of A>B thru first null
+
+ and $0, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+done_d: ret $31, ($26) # All done
+
+
+ # Null seen in first QW of A, when B alignment greater.
+ # r19 = nulls in A, shifted
+ # r27 = A
+ # r28 = A positioned like B
+ # r18 = B
+ # r21 = xor, masked
+ #
+ #.odd
+null_a: sll $19, $20, $20 # Position nulls like B
+
+ mov $18, $19 # Move B for common code
+ bne $21, null_e # Comparison done if difference seen
+
+ and $20, 255, $18 # Any nulls in first part of A?
+
+ bne $18, null_e # Comparison done if so
+
+ ldq_u $19, 8($17) # Get another B QW
+ insqh $27, $0, $28 # Position A to match
+
+ srl $20, 8, $20 # Shift nulls again to match
+ br $31, null_d # Now we must be at end
+
+
+ # Enter here if A and B alignments differ, and B's is less (so there are more
+ # B bytes in its first QW than A bytes in its first QW).
+
+ #.align quad
+more_b: cmpbge $31, $18, $28 # We'll want to know about nulls in B
+ bne $19, null_b # Skip if null seen in A
+
+ extqh $18, $0, $19 # Position B like A
+
+ srl $28, $20, $28 # Discard nulls preceding start of B
+
+ xor $27, $19, $27 # Do A and B differ?
+
+ mskqh $27, $21, $21 # Discard diffs preceding start of A
+
+ sll $28, $20, $20 # Position null mask for common code
+ ldq_u $27, 8($16) # Get next QW of A
+
+ xor $19, $21, $28 # Recover A for compare
+ beq $21, ent_d # Enter loop if A=B so far
+
+
+ # Enter here if difference seen, but no nulls.
+ # r28 = A piece
+ # r19 = B piece
+ # r21 = xor
+ #
+diff_d: cmpbge $31, $21, $21 # Where is A = B?
+
+ cmpbge $28, $19, $0 # Where is A >= B?
+
+ subq $21, 255, $27 # R27<0, first diff=1, others=0
+
+ andnot $0, $21, $0 # Mask of A > B
+
+ and $0, $27, $0 # Keep only first difference
+
+ cmoveq $0, $27, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+ ret $31, ($26)
+
+ # Null seen in first QW of A, when B alignment less.
+ # r19 = nulls in A, shifted
+ # r27 = A
+ # r18 = original B
+ #
+ nop #.align 8
+null_b: sll $19, $21, $20 # Position null mask like A
+
+ extqh $18, $0, $19 # Position B like A
+
+ mov $27, $28 # Put A where common code expects
+
+ xor $27, $19, $27 # Find differences
+
+ mskqh $27, $21, $21 # Discard diffs preceding A
+ br $31, null_e # Comparison is done
+
+ .set at
+ .set reorder
+ .end strcmp
diff --git a/private/crt32/string/alpha/strcpys.s b/private/crt32/string/alpha/strcpys.s
new file mode 100644
index 000000000..c326688eb
--- /dev/null
+++ b/private/crt32/string/alpha/strcpys.s
@@ -0,0 +1,257 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strcpy().
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ # Add decc$ prefixes.
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+ .globl strcpy
+ .ent strcpy
+
+ # r16 = dst
+ # r17 = src
+ # returns r0 = src
+ # destroys r16-r21, r27-r28
+
+strcpy:
+ .set noat
+ .set noreorder
+
+ ldq_u $27, ($17) # Get first src QW
+ and $16, 7, $28 #/ Is dst aligned?
+ lda $18, -1($31) # Get a mask of all 1's
+ bne $28, dst_unaligned #/ Go handle unaligned dst
+ and $17, 7, $19 # Is src aligned too?
+ nop
+ mov $16, $0 # Set up function result
+ bne $19, src_unaligned #/ Go handle aligned dst, unaligned src
+
+a_loop:
+ cmpbge $31, $27, $18 # Any nulls in src QW?
+ bne $18, a_exit_1 # Finish up if so
+ ldq $21, 8($17) # Load next QW if not
+match: # Enter if src matches unaligned dst
+ addq $17, 16, $17 #/ Update src pointer for unrolled loop
+ stq_u $27, ($16) # Store a whole QW
+ addq $16, 16, $16 #/ Update dst pointer for unrolled loop
+ cmpbge $31, $21, $18 # Any nulls in src QW?
+ bne $18, a_exit_2 # Finish up if so
+ ldq $27, ($17) # Load next QW if not
+ stq_u $21, -8($16) # Store a whole QW
+ br $31, a_loop # Repeat during load latency
+
+a_exit_1:
+ ldq_u $21, ($16) # Get dst QW to update
+ subq $18, 1, $17 #/ Use location of null byte...
+ xor $18, $17, $18 # ... to compute mask of what to keep
+ zapnot $27, $18, $27 # Keep src up to & including null
+ zap $21, $18, $21 # Make room for new data
+ nop
+ or $21, $27, $21 # Combine src & dst...
+ stq_u $21, ($16) #/ ... and store
+ ret $31, ($26)
+
+ nop
+a_exit_2:
+ ldq_u $27, -8($16) # Get dst QW to update
+ subq $18, 1, $17 #/ Use location of null byte...
+ xor $18, $17, $18 # ... to compute mask of what to keep
+ zapnot $21, $18, $21 # Keep src up to & including null
+ zap $27, $18, $27 # Make room for new data
+ nop
+ or $27, $21, $27 # Combine src & dst...
+ stq_u $27, -8($16) #/ ... and store
+ ret $31, ($26)
+
+src_unaligned: # dst_unaligned code would work; is this faster?
+ mskqh $18, $17, $18 # Zeros where src to be ignored
+ ornot $27, $18, $19 # Make ignored bytes nonzero
+ cmpbge $31, $19, $21 # Any null bytes in src data?
+ extql $27, $17, $27 # Move src to position of dst
+ bne $21, short_ld #/ Finish up if nulls seen
+ ldq_u $19, 8($17) # Next src QW needed to fill dst
+ br $31, u_entry_2 # Enter loop for mismatched alignment
+
+ # Here's the hard part. Enter with
+ # r16 = dst address
+ # r17 = src address
+ # r18 = -1
+ # r27 = first src QW
+ # r28 = dst alignment (>0)
+ # Check whether the first src QW has any nulls, and load the next one.
+ # Combine these if needed to fill the first dst QW, and enter a loop
+ # that fetches src QWs and checks them, while storing dst QWs.
+
+dst_unaligned:
+ ldq_u $20, ($16) # Load dst to be updated
+ mskqh $18, $17, $18 #/ Zeros where src to be ignored
+ mov $16, $0 # Set up function result
+ ornot $27, $18, $19 # Make ignored bytes of src nonzero
+ cmpbge $31, $19, $21 # Any null bytes in src data?
+ extql $27, $17, $27 # Get only interesting src data
+ bne $21, short # Finish up if nulls seen
+ mskql $20, $16, $20 #/ Make room in dst
+ ldq_u $21, 8($17) # Load next src QW if no nulls
+ mskql $18, $16, $18 #/ Need two src QWs for first dst QW?
+ insql $27, $16, $27 # Move src data to position of dst
+ subq $17, $28, $17 # Adjust src ptr for partial move
+ and $17, 7, $28 # Is src now aligned?
+ bne $18, u_loop #/ Enter loop if one src QW fills dst
+ or $27, $20, $27 # Combine first src QW with dst
+ extqh $21, $17, $20 # Position 2nd src QW in 1st dst QW
+ cmpbge $31, $21, $18 # Any nulls in next src QW?
+ beq $28, match #/ If src aligned, use quick loop
+ mov $21, $19 # Put src QW where loop expects
+ bne $18, short_a #/ Finish up if nulls seen
+
+ # r16 = address of next dst to store
+ # r17 = address-16 of next src to load
+ # r18
+ # r19 = last loaded src QW
+ # r20 = one piece of dst QW
+ # r21
+ # r27 = other piece of dst QW
+ # r28
+
+u_loop:
+ ldq_u $28, 16($17) # Load another src QW
+ addq $17, 16, $17 #/ Update src pointer for unrolled loop
+ or $27, $20, $27 # Combine pieces
+ extql $19, $17, $20 # Get second part of prior src QW
+ stq_u $27, ($16) # Store a dst QW
+ cmpbge $31, $28, $19 #/ Any nulls in this src QW?
+ extqh $28, $17, $27 # Get first part of this src QW
+ bne $19, u_exit_2 #/ Finish up if nulls seen
+ ldq_u $19, 8($17) # Load another src QW
+ addq $16, 16, $16 #/ Update dst pointer for unrolled loop
+ or $27, $20, $20 # Combine pieces
+ extql $28, $17, $27 # Get second piece of prior src QW
+ stq_u $20, -8($16) # Store a dst QW
+u_entry_2:
+ cmpbge $31, $19, $28 #/ Any nulls in this src QW?
+ extqh $19, $17, $20 # Get first part of this src QW
+ beq $28, u_loop #/ Repeat if no nulls seen
+
+ subq $16, 8, $16 # Undo part of pointer update
+ mov $19, $28 # Move src QW to expected place
+u_exit_2:
+ or $27, $20, $27 # Combine pieces
+ ldq_u $18, 8($16) #/ Load dst to update
+ cmpbge $31, $27, $21 # Is null in first dst QW?
+ bne $21, u_exit_3 # Skip if so
+ stq_u $27, 8($16) # Store a whole dst QW
+ extql $28, $17, $27 #/ Get second part of src QW
+ ldq_u $18, 16($16) # We'll update next dst QW
+ cmpbge $31, $27, $21 # Find location of null there
+ addq $16, 8, $16 # Update dst pointer
+u_exit_3:
+ subq $21, 1, $28 # Using position of null byte...
+ xor $21, $28, $21 # ... make mask for desired src data
+ zapnot $27, $21, $27 # Trim src data after null
+ zap $18, $21, $18 # Make room for it in dst
+ nop
+ or $27, $18, $27 # Combine pieces
+ stq_u $27, 8($16) #/ Store dst QW
+ ret $31, ($26)
+short_ld:
+ ldq_u $20, ($16) # Load dst QW to update
+short:
+ cmpbge $31, $27, $17 #/ Get mask showing location of null
+ insql $27, $16, $18 # Move src data to position of dst
+ mskql $20, $16, $19 # Get dst bytes preceding string
+ sll $17, $28, $17 # Move mask in the same way
+ or $18, $19, $18 # Combine src & dst
+ and $17, 255, $28 # Null byte in first dst QW?
+ subq $17, 1, $19 # Using position of null byte...
+ xor $17, $19, $17 # ... make mask for desired src data
+ bne $28, short_2 #/ Skip if null in first dst QW
+ ldq_u $20, 8($16) # Load second dst QW
+ srl $17, 8, $17 #/ Move mask down for use
+ stq_u $18, ($16) # Store first dst QW
+ insqh $27, $16, $18 #/ Move src data to position of dst
+ addq $16, 8, $16 # Advance dst pointer
+short_2:
+ zap $20, $17, $20 # Preserve dst data following null
+ zapnot $18, $17, $18 # Trim src data after null
+ nop
+ or $18, $20, $18 # Combine pieces
+ stq_u $18, ($16) #/ Store dst QW
+ ret $31, ($26)
+
+ # r16 = dst address
+ # r17 = updated src address
+ # r18 = null position
+ # r19 = next src QW
+ # r20 = first part of r19, positioned for dst
+ # r21
+ # r27 = dst QW so far
+ # r28 = low bits of updated src address
+
+short_a:
+ sll $18, 8, $18 # Shift location of null byte...
+ ldq_u $21, ($16) #/ Reload first dst QW
+ or $27, $20, $27 # Combine pieces
+ srl $18, $28, $18 # ... to position in dst QW's
+ nop
+ and $18, 255, $20 # Is null in first dst QW?
+ subq $18, 1, $28 # Using position of null byte...
+ xor $18, $28, $18 # ... make mask for desired src data
+ bne $20, short_a1 #/ Skip if null in first QW
+ stq_u $27, ($16) # Store a whole dst QW
+ extql $19, $17, $27 #/ Prepare next piece of src
+ ldq_u $21, 8($16) # Load second dst QW for update
+ srl $18, 8, $18 #/ Look at next 8 bits of mask
+ addq $16, 8, $16 # Update dst pointer
+short_a1:
+ zapnot $27, $18, $27 # Keep src data
+ zap $21, $18, $21 # Keep end of dst QW
+ nop
+ or $27, $21, $27 # Combine pieces
+ stq_u $27, ($16) # Store last dst QW
+ ret $31, ($26)
+
+ .set at
+ .set reorder
+ .end strcpy
diff --git a/private/crt32/string/alpha/strlens.s b/private/crt32/string/alpha/strlens.s
new file mode 100644
index 000000000..238699f7d
--- /dev/null
+++ b/private/crt32/string/alpha/strlens.s
@@ -0,0 +1,95 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strlen().
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+ .globl strlen
+ .ent strlen
+
+ # r16 = src pointer
+ # Returns r0 = length
+ # Destroys r16,r27-r28
+
+strlen:
+ .set noat
+ .set noreorder
+
+ ldq_u $27, ($16) # Get QW containing start of string
+ lda $28, -1($31) # Mask of all ones
+ mskql $28, $16, $28 # Nonzeros in low bytes to be ignored
+ and $16, 7, $0 # Alignment = bytes not to be counted
+ or $27, $28, $27 # Fill ignored bytes with nonzeros
+ cmpbge $31, $27, $27 # Any null bytes in this QW?
+ subq $31, $0, $0 # Initialize count to -alignment
+ bne $27, bottom # Skip if null byte seen
+
+loop: ldq_u $27, 8($16) # Load next QW of string
+ addq $16, 8, $16 # Advance pointer
+ addq $0, 8, $0 # Increment length
+ cmpbge $31, $27, $27 # Any nulls in this QW?
+ beq $27, loop # Repeat if not
+
+bottom: and $27, 0xF, $28 # Null in low longword?
+ subq $27, 1, $16 # Complement the lowest 1-bit in mask
+ blbs $27, done # Exit if null appears in first byte
+ andnot $27, $16, $27 # Make single-bit mask of null location
+ beq $28, geq_4 # Skip if null is in high longword
+ srl $27, 2, $27 # Map 2/4/8 --> 0/1/2
+ addq $0, 1, $0 # Bump length by one...
+ addq $0, $27, $0 # ... and then by null location
+
+done: ret $31, ($26)
+
+geq_4: srl $27, 5, $28 # Map 10/20/40/80 --> 0/1/2/4
+ srl $27, 7, $27 # Map 10/20/40/80 --> 0/0/0/1
+ addq $0, 4, $0 # Bump length by four
+ subq $28, $27, $28 # Compute location within high LW...
+ addq $0, $28, $0 # ... and add to length
+ ret $31, ($26)
+
+ .set at
+ .set reorder
+ .end strlen
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
diff --git a/private/crt32/string/makefile b/private/crt32/string/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/string/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/string/makefile.inc b/private/crt32/string/makefile.inc
new file mode 100644
index 000000000..84afc0560
--- /dev/null
+++ b/private/crt32/string/makefile.inc
@@ -0,0 +1,9 @@
+strcspn.c: strspn.c
+
+strpbrk.c: strspn.c
+
+i386\memmove.asm: i386\memcpy.asm
+
+i386\strcspn.asm: i386\strspn.asm
+
+i386\strpbrk.asm: i386\strspn.asm
diff --git a/private/crt32/string/memccpy.c b/private/crt32/string/memccpy.c
new file mode 100644
index 000000000..2fd8f63cd
--- /dev/null
+++ b/private/crt32/string/memccpy.c
@@ -0,0 +1,59 @@
+/***
+*memccpy.c - 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-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright. Also, fixed compiler warning.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 01-17-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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.
+*
+*Entry:
+* void *dest - pointer to memory to receive copy
+* void *src - source of bytes
+* int c - character to stop copy at
+* unsigned 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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _memccpy (
+ void * dest,
+ const void * src,
+ int c,
+ unsigned count
+ )
+{
+ while ( count && (*((char *)(dest = (char *)dest + 1) - 1) =
+ *((char *)(src = (char *)src + 1) - 1)) != (char)c )
+ count--;
+
+ return(count ? dest : NULL);
+}
diff --git a/private/crt32/string/memchr.c b/private/crt32/string/memchr.c
new file mode 100644
index 000000000..b79097e79
--- /dev/null
+++ b/private/crt32/string/memchr.c
@@ -0,0 +1,57 @@
+/***
+*memchr.c - 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-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-26-91 SRW Removed level 3 warnings
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *memchr(buf, chr, cnt) - search memory for given character.
+*
+*Purpose:
+* Searches at buf for the given character, stopping when chr is
+* first found or cnt bytes have been searched through.
+*
+*Entry:
+* void *buf - memory buffer to be searched
+* int chr - character to search for
+* size_t 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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 memchr (
+ const void * buf,
+ int chr,
+ size_t cnt
+ )
+{
+ while ( cnt && *(char *)buf != (char)chr ) {
+ buf = (char *)buf + 1;
+ cnt--;
+ }
+
+ return(cnt ? (void *)buf : NULL);
+}
diff --git a/private/crt32/string/memcmp.c b/private/crt32/string/memcmp.c
new file mode 100644
index 000000000..478ecabab
--- /dev/null
+++ b/private/crt32/string/memcmp.c
@@ -0,0 +1,65 @@
+/***
+*memcmp.c - 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-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(memcmp)
+#endif /* ndef _CRUISER_ */
+
+/***
+*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.
+*
+*Entry:
+* void *buf1, *buf2 - pointers to memory sections to compare
+* size_t count - length of sections to compare
+*
+*Exit:
+* returns < 0 if buf1 < buf2
+* returns 0 if buf1 == buf2
+* returns > 0 if buf1 > buf2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 memcmp (
+ const void * buf1,
+ const void * buf2,
+ size_t count
+ )
+{
+ if (!count)
+ return(0);
+
+ while ( --count && *(char *)buf1 == *(char *)buf2 ) {
+ buf1 = (char *)buf1 + 1;
+ buf2 = (char *)buf2 + 1;
+ }
+
+ return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );
+}
diff --git a/private/crt32/string/memcpy.c b/private/crt32/string/memcpy.c
new file mode 100644
index 000000000..a4348e74e
--- /dev/null
+++ b/private/crt32/string/memcpy.c
@@ -0,0 +1,80 @@
+/***
+*memcpy.c - contains memcpy routine
+*
+* Copyright (c) 1988-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.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up for large buffers by moving int-sized chunks
+* as much as possible.
+* 08-06-91 GJF Backed out 04-05-91 change. Pointers would have to be
+* dword-aligned for this to work on MIPS.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+#pragma function(memcpy)
+#endif
+
+/***
+*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.
+*
+*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
+*
+*Exceptions:
+*******************************************************************************/
+
+void * _CALLTYPE1 memcpy (
+ void * dst,
+ const void * src,
+ size_t count
+ )
+{
+ void * ret = dst;
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ {
+ extern void RtlMoveMemory( void *, const void *, size_t count );
+
+ RtlMoveMemory( dst, src, count );
+ }
+#else
+ /*
+ * copy from lower addresses to higher addresses
+ */
+ while (count--) {
+ *(char *)dst = *(char *)src;
+ dst = (char *)dst + 1;
+ src = (char *)src + 1;
+ }
+#endif
+
+ return(ret);
+}
diff --git a/private/crt32/string/memicmp.c b/private/crt32/string/memicmp.c
new file mode 100644
index 000000000..d38bf717f
--- /dev/null
+++ b/private/crt32/string/memicmp.c
@@ -0,0 +1,77 @@
+/***
+*memicmp.c - compare memory, ignore case
+*
+* Copyright (c) 1988-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-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright. Also, fixed compiler warnings.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 01-17-91 GJF ANSI naming.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+* 06-28-94 SRW Rewrite to use same ANSI specific tolower logic as x86
+* assembler version is i386\memicmp.asm
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _memicmp (
+ const void * first,
+ const void * last,
+ unsigned int count
+ )
+{
+ unsigned char f,l;
+
+ if (count) do {
+ f = *((const char *)first)++;
+ l = *((const char *)last)++;
+ if (f != l) {
+ if (f>='A' && f<='Z') {
+ f = f - 'A' + 'a';
+ }
+ if (l>='A' && l<='Z') {
+ l = l - 'A' + 'a';
+ }
+ if (f!=l) {
+ return f-l;
+ }
+ }
+ }
+ while (--count);
+
+ return 0;
+}
diff --git a/private/crt32/string/memmove.c b/private/crt32/string/memmove.c
new file mode 100644
index 000000000..efb0ab9b3
--- /dev/null
+++ b/private/crt32/string/memmove.c
@@ -0,0 +1,93 @@
+/***
+*memmove.c - contains memmove routine
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All right reserved.
+*
+*Purpose:
+* memmove() copies a source memory buffer to a destination buffer.
+* Overlapping buffers are treated specially, to avoid propogation.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 04-09-91 GJF Speed up a little for large buffers.
+* 08-06-91 GJF Backed out 04-09-91 change. Pointers would have to be
+* dword-aligned for this to work on MIPS.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_M_ALPHA)
+#pragma function(memmove)
+#endif
+
+/***
+*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.
+*
+*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
+*
+*Exceptions:
+*******************************************************************************/
+
+void * _CALLTYPE1 memmove (
+ void * dst,
+ const void * src,
+ size_t count
+ )
+{
+ void * ret = dst;
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ {
+ extern void RtlMoveMemory( void *, const void *, size_t count );
+
+ RtlMoveMemory( dst, src, count );
+ }
+#else
+ if (dst <= src || (char *)dst >= ((char *)src + count)) {
+ /*
+ * Non-Overlapping Buffers
+ * copy from lower addresses to higher addresses
+ */
+ while (count--) {
+ *(char *)dst = *(char *)src;
+ dst = (char *)dst + 1;
+ src = (char *)src + 1;
+ }
+ }
+ else {
+ /*
+ * Overlapping Buffers
+ * copy from higher addresses to lower addresses
+ */
+ dst = (char *)dst + count - 1;
+ src = (char *)src + count - 1;
+
+ while (count--) {
+ *(char *)dst = *(char *)src;
+ dst = (char *)dst - 1;
+ src = (char *)src - 1;
+ }
+ }
+#endif
+
+ return(ret);
+}
diff --git a/private/crt32/string/memset.c b/private/crt32/string/memset.c
new file mode 100644
index 000000000..5a04554a9
--- /dev/null
+++ b/private/crt32/string/memset.c
@@ -0,0 +1,70 @@
+/***
+*memset.c - set a section of memory to all one byte
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains the memset() routine
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+#pragma function(memset)
+#endif
+
+/***
+*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".
+*
+*Entry:
+* void *dst - pointer to memory to fill with val
+* int val - value to put in dst bytes
+* size_t count - number of bytes of dst to fill
+*
+*Exit:
+* returns dst, with filled bytes
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 memset (
+ void *dst,
+ int val,
+ size_t count
+ )
+{
+ void *start = dst;
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ {
+ extern void RtlFillMemory( void *, size_t count, char );
+
+ RtlFillMemory( dst, count, (char)val );
+ }
+#else
+ while (count--) {
+ *(char *)dst = (char)val;
+ dst = (char *)dst + 1;
+ }
+#endif
+
+ return(start);
+}
diff --git a/private/crt32/string/mips/memcmpm.s b/private/crt32/string/mips/memcmpm.s
new file mode 100644
index 000000000..961939432
--- /dev/null
+++ b/private/crt32/string/mips/memcmpm.s
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+#ident "$Header"
+
+/*
+ * Copyright 1985 by MIPS Computer Systems, Inc.
+ */
+
+/* bcmp(s1, s2, n) */
+
+#include "kxmips.h"
+
+/*
+ * bcmp(src, dst, bcount)
+ *
+ * MINCMP is minimum number of byte that its worthwhile to try and
+ * align cmp into word transactions
+ *
+ * Calculating MINCMP
+ * Overhead =~ 15 instructions => 90 cycles
+ * Byte cmp =~ 38 cycles/word
+ * Word cmp =~ 17 cycles/word
+ * Breakeven =~ 16 bytes
+ */
+#define MINCMP 16
+#define NBPW 4
+
+LEAF_ENTRY(memcmp)
+ xor v0,a0,a1
+ blt a2,MINCMP,bytecmp # too short, just byte cmp
+ and v0,NBPW-1
+ subu t8,zero,a0 # number of bytes til aligned
+ bne v0,zero,unalgncmp # src and dst not alignable
+/*
+ * src and dst can be simultaneously word aligned
+ */
+ and t8,NBPW-1
+ subu a2,t8
+ beq t8,zero,wordcmp # already aligned
+ move v0,v1 # lw[lr] don't clear target reg
+ lwr v0,0(a0)
+ lwr v1,0(a1)
+ addu a0,t8
+ addu a1,t8
+ bne v0,v1,cmpne
+
+/*
+ * word cmp loop
+ */
+wordcmp:
+ and a3,a2,~(NBPW-1)
+ subu a2,a3
+ beq a3,zero,bytecmp
+ addu a3,a0 # src1 endpoint
+1: lw v0,0(a0)
+ lw v1,0(a1)
+ addu a0,NBPW # 1st BDSLOT
+ addu a1,NBPW # 2nd BDSLOT (asm doesn't move)
+ bne v0,v1,cmpne
+ bne a0,a3,1b # at least one more word
+ b bytecmp
+
+/*
+ * deal with simultaneously unalignable cmp by aligning one src
+ */
+unalgncmp:
+ subu a3,zero,a1 # calc byte cnt to get src2 aligned
+ and a3,NBPW-1
+ subu a2,a3
+ beq a3,zero,partaligncmp # already aligned
+ addu a3,a0 # src1 endpoint
+1: lbu v0,0(a0)
+ lbu v1,0(a1)
+ addu a0,1
+ addu a1,1
+ bne v0,v1,cmpne
+ bne a0,a3,1b
+
+/*
+ * src unaligned, dst aligned loop
+ */
+partaligncmp:
+ and a3,a2,~(NBPW-1)
+ subu a2,a3
+ beq a3,zero,bytecmp
+ addu a3,a0
+1:
+ lwr v0,0(a0)
+ lwl v0,3(a0)
+ lw v1,0(a1)
+ addu a0,NBPW
+ addu a1,NBPW
+ bne v0,v1,cmpne
+ bne a0,a3,1b
+
+/*
+ * brute force byte cmp loop
+ */
+bytecmp:
+ addu a3,a2,a0 # src1 endpoint; BDSLOT
+ ble a2,zero,cmpdone
+1: lbu v0,0(a0)
+ lbu v1,0(a1)
+ addu a0,1
+ addu a1,1
+ bne v0,v1,cmpne
+ bne a0,a3,1b
+cmpdone:
+ move v0,zero
+ j ra
+
+cmpne:
+ sltu a2,v1,v0
+ bne a2,zero,9f
+ li v0,-1
+ j ra
+9:
+ li v0,1
+ j ra
+.end bcmp
diff --git a/private/crt32/string/mips/memcmpt.c b/private/crt32/string/mips/memcmpt.c
new file mode 100644
index 000000000..3adb427b9
--- /dev/null
+++ b/private/crt32/string/mips/memcmpt.c
@@ -0,0 +1,334 @@
+/*
+ * Test memcpy() function.
+ */
+
+char buffer[100];
+#include <stdio.h>
+#include <memory.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#define NTUL 7
+#define TEST16 4
+#define TEST32 8
+
+#define BUFSIZE 256
+
+void printbuf(char *identifier, char *buf, int length)
+{
+ int i;
+ printf("%s = '", identifier);
+ for (i = 0; i < length; i++)
+ printf("%c", buf[i]);
+ printf("'\n");
+}
+
+void main()
+{
+ int i, j, n, k, l;
+ int rc;
+ char *s1, *s2;
+
+ char TavEqFailed = FALSE;
+ char TvaEqFailed = FALSE;
+ char TavltFailed = FALSE;
+ char TvaltFailed = FALSE;
+ char TavgtFailed = FALSE;
+ char TvagtFailed = FALSE;
+
+ char TvveqFailed = FALSE;
+ char TvvltFailed = FALSE;
+ char TvvgtFailed = FALSE;
+
+ int Tmisc = 0;
+
+ unsigned long source1_16[TEST16] = {
+ 0x00003000,
+ 0x30003000,
+ 0x30003000,
+ 0x36003000
+ };
+
+ unsigned long source2_16[TEST16] = {
+ 0x00003000,
+ 0x30003000,
+ 0x30003000,
+ 0x00000000
+ };
+
+ unsigned long tul[NTUL] = {
+ 0x35004600,
+ 0x37004600,
+ 0x36002f00,
+ 0x37002f00,
+ 0x30004600,
+ 0x30003000,
+ 0x36003000
+ };
+ int tul_test[NTUL] = {
+ -1,
+ -1,
+ +1,
+ +1,
+ -1,
+ +1,
+ 0
+ };
+
+ struct {
+ double dummy;
+ char source1[BUFSIZE];
+ char source2[BUFSIZE];
+ } buffer;
+
+ char source32[32] = "0X0042036C 002477CD BREAK 0x91DF";
+ char source[BUFSIZE];
+
+ for (j = 0; j < BUFSIZE; ) {
+ for (i = 0; i <= j % 32; i++, j++) {
+ buffer.source1[j] = source32[i];
+ buffer.source2[j] = source32[i];
+ }
+ }
+
+ j = BUFSIZE;
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ while (j--) {
+ if (*s1++ != *s2++) {
+ printf("\n\nbuffer.source1 != buffer.source2, exiting test!!!\n");
+ exit(-1);
+ }
+ }
+
+ if (memcmp(buffer.source1, buffer.source2, BUFSIZE) != 0) {
+ printf("\n\tbuffer.source1 != buffer.source2, exiting test!!!\n");
+ exit(-1);
+ }
+
+ /* Test for zero length */
+ for (i = 0; i < BUFSIZE; i++ ) {
+ int l;
+
+ s1 = &(buffer.source1[i]);
+ s2 = &(buffer.source2[i]);
+ l = 0;
+ rc = memcmp(s1, s2, l);
+ if (rc) {
+ printf("%s, line #%d: Zero length test failed!!!\n", __FILE__, __LINE__);
+ break;
+ }
+ }
+
+
+ for (k = BUFSIZE; k > 0; k-- ) {
+ for (n = 0; n < k; n++) {
+ char c;
+ int l;
+ int m;
+
+ /* Test with aligned start and variable end */
+ if (!TavEqFailed) {
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ l = k;
+ rc = memcmp(s1, s2, l);
+ if (rc != 0) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte aligned block equal test failed!!!\n", __FILE__, __LINE__, k);
+ TavEqFailed = TRUE;
+ }
+ }
+
+ /* Test with variable start and aligned end */
+ if (!TvaEqFailed) {
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ l = k - n;
+ rc = memcmp(s1, s2, l);
+ if (rc != 0) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte unaligned block equal test failed!!!\n", __FILE__, __LINE__, k);
+ TvaEqFailed = TRUE;
+ }
+ }
+
+ /* Test with aligned start and variable end */
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ l = k - n;
+ for (m = 0; m < l && !TavltFailed; m++) {
+ c = s1[m];
+ s1[m] -= 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != -1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte aligned block less than test failed!!!\n", __FILE__, __LINE__, k);
+ TavltFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test with variable start and aligned end */
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ l = k - n;
+ for (m = 0; m < l && !TvaltFailed; m++) {
+ c = s1[m];
+ s1[m] -= 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != -1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte unaligned block less than test failed!!!\n", __FILE__, __LINE__, k);
+ TvaltFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test with aligned start and variable end */
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ l = k - n;
+ for (m = 0; m < l && !TavgtFailed; m++) {
+ c = s1[m];
+ s1[m] += 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != 1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte aligned block greater than test failed!!!\n", __FILE__, __LINE__, k);
+ TavgtFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test with variable start and aligned end */
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ l = k - n;
+ for (m = 0; m < l && !TvagtFailed; m++) {
+ c = s1[m];
+ s1[m] += 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != 1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte unaligned block greater than test failed!!!\n", __FILE__, __LINE__, k);
+ TvagtFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+ }
+ }
+
+ for (k = BUFSIZE; k > 0; k-- ) {
+ for (n = 0; n < k/2; n++) {
+ char c;
+ int m;
+
+ /* Test equal with variable start and end */
+ if (!TvveqFailed) {
+ l = k - 2*n;
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ rc = memcmp(s1, s2, l);
+ if (rc != 0) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte variable block equal test failed!!!\n", __FILE__, __LINE__, l);
+ TvveqFailed = TRUE;
+ }
+ }
+
+ /* Test less than with variable start and end */
+ l = k - 2*n;
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ for (m = 0; m < l && !TvvltFailed; m++) {
+ c = s1[m];
+ s1[m] -= 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != -1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte variable block less than test failed!!!\n", __FILE__, __LINE__, l);
+ TvvltFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test greater than with variable start and end */
+ l = k - 2*n;
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ for (m = 0; m < l && !TvvgtFailed; m++) {
+ c = s1[m];
+ s1[m] += 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != 1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte variable block greater than test failed!!!\n", __FILE__, __LINE__, l);
+ TvvgtFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+ }
+ }
+
+
+ /* Misc test1 */
+ for (k = 0; k < NTUL; k++) {
+
+ source2_16[3] = tul[k];
+
+ rc = memcmp(source1_16,source2_16,TEST16*sizeof(unsigned long));
+ if (rc != tul_test[k]) {
+
+ printf("source1_16 = ");
+ for (i = 0; i < TEST16*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source1_16)[i]);
+ printf("\n");
+
+ printf("source2_16 = ");
+ for (i = 0; i < TEST16*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source2_16)[i]);
+ printf("%s, line #%d: Misc Test #1, case #%d of %d failed!!!\n", __FILE__, __LINE__, k+1, NTUL);
+ printf("Return Code = %d, Should be = %d\n",rc,tul_test[k]);
+ Tmisc++;
+ }
+ }
+
+
+ /* Misc test2 */
+ l = 32;
+ buffer.source2[0] = '"';
+ for (i = 0; i < l; i++) {
+ buffer.source1[i] = source32[i];
+ buffer.source2[i+1] = source32[i];
+ }
+ buffer.source2[l+1] = '"';
+ s1 = &(buffer.source1[0]);
+ s2 = &(buffer.source2[1]);
+ if (0 != memcmp(s1, s2, l)) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: Misc Test #2 failed!!!\n", __FILE__, __LINE__);
+ Tmisc++;
+ }
+
+
+ rc = TavEqFailed + TvaEqFailed + TavltFailed + TvaltFailed + TavgtFailed + TvagtFailed + TvveqFailed + TvvltFailed + TvvgtFailed + Tmisc;
+ if (rc) {
+ printf("\n\tMEMCMP failed %d tests!!!\n", rc);
+ exit(rc);
+ } else {
+ printf("\n\tMEMCMP passed all tests!!!\n");
+ exit(0);
+ }
+}
diff --git a/private/crt32/string/mips/memcpym.s b/private/crt32/string/mips/memcpym.s
new file mode 100644
index 000000000..ca0f8fe78
--- /dev/null
+++ b/private/crt32/string/mips/memcpym.s
@@ -0,0 +1,298 @@
+/*
+ * Fast bcopy code which supports overlapped copies.
+ * Not fully optimized yet.
+ *
+ * Written by: Kipp Hickman
+ *
+ * $Source: /proj/sherwood/isms/irix/lib/libc/src/strings/RCS/bcopy.s,v $
+ * $Revision: 1.7 $
+ * $Date: 1993/11/20 19:23:11 $
+ */
+
+#include <kxmips.h>
+
+/*
+ * char *bcopy(from, to, count);
+ * unsigned char *from, *to;
+ * unsigned long count;
+ *
+ * OR
+ *
+ * void *memcpy/memmove(to, from, count);
+ * void *to, *from;
+ * unsigned long count;
+ *
+ * Both functions return "to"
+ */
+
+#define MINCOPY 16
+
+/* registers used */
+
+#define to a0
+#define from a1
+#define count a2
+
+LEAF_ENTRY(memcpy)
+ALTERNATE_ENTRY(memmove)
+ move a3,to # Save to in a3
+ beq count,zero,ret # Test for zero count
+ beq from,to,ret # Test for from == to
+
+ /* use backwards copying code if the from and to regions overlap */
+ blt to,from,goforwards # If to < from then use forwards copy
+ add v0,from,count # v0 := from + count
+ bge to,v0,goforwards # If to >= from + count; no overlap
+ b gobackwards # Oh well, go backwards
+
+/*****************************************************************************/
+
+/*
+ * Forward copy code. Check for pointer alignment and try to get both
+ * pointers aligned on a long boundary.
+ */
+goforwards:
+ /* small byte counts use byte at a time copy */
+ blt count,MINCOPY,forwards_bytecopy
+ and v0,from,3 # v0 := from & 3
+ and v1,to,3 # v1 := to & 3
+ beq v0,v1,forwalignable # low bits are identical
+/*
+ * Byte at a time copy code. This is used when the pointers are not
+ * alignable, when the byte count is small, or when cleaning up any
+ * remaining bytes on a larger transfer.
+ */
+forwards_bytecopy:
+ beq count,zero,ret # If count is zero, then we are done
+ addu v1,from,count # v1 := from + count
+
+99: lb v0,0(from) # v0 = *from
+ addu from,1 # advance pointer
+ sb v0,0(to) # Store byte
+ addu to,1 # advance pointer
+ bne from,v1,99b # Loop until done
+ret: move v0,a3 # Set v0 to old "to" pointer
+ j ra # return to caller
+
+/*
+ * Pointers are alignable, and may be aligned. Since v0 == v1, we need only
+ * check what value v0 has to see how to get aligned. Also, since we have
+ * eliminated tiny copies, we know that the count is large enough to
+ * encompass the alignment copies.
+ */
+forwalignable:
+ beq v0,zero,forwards # If v0==v1 && v0==0 then aligned
+ beq v0,1,forw_copy3 # Need to copy 3 bytes to get aligned
+ beq v0,2,forw_copy2 # Need to copy 2 bytes to get aligned
+
+/* need to copy 1 byte */
+ lb v0,0(from) # get one byte
+ addu from,1 # advance pointer
+ sb v0,0(to) # store one byte
+ addu to,1 # advance pointer
+ subu count,1 # and reduce count
+ b forwards # Now pointers are aligned
+
+/* need to copy 2 bytes */
+forw_copy2:
+ lh v0,0(from) # get one short
+ addu from,2 # advance pointer
+ sh v0,0(to) # store one short
+ addu to,2 # advance pointer
+ subu count,2 # and reduce count
+ b forwards
+
+/* need to copy 3 bytes */
+forw_copy3:
+ lb v0,0(from) # get one byte
+ lh v1,1(from) # and one short
+ addu from,3 # advance pointer
+ sb v0,0(to) # store one byte
+ sh v1,1(to) # and one short
+ addu to,3 # advance pointer
+ subu count,3 # and reduce count
+ /* FALLTHROUGH */
+/*
+ * Once we are here, the pointers are aligned on long boundaries.
+ * Begin copying in large chunks.
+ */
+forwards:
+
+/* 32 byte at a time loop */
+forwards_32:
+ blt count,32,forwards_16 # do 16 bytes at a time
+ lw v0,0(from)
+ lw v1,4(from)
+ lw t0,8(from)
+ lw t1,12(from)
+ lw t2,16(from)
+ lw t3,20(from)
+ lw t4,24(from)
+ lw t5,28(from) # Fetch 8*4 bytes
+ addu from,32 # advance from pointer now
+ sw v0,0(to)
+ sw v1,4(to)
+ sw t0,8(to)
+ sw t1,12(to)
+ sw t2,16(to)
+ sw t3,20(to)
+ sw t4,24(to)
+ sw t5,28(to) # Store 8*4 bytes
+ addu to,32 # advance to pointer now
+ subu count,32 # Reduce count
+ b forwards_32 # Try some more
+
+/* 16 byte at a time loop */
+forwards_16:
+ blt count,16,forwards_4 # Do rest in words
+ lw v0,0(from)
+ lw v1,4(from)
+ lw t0,8(from)
+ lw t1,12(from)
+ addu from,16 # advance from pointer now
+ sw v0,0(to)
+ sw v1,4(to)
+ sw t0,8(to)
+ sw t1,12(to)
+ addu to,16 # advance to pointer now
+ subu count,16 # Reduce count
+ b forwards_16 # Try some more
+
+/* 4 bytes at a time loop */
+forwards_4:
+ blt count,4,forwards_bytecopy # Do rest
+ lw v0,0(from)
+ addu from,4 # advance pointer
+ sw v0,0(to)
+ addu to,4 # advance pointer
+ subu count,4
+ b forwards_4
+
+/*****************************************************************************/
+
+/*
+ * Backward copy code. Check for pointer alignment and try to get both
+ * pointers aligned on a long boundary.
+ */
+gobackwards:
+ add from,count # Advance to end + 1
+ add to,count # Advance to end + 1
+
+ /* small byte counts use byte at a time copy */
+ blt count,MINCOPY,backwards_bytecopy
+ and v0,from,3 # v0 := from & 3
+ and v1,to,3 # v1 := to & 3
+ beq v0,v1,backalignable # low bits are identical
+/*
+ * Byte at a time copy code. This is used when the pointers are not
+ * alignable, when the byte count is small, or when cleaning up any
+ * remaining bytes on a larger transfer.
+ */
+backwards_bytecopy:
+ beq count,zero,ret # If count is zero quit
+ subu from,1 # Reduce by one (point at byte)
+ subu to,1 # Reduce by one (point at byte)
+ subu v1,from,count # v1 := original from - 1
+
+99: lb v0,0(from) # v0 = *from
+ subu from,1 # backup pointer
+ sb v0,0(to) # Store byte
+ subu to,1 # backup pointer
+ bne from,v1,99b # Loop until done
+ move v0,a3 # Set v0 to old "to" pointer
+ j ra # return to caller
+
+/*
+ * Pointers are alignable, and may be aligned. Since v0 == v1, we need only
+ * check what value v0 has to see how to get aligned. Also, since we have
+ * eliminated tiny copies, we know that the count is large enough to
+ * encompass the alignment copies.
+ */
+backalignable:
+ beq v0,zero,backwards # If v0==v1 && v0==0 then aligned
+ beq v0,3,back_copy3 # Need to copy 3 bytes to get aligned
+ beq v0,2,back_copy2 # Need to copy 2 bytes to get aligned
+
+/* need to copy 1 byte */
+ lb v0,-1(from) # get one byte
+ subu from,1 # backup pointer
+ sb v0,-1(to) # store one byte
+ subu to,1 # backup pointer
+ subu count,1 # and reduce count
+ b backwards # Now pointers are aligned
+
+/* need to copy 2 bytes */
+back_copy2:
+ lh v0,-2(from) # get one short
+ subu from,2 # backup pointer
+ sh v0,-2(to) # store one short
+ subu to,2 # backup pointer
+ subu count,2 # and reduce count
+ b backwards
+
+/* need to copy 3 bytes */
+back_copy3:
+ lb v0,-1(from) # get one byte
+ lh v1,-3(from) # and one short
+ subu from,3 # backup pointer
+ sb v0,-1(to) # store one byte
+ sh v1,-3(to) # and one short
+ subu to,3 # backup pointer
+ subu count,3 # and reduce count
+ /* FALLTHROUGH */
+/*
+ * Once we are here, the pointers are aligned on long boundaries.
+ * Begin copying in large chunks.
+ */
+backwards:
+
+/* 32 byte at a time loop */
+backwards_32:
+ blt count,32,backwards_16 # do 16 bytes at a time
+ lw v0,-4(from)
+ lw v1,-8(from)
+ lw t0,-12(from)
+ lw t1,-16(from)
+ lw t2,-20(from)
+ lw t3,-24(from)
+ lw t4,-28(from)
+ lw t5,-32(from) # Fetch 8*4 bytes
+ subu from,32 # backup from pointer now
+ sw v0,-4(to)
+ sw v1,-8(to)
+ sw t0,-12(to)
+ sw t1,-16(to)
+ sw t2,-20(to)
+ sw t3,-24(to)
+ sw t4,-28(to)
+ sw t5,-32(to) # Store 8*4 bytes
+ subu to,32 # backup to pointer now
+ subu count,32 # Reduce count
+ b backwards_32 # Try some more
+
+/* 16 byte at a time loop */
+backwards_16:
+ blt count,16,backwards_4 # Do rest in words
+ lw v0,-4(from)
+ lw v1,-8(from)
+ lw t0,-12(from)
+ lw t1,-16(from)
+ subu from,16 # backup from pointer now
+ sw v0,-4(to)
+ sw v1,-8(to)
+ sw t0,-12(to)
+ sw t1,-16(to)
+ subu to,16 # backup to pointer now
+ subu count,16 # Reduce count
+ b backwards_16 # Try some more
+
+/* 4 byte at a time loop */
+backwards_4:
+ blt count,4,backwards_bytecopy # Do rest
+ lw v0,-4(from)
+ subu from,4 # backup from pointer
+ sw v0,-4(to)
+ subu to,4 # backup to pointer
+ subu count,4 # Reduce count
+ b backwards_4
+.end memcpy
diff --git a/private/crt32/string/mips/memorym.s b/private/crt32/string/mips/memorym.s
new file mode 100644
index 000000000..6f98423dc
--- /dev/null
+++ b/private/crt32/string/mips/memorym.s
@@ -0,0 +1,1218 @@
+// TITLE("Compare, Move, and Fill Memory Support")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// memory.s
+//
+// Abstract:
+//
+// This module implements functions to compare, move, zero, and fill
+// blocks of memory. If the memory is aligned, then these functions
+// are very efficient.
+//
+// N.B. These routines MUST preserve all floating state since they are
+// frequently called from interrupt service routines that normally
+// do not save or restore floating state.
+//
+// Author:
+//
+// David N. Cutler (davec) 11-Apr-1990
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+// 02/02/94 RDL This is a cloned version of ntos\rtl\mips\xxmvmem.s
+// Used RtlMoveMemory and RtlFillMemory.
+// 02/15/94 RDL Used RtlCompareMemory, changed return code for memcmp.
+// 02/22/94 RDL Fixed memcmp, zero length and equal aligned 32-byte
+// buffers return wrong code.
+//
+//--
+
+#include "ksmips.h"
+ SBTTL("Compare Memory")
+
+//++
+//
+// ULONG
+// RtlCompareMemory (
+// IN PVOID Source1,
+// IN PVOID Source2,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function compares two blocks of memory and returns the number
+// of bytes that compared equal.
+//
+// Arguments:
+//
+// Source1 (a0) - Supplies a pointer to the first block of memory to
+// compare.
+//
+// Source2 (a1) - Supplies a pointer to the second block of memory to
+// compare.
+//
+// Length (a2) - Supplies the length, in bytes, of the memory to be
+// compared.
+//
+// Return Value:
+//
+// zero if source1 == source2
+// -1 if source1 < source2
+// 1 if source1 > source2
+// value. If all bytes compared equal, then the length of the orginal
+// block of memory is returned.
+//
+//--
+
+ LEAF_ENTRY(memcmp)
+
+ addu a3,a0,a2 // compute ending address of source1
+ move v0,a2 // save length of comparison
+ and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t4,a0,t1 // compute ending block address
+ beq zero,t1,100f // if eq, no 32-byte block to compare
+ or t0,a0,a1 // merge and isolate alignment bits
+ and t0,t0,0x3 //
+ bne zero,t0,CompareUnaligned // if ne, unalignment comparison
+
+//
+// Compare memory aligned.
+//
+
+CompareAligned: //
+
+ .set noreorder
+10: lw t0,0(a0) // compare 32-byte block
+ lw t1,0(a1) //
+ lw t2,4(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lw t3,4(a1) //
+ lw t0,8(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lw t1,8(a1) //
+ lw t2,12(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lw t3,12(a1) //
+ lw t0,16(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lw t1,16(a1) //
+ lw t2,20(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lw t3,20(a1) //
+ lw t0,24(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lw t1,24(a1) //
+ lw t2,28(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lw t3,28(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Compare memory unaligned.
+//
+
+CompareUnaligned: //
+ and t0,a0,0x3 // isolate source1 alignment
+ bne zero,t0,CompareUnalignedS1 // if ne, source1 unaligned
+
+//
+// Source1 is aligned and Source2 is unaligned.
+//
+
+CompareUnalignedS2: //
+
+ .set noreorder
+10: lw t0,0(a0) // compare 32-byte block
+ lwr t1,0(a1) //
+ lwl t1,3(a1) //
+ lw t2,4(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lwr t3,4(a1) //
+ lwl t3,7(a1) //
+ lw t0,8(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lwr t1,8(a1) //
+ lwl t1,11(a1) //
+ lw t2,12(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lwr t3,12(a1) //
+ lwl t3,15(a1) //
+ lw t0,16(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lwr t1,16(a1) //
+ lwl t1,19(a1) //
+ lw t2,20(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lwr t3,20(a1) //
+ lwl t3,23(a1) //
+ lw t0,24(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lwr t1,24(a1) //
+ lwl t1,27(a1) //
+ lw t2,28(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lwr t3,28(a1) //
+ lwl t3,31(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Source1 is unaligned, check Source2 alignment.
+//
+
+CompareUnalignedS1: //
+ and t0,a1,0x3 // isolate Source2 alignment
+ bne zero,t0,CompareUnalignedS1AndS2 // if ne, Source2 unaligned
+
+//
+// Source1 is unaligned and Source2 is aligned.
+//
+
+ .set noreorder
+10: lwr t0,0(a0) // compare 32-byte block
+ lwl t0,3(a0) //
+ lw t1,0(a1) //
+ lwr t2,4(a0) //
+ lwl t2,7(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lw t3,4(a1) //
+ lwr t0,8(a0) //
+ lwl t0,11(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lw t1,8(a1) //
+ lwr t2,12(a0) //
+ lwl t2,15(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lw t3,12(a1) //
+ lwr t0,16(a0) //
+ lwl t0,19(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lw t1,16(a1) //
+ lwr t2,20(a0) //
+ lwl t2,23(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lw t3,20(a1) //
+ lwr t0,24(a0) //
+ lwl t0,27(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lw t1,24(a1) //
+ lwr t2,28(a0) //
+ lwl t2,31(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lw t3,28(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Source1 and Source2 are unaligned.
+//
+
+CompareUnalignedS1AndS2: //
+
+ .set noreorder
+10: lwr t0,0(a0) // compare 32-byte block
+ lwl t0,3(a0) //
+ lwr t1,0(a1) //
+ lwl t1,3(a1) //
+ lwr t2,4(a0) //
+ lwl t2,7(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lwr t3,4(a1) //
+ lwl t3,7(a1) //
+ lwr t0,8(a0) //
+ lwl t0,11(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lwr t1,8(a1) //
+ lwl t1,11(a1) //
+ lwr t2,12(a0) //
+ lwl t2,15(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lwr t3,12(a1) //
+ lwl t3,15(a1) //
+ lwr t0,16(a0) //
+ lwl t0,19(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lwr t1,16(a1) //
+ lwl t1,19(a1) //
+ lwr t2,20(a0) //
+ lwl t2,23(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lwr t3,20(a1) //
+ lwl t3,23(a1) //
+ lwr t0,24(a0) //
+ lwl t0,27(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lwr t1,24(a1) //
+ lwl t1,27(a1) //
+ lwr t2,28(a0) //
+ lwl t2,31(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lwr t3,28(a1) //
+ lwl t3,31(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Adjust source1 and source2 pointers dependent on position of miscompare in
+// block.
+//
+
+20: addu a0,a0,4 // mismatch on second word
+ addu a1,a1,4 //
+ b 90f //
+
+30: addu a0,a0,8 // mismatch on third word
+ addu a1,a1,8 //
+ b 90f //
+
+40: addu a0,a0,12 // mistmatch on fourth word
+ addu a1,a1,12 //
+ b 90f //
+
+50: addu a0,a0,16 // mismatch on fifth word
+ addu a1,a1,16 //
+ b 90f //
+
+60: addu a0,a0,20 // mismatch on sixth word
+ addu a1,a1,20 //
+ b 90f //
+
+70: addu a0,a0,24 // mismatch on seventh word
+ addu a1,a1,24 //
+ b 90f //
+
+80: subu a0,a0,4 // mismatch on eighth word
+ addu a1,a1,28 //
+90: subu a2,a3,a0 // compute remaining bytes
+
+//
+// Compare 1-byte blocks.
+//
+
+100: addu t2,a0,a2 // compute ending block address
+ beq zero,a2,120f // if eq, buffers equal
+110: lb t0,0(a0) // compare 1-byte block
+ lb t1,0(a1) //
+ addu a1,a1,1 // advance pointers to next block
+ bne t0,t1,130f // if ne, byte not equal
+ addu a0,a0,1 //
+ bne a0,t2,110b // if ne, more 1-byte block to zero
+
+120: move v0,zero // source1 == source2
+ j ra // return
+
+130: sltu v0,t1,t0 // compare source1 to source2
+ beq v0,zero,140f
+ j ra // return, source1 > source2
+140:
+ li v0,-1
+ j ra // return, source1 < source2
+
+ .end memcmp
+
+ SBTTL("Move Memory")
+//++
+//
+// VOID
+// RtlMoveMemory (
+// IN PVOID Destination,
+// IN PVOID Source,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function moves memory either forward or backward, aligned or
+// unaligned, in 32-byte blocks, followed by 4-byte blocks, followed
+// by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Source (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Length (a2) - Supplies the length, in bytes, of the memory to be moved.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. The C runtime entry points memmove and memcpy are equivalent to
+// RtlMoveMemory thus alternate entry points are provided for these
+// routines.
+//--
+
+ LEAF_ENTRY(memmove)
+ j memcpy
+ .end memmove
+
+ LEAF_ENTRY(memcpy)
+
+ move v0,a0 // return destination
+
+//
+// If the source address is less than the destination address and source
+// address plus the length of the move is greater than the destination
+// address, then the source and destination overlap such that the move
+// must be performed backwards.
+//
+
+10: bgeu a1,a0,MoveForward // if geu, no overlap possible
+ addu t0,a1,a2 // compute source ending address
+ bgtu t0,a0,MoveBackward // if gtu, source and destination overlap
+
+//
+// Move memory forward aligned and unaligned.
+//
+
+MoveForward: //
+ sltu t0,a2,4 // check if less than four bytes
+ bne zero,t0,50f // if ne, less than four bytes to move
+ xor t0,a0,a1 // compare alignment bits
+ and t0,t0,0x3 // isolate alignment comparison
+ bne zero,t0,MoveForwardUnaligned // if ne, incompatible alignment
+
+//
+// Move memory forward aligned.
+//
+
+MoveForwardAligned: //
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwr t1,0(a1) // move unaligned bytes
+ swr t1,0(a0) //
+ addu a0,a0,t0 // align destination address
+ addu a1,a1,t0 // align source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte blocks.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destination quadword aligned
+ beq zero,t0,15f // if eq, destination quadword aligned
+ lw t0,0(a1) // get source longword
+ addu a1,a1,4 // align source address
+ sw t0,0(a0) // store destination longword
+ addu a0,a0,4 // align destination address
+ addu a2,a2,t1 // recompute bytes to move
+ subu a2,a2,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned, check the source operand.
+//
+
+15: and t0,a1,1 << 2 // check if source quadword aligned
+ beq zero,t0,22f // if eq, source quadword aligned
+
+//
+// The source is longword aligned and the destination is quadword aligned.
+//
+
+ .set noreorder
+20: lwc1 f0,0(a1) // move 32-byte block
+ lwc1 f1,4(a1) //
+ lwc1 f2,8(a1) //
+ lwc1 f3,12(a1) //
+ lwc1 f4,16(a1) //
+ lwc1 f5,20(a1) //
+ lwc1 f6,24(a1) //
+ lwc1 f7,28(a1) //
+ sdc1 f0,0(a0) //
+ sdc1 f2,8(a0) //
+ sdc1 f4,16(a0) //
+ sdc1 f6,24(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ addu a1,a1,32 //
+ .set reorder
+
+ b 30f //
+
+//
+// Both the source and the destination are quadword aligned.
+//
+
+22: and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,26f // if eq, even number of 32-byte blocks
+
+//
+// Move one 32-byte block quadword aligned.
+//
+
+ .set noreorder
+ ldc1 f0,0(a1) // move 32-byte block
+ ldc1 f2,8(a1) //
+ ldc1 f4,16(a1) //
+ ldc1 f6,24(a1) //
+ sdc1 f0,0(a0) //
+ sdc1 f2,8(a0) //
+ sdc1 f4,16(a0) //
+ sdc1 f6,24(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ beq a0,t8,30f // if eq, end of block
+ addu a1,a1,32 //
+ .set reorder
+
+//
+// Move 64-byte blocks quadword aligned.
+//
+
+ .set noreorder
+26: ldc1 f0,0(a1) // move 64-byte block
+ ldc1 f2,8(a1) //
+ ldc1 f4,16(a1) //
+ ldc1 f6,24(a1) //
+ ldc1 f8,32(a1) //
+ ldc1 f10,40(a1) //
+ ldc1 f12,48(a1) //
+ ldc1 f14,56(a1) //
+ sdc1 f0,0(a0) //
+ sdc1 f2,8(a0) //
+ sdc1 f4,16(a0) //
+ sdc1 f6,24(a0) //
+ sdc1 f8,32(a0) //
+ sdc1 f10,40(a0) //
+ sdc1 f12,48(a0) //
+ sdc1 f14,56(a0) //
+ addu a0,a0,64 // advance pointers to next block
+ bne a0,t8,26b // if ne, more 64-byte blocks to zero
+ addu a1,a1,64 //
+ .set reorder
+
+#endif
+
+//
+// The source is longword aligned and the destination is longword aligned.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: lw t0,0(a1) // move 32-byte block
+ lw t1,4(a1) //
+ lw t2,8(a1) //
+ lw t3,12(a1) //
+ lw t4,16(a1) //
+ lw t5,20(a1) //
+ lw t6,24(a1) //
+ lw t7,28(a1) //
+ sw t0,0(a0) //
+ sw t1,4(a0) //
+ sw t2,8(a0) //
+ sw t3,12(a0) //
+ sw t4,16(a0) //
+ sw t5,20(a0) //
+ sw t6,24(a0) //
+ sw t7,28(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ addu a1,a1,32 //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lw t0,0(a1) // move 4-byte block
+ addu a0,a0,4 // advance pointers to next block
+ sw t0,-4(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ addu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: addu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,0(a1) // move 1-byte block
+ addu a0,a0,1 // advance pointers to next block
+ sb t0,-1(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ addu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+//
+// Move memory forward unaligned.
+//
+
+MoveForwardUnaligned: //
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwr t1,0(a1) // move unaligned bytes
+ lwl t1,3(a1) //
+ swr t1,0(a0) //
+ addu a0,a0,t0 // align destination address
+ addu a1,a1,t0 // update source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte block.
+//
+
+ .set noreorder
+20: lwr t0,0(a1) // move 32-byte block
+ lwl t0,3(a1) //
+ lwr t1,4(a1) //
+ lwl t1,7(a1) //
+ lwr t2,8(a1) //
+ lwl t2,11(a1) //
+ lwr t3,12(a1) //
+ lwl t3,15(a1) //
+ lwr t4,16(a1) //
+ lwl t4,19(a1) //
+ lwr t5,20(a1) //
+ lwl t5,23(a1) //
+ lwr t6,24(a1) //
+ lwl t6,27(a1) //
+ lwr t7,28(a1) //
+ lwl t7,31(a1) //
+ sw t0,0(a0) //
+ sw t1,4(a0) //
+ sw t2,8(a0) //
+ sw t3,12(a0) //
+ sw t4,16(a0) //
+ sw t5,20(a0) //
+ sw t6,24(a0) //
+ sw t7,28(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ addu a1,a1,32 //
+ .set reorder
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lwr t0,0(a1) // move 4-byte block
+ lwl t0,3(a1) //
+ addu a0,a0,4 // advance pointers to next block
+ sw t0,-4(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ addu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: addu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,0(a1) // move 1-byte block
+ addu a0,a0,1 // advance pointers to next block
+ sb t0,-1(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ addu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+//
+// Move memory backward.
+//
+
+MoveBackward: //
+ addu a0,a0,a2 // compute ending destination address
+ addu a1,a1,a2 // compute ending source address
+ sltu t0,a2,4 // check if less than four bytes
+ bne zero,t0,50f // if ne, less than four bytes to move
+ xor t0,a0,a1 // compare alignment bits
+ and t0,t0,0x3 // isolate alignment comparison
+ bne zero,t0,MoveBackwardUnaligned // if ne, incompatible alignment
+
+//
+// Move memory backward aligned.
+//
+
+MoveBackwardAligned: //
+ and t0,a0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwl t1,-1(a1) // move unaligned bytes
+ swl t1,-1(a0) //
+ subu a0,a0,t0 // align destination address
+ subu a1,a1,t0 // align source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte block.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destination quadword aligned
+ beq zero,t0,15f // if eq, destination quadword aligned
+ lw t0,-4(a1) // get source longword
+ subu a1,a1,4 // align source address
+ sw t0,-4(a0) // store destination longword
+ subu a0,a0,4 // align destination address
+ addu a2,a2,t1 // recompute byte to move
+ subu a2,a2,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned, check the source operand.
+//
+
+15: and t0,a1,1 << 2 // check if source quadword aligned
+ beq zero,t0,22f // if eq, source quadword aligned
+
+//
+// The source is longword aligned and the destination is quadword aligned.
+//
+
+ .set noreorder
+20: lwc1 f1,-4(a1) // move 32-byte block
+ lwc1 f0,-8(a1) //
+ lwc1 f3,-12(a1) //
+ lwc1 f2,-16(a1) //
+ lwc1 f5,-20(a1) //
+ lwc1 f4,-24(a1) //
+ lwc1 f7,-28(a1) //
+ lwc1 f6,-32(a1) //
+ sdc1 f0,-8(a0) //
+ sdc1 f2,-16(a0) //
+ sdc1 f4,-24(a0) //
+ sdc1 f6,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ subu a1,a1,32 //
+ .set reorder
+
+ b 30f //
+
+//
+// Both the source and the destination are quadword aligned.
+//
+
+22: and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,26f // if eq, even number of 32-byte blocks
+
+//
+// Move one 32-byte block quadword aligned.
+//
+
+ .set noreorder
+ ldc1 f0,-8(a1) // move 32-byte block
+ ldc1 f2,-16(a1) //
+ ldc1 f4,-24(a1) //
+ ldc1 f6,-32(a1) //
+ sdc1 f0,-8(a0) //
+ sdc1 f2,-16(a0) //
+ sdc1 f4,-24(a0) //
+ sdc1 f6,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ beq a0,t8,30f // if eq, end of block
+ subu a1,a1,32 //
+ .set reorder
+
+//
+// Move 64-byte blocks quadword aligned.
+//
+
+ .set noreorder
+26: ldc1 f0,-8(a1) // move 64-byte block
+ ldc1 f2,-16(a1) //
+ ldc1 f4,-24(a1) //
+ ldc1 f6,-32(a1) //
+ ldc1 f8,-40(a1) //
+ ldc1 f10,-48(a1) //
+ ldc1 f12,-56(a1) //
+ ldc1 f14,-64(a1) //
+ sdc1 f0,-8(a0) //
+ sdc1 f2,-16(a0) //
+ sdc1 f4,-24(a0) //
+ sdc1 f6,-32(a0) //
+ sdc1 f8,-40(a0) //
+ sdc1 f10,-48(a0) //
+ sdc1 f12,-56(a0) //
+ sdc1 f14,-64(a0) //
+ subu a0,a0,64 // advance pointers to next block
+ bne a0,t8,26b // if ne, more 64-byte blocks to zero
+ subu a1,a1,64 //
+ .set reorder
+
+#endif
+
+//
+// The source is longword aligned and the destination is longword aligned.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: lw t0,-4(a1) // move 32-byte block
+ lw t1,-8(a1) //
+ lw t2,-12(a1) //
+ lw t3,-16(a1) //
+ lw t4,-20(a1) //
+ lw t5,-24(a1) //
+ lw t6,-28(a1) //
+ lw t7,-32(a1) //
+ sw t0,-4(a0) //
+ sw t1,-8(a0) //
+ sw t2,-12(a0) //
+ sw t3,-16(a0) //
+ sw t4,-20(a0) //
+ sw t5,-24(a0) //
+ sw t6,-28(a0) //
+ sw t7,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ subu a1,a1,32 //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lw t0,-4(a1) // move 4-byte block
+ subu a0,a0,4 // advance pointers to next block
+ sw t0,0(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ subu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: subu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,-1(a1) // move 1-byte block
+ subu a0,a0,1 // advance pointers to next block
+ sb t0,0(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ subu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+//
+// Move memory backward unaligned.
+//
+
+MoveBackwardUnaligned: //
+ and t0,a0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwl t1,-1(a1) // move unaligned bytes
+ lwr t1,-4(a1) //
+ swl t1,-1(a0) //
+ subu a0,a0,t0 // align destination address
+ subu a1,a1,t0 // update source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte block.
+//
+
+ .set noreorder
+20: lwr t0,-4(a1) // move 32-byte block
+ lwl t0,-1(a1) //
+ lwr t1,-8(a1) //
+ lwl t1,-5(a1) //
+ lwr t2,-12(a1) //
+ lwl t2,-9(a1) //
+ lwr t3,-16(a1) //
+ lwl t3,-13(a1) //
+ lwr t4,-20(a1) //
+ lwl t4,-17(a1) //
+ lwr t5,-24(a1) //
+ lwl t5,-21(a1) //
+ lwr t6,-28(a1) //
+ lwl t6,-25(a1) //
+ lwr t7,-32(a1) //
+ lwl t7,-29(a1) //
+ sw t0,-4(a0) //
+ sw t1,-8(a0) //
+ sw t2,-12(a0) //
+ sw t3,-16(a0) //
+ sw t4,-20(a0) //
+ sw t5,-24(a0) //
+ sw t6,-28(a0) //
+ sw t7,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ subu a1,a1,32 //
+ .set reorder
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lwr t0,-4(a1) // move 4-byte block
+ lwl t0,-1(a1) //
+ subu a0,a0,4 // advance pointers to next block
+ sw t0,0(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ subu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: subu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,-1(a1) // move 1-byte block
+ subu a0,a0,1 // advance pointers to next block
+ sb t0,0(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ subu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+ .end memcpy
+
+ SBTTL("Fill Memory")
+//++
+//
+// VOID
+// RtlFillMemory (
+// IN PVOID Destination,
+// IN ULONG Length,
+// IN UCHAR Fill
+// )
+//
+// Routine Description:
+//
+// This function fills memory by first aligning the destination address to
+// a longword boundary, and then filling 32-byte blocks, followed by 4-byte
+// blocks, followed by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the memory to fill.
+//
+// Length (a1) - Supplies the length, in bytes, of the memory to be filled.
+//
+// Fill (a2) - Supplies the fill byte.
+//
+// N.B. The alternate entry memset expects the length and fill arguments
+// to be reversed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(memset)
+
+ move a3,a1 // swap length and fill arguments
+ move a1,a2 //
+ move a2,a3 //
+ move v0,a0 // return destination
+
+ and a2,a2,0xff // clear excess bits
+ sll t0,a2,8 // duplicate fill byte
+ or a2,a2,t0 // generate fill word
+ sll t0,a2,16 // duplicate fill word
+ or a2,a2,t0 // generate fill longword
+
+//
+// Fill memory with the pattern specified in register a2.
+//
+
+#if DBG
+
+ mtc1 a2,f0 // set pattern to store
+ mtc1 a2,f1 //
+
+#endif
+
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu t1,a1,t0 // reduce number of bytes to fill
+ blez t1,60f // if lez, less than 4 bytes to fill
+ move a1,t1 // set number of bytes to fill
+ beq zero,t0,10f // if eq, already aligned
+ swr a2,0(a0) // fill unaligned bytes
+ addu a0,a0,t0 // align destination address
+
+//
+// Check for 32-byte blocks to fill.
+//
+
+10: and t0,a1,32 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,40f // if eq, no 32-byte blocks to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destintion quadword aligned
+ beq zero,t0,20f // if eq, yes
+ sw a2,0(a0) // store destination longword
+ addu a0,a0,4 // align destination address
+ addu a1,a1,t1 // recompute bytes to fill
+ subu a1,a1,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned.
+//
+
+20: mtc1 a2,f0 // set pattern value
+ mtc1 a2,f1 //
+ and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,30f // if eq, even number of 32-byte blocks
+
+//
+// Fill one 32-byte block.
+//
+
+ .set noreorder
+ sdc1 f0,0(a0) // fill 32-byte block
+ sdc1 f0,8(a0) //
+ sdc1 f0,16(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ beq a0,t2,40f // if ne, no 64-byte blocks to fill
+ sdc1 f0,-8(a0) //
+ .set reorder
+
+//
+// Fill 64-byte block.
+//
+
+ .set noreorder
+30: sdc1 f0,0(a0) // fill 32-byte block
+ sdc1 f0,8(a0) //
+ sdc1 f0,16(a0) //
+ sdc1 f0,24(a0) //
+ sdc1 f0,32(a0) //
+ sdc1 f0,40(a0) //
+ sdc1 f0,48(a0) //
+ addu a0,a0,64 // advance pointer to next block
+ bne a0,t2,30b // if ne, more 32-byte blocks to fill
+ sdc1 f0,-8(a0) //
+ .set reorder
+
+#endif
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: sw a2,0(a0) // fill 32-byte block
+ sw a2,4(a0) //
+ sw a2,8(a0) //
+ sw a2,12(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ sw a2,-4(a0) //
+ sw a2,-8(a0) //
+ sw a2,-12(a0) //
+ bne a0,t2,20b // if ne, more 32-byte blocks to fill
+ sw a2,-16(a0) //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to fill.
+//
+
+40: and t0,a1,4 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,60f // if eq, no 4-byte block to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 4-byte blocks.
+//
+
+ .set noreorder
+50: addu a0,a0,4 // advance pointer to next block
+ bne a0,t2,50b // if ne, more 4-byte blocks to fill
+ sw a2,-4(a0) // fill 4-byte block
+ .set reorder
+
+//
+// Check for 1-byte blocks to fill.
+//
+
+60: addu t2,a0,a1 // compute ending block address
+ beq zero,a1,80f // if eq, no bytes to fill
+
+//
+// Fill 1-byte blocks.
+//
+
+ .set noreorder
+70: addu a0,a0,1 // advance pointer to next block
+ bne a0,t2,70b // if ne, more 1-byte block to fill
+ sb a2,-1(a0) // fill 1-byte block
+ .set reorder
+
+#if DBG
+
+80: mfc1 t0,f0 // get fill pattern
+ mfc1 t1,f1 //
+ bne t0,a2,90f // if ne, pattern altered
+ bne t1,a2,90f // if ne, pattern altered
+ j ra // return
+
+90: break KERNEL_BREAKPOINT //
+
+#else
+
+80: j ra // return
+
+#endif
+
+ .end memset
diff --git a/private/crt32/string/mips/memsetm.s b/private/crt32/string/mips/memsetm.s
new file mode 100644
index 000000000..a53f8f0a1
--- /dev/null
+++ b/private/crt32/string/mips/memsetm.s
@@ -0,0 +1,105 @@
+/* --------------------------------------------------- */
+/* | Copyright (c) 1986 MIPS Computer Systems, Inc. | */
+/* | All Rights Reserved. | */
+/* --------------------------------------------------- */
+/* $Revision: 1.3 $ */
+
+/*
+ * char *
+ * memset(s, c, n)
+ * register char * s;
+ * register c, n;
+ * {
+ * register char * p = s;
+ *
+ * while (--n >= 0)
+ * *s++ = c;
+ *
+ * return (p);
+ * }
+ */
+
+/*
+ * Copyright 1986 by MIPS Computer Systems, Inc.
+ */
+
+#include <kxmips.h>
+
+#define NBPW 4
+
+/*
+ * memset(dst, c, bcount)
+ * set block of memory with blanks
+ *
+ * Calculating MINSET, assuming 10% cache-miss on non-loop code:
+ * Overhead =~ 18 instructions => 28 (30) cycles
+ * Byte set =~ 12 (24) cycles/word for 08M44 (08V11)
+ * Word set =~ 3 (5) cycles/word for 08M44 (08V11)
+ * If I-cache-miss nears 0, MINSET ==> 4 bytes; otherwise, times are:
+ * breakeven (MEM) = 28 / (12 - 3) =~ 3 words
+ * breakeven (VME) = 30 / (24 - 5) =~ 1.5 words
+ * Since the overhead is pessimistic (worst-case alignment), and many calls
+ * will be for well-aligned data, and since Word-set at least leaves
+ * the set in the cache, we shade these values (6-12) down to 8 bytes
+ */
+#define MINSET 8
+
+/* It turns out better to think of lwl/lwr and swl/swr as
+ smaller-vs-bigger address rather than left-vs-right.
+ Such a representation makes the code endian-independent. */
+
+#define LWS lwr
+#define LWB lwl
+#define SWS swr
+#define SWB swl
+
+LEAF_ENTRY(memset)
+ move v0,a0 # return first argument; BDSLOT
+ blt a2,MINSET,byteset
+ subu v1,zero,a0 # number of bytes til aligned; BDSLOT
+ beq a1,$0,1f # make memset(s, 0, n) faster
+ sll t0,a1,8
+ or a1,t0
+ sll t0,a1,16
+ or a1,t0
+1: and v1,NBPW-1
+ subu a2,v1 # adjust count; BDSLOT
+ beq v1,zero,blkset # already aligned
+ SWS a1,0(a0)
+ addu a0,v1
+
+/*
+ * set 8 byte, aligned block (no point in unrolling further,
+ * since maximum write rate in M/500 is two cycles/word write)
+ */
+blkset:
+ and t0,a2,NBPW+NBPW-1 # count after by-8-byte loop done
+ subu a3,a2,t0 # total in 8 byte chunks; BDSLOT
+ beq a2,t0,wordset # less than 8 bytes to set
+ addu a3,a0 # dst endpoint
+1: addu a0,NBPW+NBPW
+ sw a1,-NBPW-NBPW(a0)
+ sw a1,-NBPW(a0)
+ bne a0,a3,1b
+ move a2,t0 # set end-of loop count
+
+/*
+ * do a word (if required) this is not a loop since loop above
+ * guarantees that at most one word must be written here.
+ */
+wordset:
+ and t0,a2,NBPW # count after by-word non-loop done
+ subu a2,t0 # adjust count; BDSLOT
+ beq t0,zero,byteset # less than word to set
+ sw a1,0(a0)
+ addu a0,NBPW
+
+byteset:
+ addu a3,a2,a0 # dst endpoint; BDSLOT
+ ble a2,zero,setdone
+1: addu a0,1
+ sb a1,-1(a0)
+ bne a0,a3,1b
+setdone:
+ j ra
+.end memset
diff --git a/private/crt32/string/mips/memsett.c b/private/crt32/string/mips/memsett.c
new file mode 100644
index 000000000..c653803ab
--- /dev/null
+++ b/private/crt32/string/mips/memsett.c
@@ -0,0 +1,20 @@
+char buffer[100];
+#include <stdio.h>
+#include <string.h>
+
+void main()
+{
+ char *f = buffer;
+ char *g = buffer;
+
+ printf("%8.8x\n", f);
+ f=(char*)memset(f,0x0a,12);
+ printf("%8.8x\n", f);
+
+ if (f == g) {
+ int k = 12;
+ while (k--)
+ printf("%2.2x", *f++);
+ }
+}
+
diff --git a/private/crt32/string/mips/strcatm.s b/private/crt32/string/mips/strcatm.s
new file mode 100644
index 000000000..0c22c47de
--- /dev/null
+++ b/private/crt32/string/mips/strcatm.s
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strcat.s 1.1 */
+
+/* This function is an assembly-code replacement for the libc function
+ * strcat.
+
+ * strcat and strcpy are very similar, but we waste about 40 words of
+ * code when both are used, so that they can be independently replaced.
+
+ * There are one caveat to consider: this function is written in
+ * assembler code, and as such, cannot be merged using the U-code
+ * loader. */
+
+/* Craig Hansen - 3-September-86 */
+
+#include <kxmips.h>
+
+/* It turns out better to think of lwl/lwr and swl/swr as
+ smaller-vs-bigger address rather than left-vs-right.
+ Such a representation makes the code endian-independent. */
+
+#define LWS lwr
+#define LWB lwl
+#define SWS swr
+#define SWB swl
+
+.text
+
+LEAF_ENTRY(strcat)
+.set noreorder
+ // a0/ destination
+ // a1/ source
+ move v0, a0 # a copy of destination address is returned
+$findz: lb t0,0(a0)
+ nop
+ bne t0,0,$findz
+ add a0,1
+ // go back over null byte
+ add a0,-1
+ // start up first word
+ // adjust pointers so that a0 points to next word
+ // t7 = a1 adjusted by same amount minus one
+ // t0,t1,t2,t3 are filled with 4 consecutive bytes
+ // t4 is filled with the same 4 bytes in a single word
+ lb t0, 0(a1)
+ ori t5, a0, 3 # get an early start
+ beq t0, 0, $doch0
+ sub t6, t5, a0 # number of char in 1st word of dest - 1
+ lb t1, 1(a1)
+ add t7, a1, t6 # offset starting point for source string
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2(a1)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0(a1) # safe: always in same word as 0(a1)
+ lb t3, 3(a1)
+ LWB t4, 3(a1) # fill out word
+ beq t3, 0, $doch3
+ SWS t4, 0(a0) # store entire or part word
+ addi a0, t5, 1-4 # adjust destination ptr
+
+ // inner loop
+1: lb t0, 1(t7)
+ addi t7, 4
+ beq t0, 0, $doch0
+ addi a0, 4
+ lb t1, 1+1-4(t7)
+ nop
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2+1-4(t7)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0+1-4(t7)
+ lb t3, 3+1-4(t7)
+ LWB t4, 3+1-4(t7)
+ bne t3, 0, 1b
+ sw t4, 0(a0)
+ j ra
+ nop
+
+ // store four bytes using swl/swr
+$doch3: j ra
+ SWB t4, 3(a0)
+ // store up to three bytes, a byte at a time.
+$doch2: sb t2, 2(a0)
+$doch1: sb t1, 1(a0)
+$doch0: j ra
+ sb t0, 0(a0)
+
+.end strcat
diff --git a/private/crt32/string/mips/strchrm.s b/private/crt32/string/mips/strchrm.s
new file mode 100644
index 000000000..b92f79fd6
--- /dev/null
+++ b/private/crt32/string/mips/strchrm.s
@@ -0,0 +1,26 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+#ident "$Header: /disks/bits/5.1isms/irix/lib/libc/src/strings/RCS/index.s,v 1.3 1992/03/07 15:37:04 jleong Exp $"
+
+/*
+ * Copyright 1985 by MIPS Computer Systems, Inc.
+ */
+
+#include "kxmips.h"
+
+LEAF_ENTRY(strchr)
+1: lbu a2,0(a0)
+ addu a0,1
+ beq a2,a1,2f
+ bne a2,zero,1b
+ move v0,zero
+ j ra
+
+2: subu v0,a0,1
+ j ra
+.end strchr
diff --git a/private/crt32/string/mips/strchrt.c b/private/crt32/string/mips/strchrt.c
new file mode 100644
index 000000000..1da4e1d0d
--- /dev/null
+++ b/private/crt32/string/mips/strchrt.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+void main( int argc, char **argv )
+ {
+ int c;
+ unsigned char *pstr;
+ unsigned char string[100];
+
+ strcpy(string, "ABCDEFGHIJKLMNOPQRST");
+ for (c = 'a'; c <= UCHAR_MAX; c++)
+ {
+ string[9] = c;
+ pstr = strchr( string, c);
+ if (!pstr)
+ printf("Fail - Could not find %d in %s\n", c, string);
+ }
+ return;
+ }
diff --git a/private/crt32/string/mips/strcmpm.s b/private/crt32/string/mips/strcmpm.s
new file mode 100644
index 000000000..dfaaa9c39
--- /dev/null
+++ b/private/crt32/string/mips/strcmpm.s
@@ -0,0 +1,50 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strcmp.s 1.1 */
+
+/* This function is an assembly-code replacement for
+ the libc function "strcmp." */
+/* Libc currently has a mips-specific C version that uses 7 instructions/byte.
+ (It claims to use 6 cycles/byte, but is wrong!)
+ This function uses an unrolled loop, which uses 5 instructions per byte.
+
+ Under some circumstances more characters are read than are
+ required for determining the collating order, but it
+ never reads beyond the end of either string.
+
+ There are one caveat to consider: this function is written
+ in assembler code, and as such, cannot be merged
+ using the U-code loader. */
+
+/* Craig Hansen - 6-June-86 */
+
+#include <kxmips.h>
+
+ .text
+
+LEAF_ENTRY(strcmp)
+
+ .set noreorder
+ lbu t0,0(a0)
+1: lbu t1,0(a1)
+ beq t0,0,2f
+ addi a0,2
+ bne t0,t1,3f
+ lbu t2,-1(a0) # ok to load since -2(a0)!=0
+ lbu t1,1(a1)
+ beq t2,0,2f
+ addi a1,2
+ beq t2,t1,1b
+ lbu t0,0(a0) # ok to load since -1(a0) != 0
+ j ra
+ subu v0,t2,t1
+2: j ra
+ subu v0,zero,t1
+3: j ra
+ subu v0,t0,t1
+ .end strcmp
diff --git a/private/crt32/string/mips/strcpym.s b/private/crt32/string/mips/strcpym.s
new file mode 100644
index 000000000..4f5bc416a
--- /dev/null
+++ b/private/crt32/string/mips/strcpym.s
@@ -0,0 +1,148 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strcpy.s 1.2 */
+
+/* This function is an assembly-code replacement for the libc function
+ * strcpy. It uses the MIPS special instructions "lwl", "lwr", "swl",
+ * and "swr", which handle unaligned words.
+
+ * The standard C version of this function is a 5-instruction loop,
+ * working one byte at a time:
+
+ * Copy string s2 to s1. s1 must be large enough.
+ * return s1
+ * char *strcpy(s1, s2)
+ * register char *s1, *s2;
+ * {
+ * register char *os1;
+ * os1 = s1;
+ * while (*s1++ = *s2++);
+ * return(os1);
+ * }
+
+ * A better C version is 4 cycles/byte. Loop is unrolled once.
+ * char *
+ * strcpy(s1, s2)
+ * register char *s1, *s2;
+ * {
+ * register char *os1 = s1;
+ * while (1) {
+ * register unsigned c;
+ * c = s2[0];
+ * s2 += 2;
+ * s1[0] = c;
+ * if (c == 0) break;
+ * c = s2[1-2];
+ * s1 += 2;
+ * s1[1-2] = c;
+ * if (c == 0) break;
+ * }
+ * return(os1);
+ * }
+
+ * This function starts with an unrolled loop, which uses 5
+ * instructions per byte (including the store bytes at the end) for
+ * the first few bytes.
+
+ * After filling a word, the first word or portion of a word is saved
+ * using a "swl" instruction. If the start of destination string is at
+ * a word boundary, this leaves the result valid in the cache. Because
+ * this replaces up to 4 store byte instructions, we are still near 3
+ * instructions per byte, but there is only one write.
+
+ * The inner loop moves 4 bytes in 16 cycles, an average of 4 cycles
+ * per byte. This is 1 cycle faster than the standard C code, the
+ * same speed as the unrolled version, and it also leaves the result
+ * valid in the cache.
+
+ * Finally, when a zero byte is found, the end of the string is stored
+ * using store byte instructions. This adds one instruction per byte
+ * for as much as three bytes, but elminates the up to four cycles of
+ * overhead we counted before.
+
+ * The end result is that this function is never slower than the C
+ * function, is faster by up to 30% in instruction count, uses up to
+ * 75% fewer writes, and leaves most of the result valid in the cache.
+
+ * There are one caveat to consider: this function is written in
+ * assembler code, and as such, cannot be merged using the U-code
+ * loader. */
+
+/* Craig Hansen - 3-September-86 */
+
+#include <kxmips.h>
+
+/* It turns out better to think of lwl/lwr and swl/swr as
+ smaller-vs-bigger address rather than left-vs-right.
+ Such a representation makes the code endian-independent. */
+
+#define LWS lwr
+#define LWB lwl
+#define SWS swr
+#define SWB swl
+
+.text
+
+LEAF_ENTRY(strcpy)
+.set noreorder
+ // a0/ destination
+ // a1/ source
+ move v0, a0 # a copy of destination address is returned
+ // start up first word
+ // adjust pointers so that a0 points to next word
+ // t7 = a1 adjusted by same amount minus one
+ // t0,t1,t2,t3 are filled with 4 consecutive bytes
+ // t4 is filled with the same 4 bytes in a single word
+ lb t0, 0(a1)
+ ori t5, a0, 3 # get an early start
+ beq t0, 0, $doch0
+ sub t6, t5, a0 # number of char in 1st word of dest - 1
+ lb t1, 1(a1)
+ add t7, a1, t6 # offset starting point for source string
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2(a1)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0(a1) # safe: always in same word as 0(a1)
+ lb t3, 3(a1)
+ LWB t4, 3(a1) # fill out word
+ beq t3, 0, $doch3
+ SWS t4, 0(a0) # store entire or part word
+ addi a0, t5, 1-4 # adjust destination ptr
+
+ // inner loop
+1: lb t0, 1(t7)
+ addi t7, 4
+ beq t0, 0, $doch0
+ addi a0, 4
+ lb t1, 1+1-4(t7)
+ nop
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2+1-4(t7)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0+1-4(t7)
+ lb t3, 3+1-4(t7)
+ LWB t4, 3+1-4(t7)
+ bne t3, 0, 1b
+ sw t4, 0(a0)
+ j ra
+ nop
+
+ // store four bytes using swl/swr
+$doch3: j ra
+ SWB t4, 3(a0)
+ // store up to three bytes, a byte at a time.
+$doch2: sb t2, 2(a0)
+$doch1: sb t1, 1(a0)
+$doch0: j ra
+ sb t0, 0(a0)
+
+.end strcpy
diff --git a/private/crt32/string/mips/strcpyt.c b/private/crt32/string/mips/strcpyt.c
new file mode 100644
index 000000000..4d0d99279
--- /dev/null
+++ b/private/crt32/string/mips/strcpyt.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <limits.h>
+
+#define SRCLEN 21 /* to avoid complicating errors */
+
+void main( int argc, char **argv )
+{
+ int c;
+ unsigned char *psrc, *pdst;
+ unsigned char src[SRCLEN] = "ABCDEFGHIJKLMNOPQRST";
+ unsigned char dst[100];
+
+ for (c = 'a'; c <= UCHAR_MAX; c++) {
+ src[9] = c;
+ strcpy( dst, src);
+ for (psrc = src, pdst = dst; *psrc; psrc++, pdst++) {
+ if (*psrc != *pdst) {
+ printf("Fail - Could not find '%c' 0x%x in %s\n", c, c, src);
+ break;
+ }
+ }
+ }
+}
diff --git a/private/crt32/string/mips/strlenm.s b/private/crt32/string/mips/strlenm.s
new file mode 100644
index 000000000..24027e0fc
--- /dev/null
+++ b/private/crt32/string/mips/strlenm.s
@@ -0,0 +1,19 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strlen.s 1.1 */
+
+#include <kxmips.h>
+
+LEAF_ENTRY(strlen)
+ subu v0,a0,1
+1: lbu v1,1(v0)
+ add v0,1
+ bne v1,zero,1b
+ subu v0,v0,a0
+ j ra
+ .end strlen
diff --git a/private/crt32/string/mips/strrchrm.s b/private/crt32/string/mips/strrchrm.s
new file mode 100644
index 000000000..feb1f7945
--- /dev/null
+++ b/private/crt32/string/mips/strrchrm.s
@@ -0,0 +1,24 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+#ident "$Header: /disks/bits/5.1isms/irix/lib/libc/src/strings/RCS/rindex.s,v 1.3 1992/03/07 15:37:36 jleong Exp $"
+
+/*
+ * Copyright 1985 by MIPS Computer Systems, Inc.
+ */
+
+#include "kxmips.h"
+
+LEAF_ENTRY(strrchr)
+ move v0,zero
+1: lbu a3,0(a0)
+ addu a0,1
+ bne a3,a1,2f
+ subu v0,a0,1
+2: bne a3,zero,1b
+ j ra
+.end strrchr
diff --git a/private/crt32/string/mips/strrchrt.c b/private/crt32/string/mips/strrchrt.c
new file mode 100644
index 000000000..f608c2fc6
--- /dev/null
+++ b/private/crt32/string/mips/strrchrt.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+void main( int argc, char **argv )
+ {
+ int c;
+ unsigned char *pstr;
+ unsigned char string[100];
+
+ strcpy(string, "ABCDEFGHIJKLMNOPQRST");
+ for (c = 'a'; c <= UCHAR_MAX; c++)
+ {
+ string[9] = c;
+ pstr = strrchr( string, c);
+ if (!pstr)
+ printf("Fail - Could not find %d in %s\n", c, string);
+ }
+ return;
+ }
diff --git a/private/crt32/string/mips/wcscmpm.s b/private/crt32/string/mips/wcscmpm.s
new file mode 100644
index 000000000..d3997945d
--- /dev/null
+++ b/private/crt32/string/mips/wcscmpm.s
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * wcscmpm.s - contains wcscmp()
+ *
+ * ------------------------------------------------------------------
+ * | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights |
+ * | Reserved. This software contains proprietary and confidential |
+ * | information of MIPS and its suppliers. Use, disclosure or |
+ * | reproduction is prohibited without the prior express written |
+ * | consent of MIPS. |
+ * ------------------------------------------------------------------
+ * strcmp.s 1.1
+ *
+ * Purpose:
+ * wcscmp() compares two wide-character 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.
+ *
+ * Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
+ * say that Null wchar_t(0) is less than any other character.
+ *
+ * This function is a MIPS assembly-code replacement for the C version.
+ *
+ * Entry:
+ *
+ * const wchar_t * src - string for left-hand side of comparison
+ * const wchar_t * dst - string for right-hand side of comparison
+ *
+ *Exit:
+ * returns -1 if src < dst
+ * returns 0 if src == dst
+ * returns +1 if src > dst
+ *
+ *Exceptions:
+ *
+ *Revision History:
+ * Craig Hansen (MIPS) 06-June-86 Created.
+ * Roger Lanser (MS) 02-April-94 Cloned for Wide Characters (16-bits).
+ *
+ ******************************************************************************/
+
+#include <kxmips.h>
+
+ .text
+
+LEAF_ENTRY(wcscmp)
+
+ lhu t0,0(a0)
+1: lhu t1,0(a1)
+ addi a0,4
+ beq t0,0,2f
+ lhu t2,-2(a0) # ok to load since -4(a0)!=0
+ bne t0,t1,2f
+ lhu t1,2(a1)
+ addi a1,4
+ beq t2,0,2f
+ lhu t0,0(a0) # ok to load since -2(a0) != 0
+ beq t2,t1,1b
+ move v0,zero
+ j ra // source1 == source2, return 0
+2:
+ sltu v0,t1,t0 // compare source1 to source2
+ beq v0,zero,3f
+ j ra // source1 > source2, return 1
+3:
+ li v0,-1
+ j ra // source1 < source2, return 1
+ .end wcscmp
diff --git a/private/crt32/string/mips/wcscmpt.c b/private/crt32/string/mips/wcscmpt.c
new file mode 100644
index 000000000..629f61ca5
--- /dev/null
+++ b/private/crt32/string/mips/wcscmpt.c
@@ -0,0 +1,62 @@
+char buffer[100];
+#include <stdio.h>
+#include <memory.h>
+
+#define NTUL 7
+
+void main()
+{
+ int i, k;
+ int rc;
+
+ unsigned long source1[4] = {
+ 0x30003000,
+ 0x30003000,
+ 0x30003000,
+ 0x36003000
+ };
+
+ unsigned long source2[4] = {
+ 0x30003000,
+ 0x30003000,
+ 0x30003000,
+ 0x00000000
+ };
+
+ unsigned long tul[NTUL] = {
+ 0x35004600,
+ 0x37004600,
+ 0x36002f00,
+ 0x37002f00,
+ 0x30004600,
+ 0x30003000,
+ 0x36003000
+ };
+
+
+ for (k = 0; k < NTUL; k++) {
+ unsigned short *s1 = (unsigned short *)source1;
+ unsigned short *s2 = (unsigned short *)source2;
+
+ source2[3] = tul[k];
+
+ printf("source1 = ");
+ for (i = 0; i < 4*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source1)[i]);
+ printf("\n");
+
+ printf("source2 = ");
+ for (i = 0; i < 4*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source2)[i]);
+
+ rc = wcscmp(source1,source2);
+ if (rc < 0) {
+ printf(" source1 < source2\n");
+ } else if (rc > 0) {
+ printf(" source1 > source2\n");
+ } else {
+ printf(" source1 == source2\n");
+ }
+ printf("Return Code = %d\n",rc);
+ }
+}
diff --git a/private/crt32/string/mips/wcscpym.s b/private/crt32/string/mips/wcscpym.s
new file mode 100644
index 000000000..41b3544ec
--- /dev/null
+++ b/private/crt32/string/mips/wcscpym.s
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * wcscpym.s - contains wcscpy()
+ *
+ * Copyright (c) 1994, Microsoft Corporation. All rights reserved.
+ *
+ * Purpose:
+ * wcscpy() copies one wchar_t string into another.
+ *
+ * wcscpy() copies the source string to the destination string
+ * assuming no overlap and enough room in the destination. The
+ * destination string is returned. Strings are wide-character
+ * strings.
+ *
+ * This function is a MIPS assembly-code replacement for the C version.
+ * The only thing that this code tries to do is to produce a loop that
+ * uses a lw/sw pair versus running a lhu/sh loop twice. A small
+ * penality will be paid for very short wide-character strings due
+ * to the setup tests.
+ *
+ * Entry:
+ *
+ * wchar_t *wcscpy(dst, src)
+ * wchar_t * dst - wchar_t string over which "src" is to be copied
+ * const wchar_t * src - wchar_t string to be copied over "dst"
+ *
+ *Exit:
+ * The address of "dst".
+ *
+ *Exceptions:
+ *
+ *Revision History:
+ * 02-08-97 RDL Created initial version.
+ *
+ ******************************************************************************/
+
+#include <kxmips.h>
+
+.text
+
+LEAF_ENTRY(wcscat)
+
+ .set noreorder
+
+ // a0 destination
+ // a1 source
+
+ move v0, a0 // a copy of destination address is returned
+1: lhu t2,0(a0)
+ bnel zero,t2,1b
+ addiu a0,a0,2
+ b 2f
+ nop
+
+ALTERNATE_ENTRY(wcscpy)
+
+ // a0 destination
+ // a1 source
+
+ move v0, a0 // a copy of destination address is returned
+
+2: andi t1,a1,2 // assume at least halfword alignment
+3: andi t0,a0,2 // assume at least halfword alignment
+5: bne t0,t1,30f
+ nop
+
+10: // buffers start on same alignment
+ beq zero,t0,20f
+ nop
+ // halfword alignment
+ lhu t1,0(a1)
+ addiu a0,2
+ addiu a1,2
+ beq zero,t1,99f
+ sh t1,-2(a0)
+
+20: // word alignment
+ lw t0,0(a1)
+ addiu a0,4
+ addiu a1,4
+ andi t1,t0,0xffff
+ beq zero,t1,92f
+ srl t2,t0,16
+ bne zero,t2,20b
+ sw t0,-4(a0)
+ j ra
+ nop
+
+30: // buffers start on different alignment
+ beq zero,t1,40f
+ nop
+ // destination on word boundary, source on halfword boundary
+ lhu t0,0(a1)
+ addiu a1,2
+35: beq zero,t0,92f
+ addiu a0,4
+ lw t1,0(a1)
+ addiu a1,4
+ srl t2,t1,16
+ andi t1,0xffff
+ sll t3,t1,16
+ or t0,t0,t3
+ sw t0,-4(a0)
+ bne zero,t1,35b
+ or t0,zero,t2
+ j ra
+ nop
+
+40: // destination on halfword boundary, source on word boundary
+ lw t3,0(a1)
+ addiu a0,2
+ addiu a1,4
+ srl t2,t3,16
+ andi t0,t3,0xffff
+ beq zero,t0,99f
+ sh t0,-2(a0)
+45: lw t3,0(a1)
+ addiu a0,4
+ addiu a1,4
+ srl t1,t3,16
+ sll t3,t3,16
+ beq zero,t3,94f
+ or t0,t2,t3
+ sw t0,-4(a0)
+ bne zero,t1,45b
+ or t2,t1,zero
+ j ra
+ sh t1,0(a0)
+
+92: j ra
+ sh t0,-4(a0)
+
+94: j ra
+ sw t0,-4(a0)
+
+99: j ra
+ nop
+ .set reorder
+
+ .end wcscat
diff --git a/private/crt32/string/mips/wcslenm.s b/private/crt32/string/mips/wcslenm.s
new file mode 100644
index 000000000..ef45c114e
--- /dev/null
+++ b/private/crt32/string/mips/wcslenm.s
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * wcslenm.s - contains wcslen()
+ *
+ * ------------------------------------------------------------------
+ * | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights |
+ * | Reserved. This software contains proprietary and confidential |
+ * | information of MIPS and its suppliers. Use, disclosure or |
+ * | reproduction is prohibited without the prior express written |
+ * | consent of MIPS. |
+ * ------------------------------------------------------------------
+ * strlen.s 1.1
+ *
+ * Purpose:
+ * Finds the length in wchar_t's of the given string, not including
+ * the final null wchar_t (wide-characters).
+ *
+ * This function is a MIPS assembly-code replacement for the C version.
+ *
+ * Entry:
+ *
+ * wchar_t *wcslen(wcs)
+ * wchar_t * wcs - wchar_t string
+ *
+ *Exit:
+ * The "length" of wcs in wchar_t's.
+ *
+ *Exceptions:
+ *
+ *Revision History:
+ * Craig Hansen (MIPS) 06-June-86 Created.
+ * Roger Lanser (MS) 02-April-94 Cloned for Wide Characters (16-bits).
+ *
+ ******************************************************************************/
+
+#include <kxmips.h>
+
+LEAF_ENTRY(wcslen)
+ subu v0,a0,2
+1: lhu v1,2(v0)
+ addiu v0,v0,2
+ bne v1,zero,1b
+ subu v0,v0,a0
+ srl v0,v0,1
+ j ra
+ .end wcslen
diff --git a/private/crt32/string/ppc/memccpyp.s b/private/crt32/string/ppc/memccpyp.s
new file mode 100644
index 000000000..3690a0bd5
--- /dev/null
+++ b/private/crt32/string/ppc/memccpyp.s
@@ -0,0 +1,78 @@
+// TITLE("memccpy")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// memccpy.s
+//
+// Routine Description:
+//
+// Copies bytes from src to dest until count bytes have been
+// copied, or up to and including the character c, whichever
+// comes first.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the memory destination
+//
+// SRC1 (r.4) - A pointer to the memory source
+//
+// CHAR (r.5) - A character to stop copy
+//
+// LNGTH (r.6) - Max number of comparison in bytes
+//
+// Return Value:
+//
+// NULL if search character is not found or not copied
+// ptr to byte immediately after search character ...
+// ... if character found AND copied
+//
+// void * _CALLTYPE1 _memccpyc (
+// void * dest,
+// const void * src,
+// int c,
+// unsigned count
+// )
+//
+
+ LEAF_ENTRY(_memccpy)
+
+ addi r7,r6,1 # incr count, artificial
+ mtctr r7 # move count to ctr
+ bdz L..7A # if 0, finish up
+ lbz r8,0(r4) # read 1st char
+ subi r3,r3,1 # prep r3 for update form
+
+L..3:
+ stbu r8,1(r3) # copy char
+ cmp 0x0,0x0,r8,r5 # compare to char c
+ beq L..5 # found char c, say goodbye
+ bdz L..7A # count 0, say goodbye
+ lbzu r8,1(r4) # read next char
+ b L..3 # do another
+
+L..5:
+ addi r3,r3,1 # ret r3+1
+ b L..7 # all done, one exit pt.
+L..7A:
+ addi r3,r0,0 # return null
+L..7:
+
+ LEAF_EXIT(_memccpy)
diff --git a/private/crt32/string/ppc/memchrp.s b/private/crt32/string/ppc/memchrp.s
new file mode 100644
index 000000000..05a78105b
--- /dev/null
+++ b/private/crt32/string/ppc/memchrp.s
@@ -0,0 +1,74 @@
+// TITLE("memchr")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// memchr.s
+//
+// Routine Description:
+//
+// Searches buffer for character, stopping when found
+// or after checking count bytes.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// void * memchr (
+// const void * buffer,
+// int character,
+// size_t count
+// )
+//
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the block of memory
+//
+// SRC2 (r.4) - A character to base search
+//
+// LNGTH (r.5) - Max number of comparison in bytes
+//
+// Return Value:
+//
+// NULL if not found after count bytes
+// ptr to character in buffer, if character is found
+//
+//
+
+ LEAF_ENTRY(memchr)
+
+ cmpi 0x7,0x0,r5,0 # chk cnt
+ cmpi 0x1,0x0,r5,1 # finish early
+ beq 0x7,Null # all done
+
+ lbz r6,0(r3) # read char
+ cmp 0x6,0x0,r6,r4 # char ?= c
+ subi r5,r5,1 # decr cnt
+ beq 0x6,Fini # all done
+ beq 0x1,Null # rd 1 char only
+
+ mtctr r5 # init ctr
+
+L..1:
+ lbzu r6,1(r3)
+ cmp 0x0,0x0,r6,r4 # char ?= c
+ bdnzf eq,L..1 # dec ctr & ...
+ beq Fini # br ctr != 0 & !char
+Null:
+ addi r3,r0,0 # return null
+Fini:
+
+ LEAF_EXIT(memchr)
diff --git a/private/crt32/string/ppc/memcmpp.s b/private/crt32/string/ppc/memcmpp.s
new file mode 100644
index 000000000..ce1b003ff
--- /dev/null
+++ b/private/crt32/string/ppc/memcmpp.s
@@ -0,0 +1,71 @@
+// TITLE("memcmp")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// memcmp.s
+//
+// Routine Description:
+//
+// This function lexically determines two blocks of memory and
+// returns an integer indicating order.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// int memcmp (
+// void * src1,
+// void * src2,
+// int
+// )
+//
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the first block of memory
+//
+// SRC2 (r.4) - A pointer to the second block of memory
+//
+// LNGTH (r.5) - Max number of comparison in bytes
+//
+// Return Value:
+//
+// < 0 if SRC1 < SRC2
+// = 0 if SRC1 = SRC2 for LNGTH bytes, or if LNGTH == 0
+// > 0 if SRC1 > SRC2
+//
+//
+
+ LEAF_ENTRY(memcmp)
+
+ cmpwi r.5,0 // we'll do the first iteration
+ mtctr r.5 // by hand, iff length > 0
+ beq zip // branch if nothing to check
+ lbz r.6,0(r.4) // read first byte
+ lbz r.5,0(r.3) // of both strings
+ b comp
+
+next: lbzu r.6,1(r.4) // get next byte (src2)
+ lbzu r.5,1(r.3) // get next byte (src1)
+comp: cmpw r.5,r.6 // bytes equal?
+ bdnzt eq,next // branch equal AND length not exhausted
+
+ subf r.3,r.6,r.5 // r7 ?= r8
+ blr
+
+zip: li r.3,0 // return null when length == 0
+
+ LEAF_EXIT(memcmp)
diff --git a/private/crt32/string/ppc/strcatp.s b/private/crt32/string/ppc/strcatp.s
new file mode 100644
index 000000000..bbbfd7a96
--- /dev/null
+++ b/private/crt32/string/ppc/strcatp.s
@@ -0,0 +1,137 @@
+// TITLE("strcpy strcat")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strcatp.s
+//
+// Abstract:
+//
+// The module implements the routines strcpy and strcat.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Peter Johnston (plj@vnet.ibm.com) 08-Aug-1994
+//
+// Minor optimization.
+//
+//--
+
+#include <kxppc.h>
+
+//++
+//
+// PUCHAR
+// strcpy (
+// PUCHAR dest;
+// PUCHAR src;
+// )
+//
+// Routine Description:
+//
+// Copies an ANSI (null terminated) string from src to dest.
+//
+// Arguments:
+//
+// dest (r.3) - A pointer to the string destination
+//
+// src (r.4) - A pointer to the string source
+//
+//
+// Return Value:
+//
+// dest Pointer to the destination string.
+//
+//--
+
+ LEAF_ENTRY(strcpy)
+
+ lbz r.5,0(r.4) // get first byte
+ addi r.9,r.3,-1 // pref for store with update
+ cmpwi r.5,0 // check if first byte was last
+ beq cpdone // jif so
+
+cploop: lbzu r.6,1(r.4) // get next byte
+ stbu r.5,1(r.9) // store previous byte
+ or. r.5,r.6,r.6 // mv to store reg and check if done
+ bne cploop
+
+cpdone: stbu r.5,1(r.9) // store last byte
+
+ LEAF_EXIT(strcpy)
+
+//++
+//
+// PUCHAR
+// strcat (
+// PUCHAR str1;
+// PUCHAR str2;
+//
+// Routine Description:
+//
+// This function concatenates a source string (str2) to the end of
+// the desintation string (str1).
+//
+// Arguments:
+//
+// str1 (r.3) - A pointer to the string destination
+//
+// str2 (r.4) - A pointer to the string source
+//
+//
+// Return Value:
+//
+// str1 Pointer to the destination string.
+//
+//--
+
+
+ LEAF_ENTRY(strcat)
+
+ lbz r.5,0(r.4) // Load 1st char str2
+ lbz r.6,0(r.3) // Load 1st char str1
+ cmpwi cr.1,r.5,0 // check if str2 null
+ cmpwi r.6,0 // check if str1 null
+ mr r.9,r.3 // copy char ptr
+
+//
+// If str2 is empty, we have nothing to do, return early.
+//
+
+ beqlr cr.1 // return if str2 empty
+
+//
+// If str 1 empty, we're done scanning already.
+//
+
+ beq ctcpy // if str1 null start cat
+
+//
+// Scan str1 until we find its null terminator.
+//
+
+ctscan: lbzu r.6,1(r.9) // get next byte str1
+ cmpwi r.6,0 // test for null
+ bne ctscan // if not null, continue scan
+
+//
+// We found the end of str1, we know we have data in str2, all that
+// remains is to strcpy str2 to the end of str1, set up for and use
+// the body of strcpy (above) to do this.
+//
+
+ctcpy: addi r.9,r.9,-1 // prep for store with update
+ b cploop // finish in strcpy
+
+ LEAF_EXIT(strcat)
+
diff --git a/private/crt32/string/ppc/strchrp.s b/private/crt32/string/ppc/strchrp.s
new file mode 100644
index 000000000..0f03dc54a
--- /dev/null
+++ b/private/crt32/string/ppc/strchrp.s
@@ -0,0 +1,70 @@
+// TITLE("strchr")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strchr.s
+//
+// Routine Description:
+//
+// Searches a string for a given character, which may be the
+// null character '\0'.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// *char *strchr(
+// char *str,
+// char c)
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the first block of memory
+//
+// SRC2 (r.4) - A search character
+//
+//
+// Return Value:
+//
+// returns pointer to the first occurence of c in string
+// returns NULL if c does not occur in string
+//
+//
+
+ LEAF_ENTRY(strchr)
+
+ lbz r6,0(r3) # read char
+ cmpi 0x0,0x0,r4,0 # c ?= null
+ beq L..3A # use special loop
+
+L..3:
+ cmpi 0x1,0x0,r6,0 # char ?= null
+ cmp 0x0,0x0,r6,r4 # char ?= c
+ beq 0x1,L..5A # b, if char is null
+ beq Fini
+ lbzu r6,1(r3) # read char
+ b L..3
+L..3A:
+ cmpi 0x0,0x0,r6,0 # char ?= null
+ beq Fini
+ lbzu r6,1(r3) # read char
+ b L..3A
+L..5A:
+ addi r3,r0,0 # return null
+
+Fini:
+
+ LEAF_EXIT(strchr)
diff --git a/private/crt32/string/ppc/strcmpp.s b/private/crt32/string/ppc/strcmpp.s
new file mode 100644
index 000000000..0d57279e0
--- /dev/null
+++ b/private/crt32/string/ppc/strcmpp.s
@@ -0,0 +1,74 @@
+// TITLE("strcmp")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strcmp.s
+//
+// Routine Description:
+//
+// This function lexically determines two blocks of memory and
+// returns an integer indicating order.
+// 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.
+//
+// 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).
+//
+// Author:
+//
+// Jeff Simon (jhs) 03-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// int strcmp (
+// const char * src,
+// const char * dst
+// )
+//
+// Arguments:
+//
+// STR1 (r.3) - A pointer to the first string
+//
+// STR2 (r.4) - A pointer to the second string
+//
+// Return Value:
+//
+// < 0 if STR1 < STR2
+// = 0 if STR1 = STR2 for LNGTH bytes, or if LNGTH == 0
+// > 0 if STR1 > STR2
+//
+//
+ LEAF_ENTRY(strcmp)
+
+ lbz r5,0(r3) # init r5
+ lbz r6,0(r4) # init r6
+ or r9,r3,r3 # cp ptr
+L..3:
+ cmpi 0x7,0x0,r6,0x0 # end of string ?
+ subf. r3,r6,r5 # lexical compare
+ bc 0xc,0x1e,L..4 # b, if null detected
+ bne L..4 # b, if not equal
+ lbzu r5,1(r9) # next char
+ lbzu r6,1(r4) # next char
+ b L..3 # loop
+
+L..4:
+ beqlr
+ addi r3,r0,-1 #?I hate doing this, but intel
+ bltlr #?ret -1, +1, so ...
+ addi r3,r0,1 #?
+
+ LEAF_EXIT(strcmp)
diff --git a/private/crt32/string/ppc/stricmpp.s b/private/crt32/string/ppc/stricmpp.s
new file mode 100644
index 000000000..a61d23573
--- /dev/null
+++ b/private/crt32/string/ppc/stricmpp.s
@@ -0,0 +1,89 @@
+// TITLE("_stricmp _strcmpi")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// _stricmp.s
+// _strcmpi.s
+//
+// Routine Description:
+//
+// The functions are synomns. The functions return an integer
+// indicating case-insensitive string comparision, as the function
+// maps characters from upper to lower case. Note that the
+// mapping from upper to lower affects outcome when comparison
+// strings contain characters 91-96 as compared
+// to mapping lower to upper.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+// int _stricmp _strcmpi
+// (
+// char *str1,
+// char *str2
+// )
+//
+// Arguments:
+//
+// STR1 (r.3) - A pointer to the first string
+//
+// STR2 (r.4) - A pointer to the second string
+//
+//
+// Return Value:
+//
+// < 0 if STR1 < STR2
+// = 0 if STR1 = STR2
+// > 0 if STR1 > STR2
+//
+//
+
+ LEAF_ENTRY(_stricmp)
+ ALTERNATE_ENTRY(_strcmpi)
+
+ addi r9,r3,-1 # copy ptr
+ addi r4,r4,-1
+Loop1:
+
+ lbzu r6,1(r4) # read char
+ lbzu r5,1(r9) # read char
+ cmpi 0x7,0x0,r6,0 # Is char null?
+ subf. r3,r6,r5 # Calc result
+
+ bc 0xc,0x1e,Loop20 # b if !=
+ bc 0xc,0x2,Loop1 # b if r5 ?= r6
+
+Loop4:
+ cmpi 0x5,0x0,r6,0x41 # Is r5 > 60
+ cmpi 0x6,0x0,r6,0x5A # Is r6 < 7B
+ blt 0x5,Loop2 # ? >
+ bgt 0x6,Loop2 # ? <
+
+ ori r6,r6,0x20 # cvrt to lower case
+Loop2:
+ cmpi 0x0,0x0,r5,0x41 # Is r5 > 60
+ cmpi 0x1,0x0,r5,0x5A # Is r6 < 7B
+ blt 0x0,Loop3 # ?
+ bgt 0x1,Loop3 # ?
+
+ ori r5,r5,0x20 # cvrt to lower case
+Loop3:
+ subf. r3,r6,r5 # Is r6 = r5
+ beq Loop1 # !=, done
+
+Loop20:
+ LEAF_EXIT(_stricmp)
diff --git a/private/crt32/string/ppc/strlenp.s b/private/crt32/string/ppc/strlenp.s
new file mode 100644
index 000000000..94553997a
--- /dev/null
+++ b/private/crt32/string/ppc/strlenp.s
@@ -0,0 +1,164 @@
+// TITLE("strlen")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strlen.s
+//
+// Routine Description:
+//
+// This function returns the length of a string excluding the
+// terminating null.
+//
+// The algorithm used here merits some explanation. It turns
+// out to be quite fast on a 32 bit processor but it is known
+// to be extremely fast on a 64 bit processor. I have seen this
+// algorithm used elsewhere but the best description I have seen
+// for it is in a document entitled "Hacker's Delight" by
+// Henry S. Warren, Jr. IBM Thomas J. Watson Research Center.
+//
+// I have found (by experimentation) that it is faster to just
+// get on with it and do the first few bytes as single bytes
+// rather than trying to work out the alignment up front.
+//
+// Once word aligned, we can process the string a word at a time.
+// The hard part is to figure out if the word contains a zero byte.
+//
+// Given x where x is the word being examined, consider
+//
+// y = x & 0x7f7f7f7f we have reduced each byte in x to a
+// value of 7f or less.
+//
+// y += 0x7f7f7f7f each byte whose lower 7 bits were non
+// zero now has its left most bit set.
+//
+// y |= x each byte whose value was 0x80 now
+// also has its upper bit set.
+//
+// y |= 0x7f7f7f7f each non zero byte now has the value
+// 0xff. (Each zero byte is now 0x7f).
+//
+// Note the last two "or" operations can be rewritten as
+//
+// x |= 0x7f7f7f7f
+//
+// y |= x
+//
+// making the operations to independent which allows them to run in
+// parrallel on a superscalar machine with multiple boolean functional
+// units.
+//
+// This value can now be checked for equality with -1, or its
+// complement with 0. If equal, then this word contains no zero
+// bytes.
+//
+// The complement is more interesting. On a big endian machine, a
+// count leading zeroes on the complement gives you 8 times the number
+// of non-zero bytes before the zero byte. Little endian, no such
+// luxury. Given that a non-zero complement means one or more bytes
+// are zero, we only need check the first three (starting at the
+// right). On PowerPC we can easily do this by moving the complement
+// to the condition register (after suitably rotating so we do not
+// overwrite any non-volatile condition register fields) then testing
+// one bit for each byte.
+//
+// I have found this method to be about the same speed (no slower) for
+// very short strings and almost (not quite) twice as fast as checking
+// each byte individually for long strings.
+//
+//
+// Author:
+//
+// Peter L Johnston (plj@vnet.ibm.com) 15-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Arguments:
+//
+// addr (r.3) - A pointer to the string
+//
+// Return Value:
+//
+// length (r.3) - length of the string excluding the terminating null
+//
+
+#include <kxppc.h>
+
+ LEAF_ENTRY(strlen)
+
+//
+// Do the first 1, 2, 3 or 4 bytes individually while we try to figure
+// out the real alignment.
+//
+
+ lbz r.4, 0(r.3) // get first byte
+ addi r.7, r.3, 1 // bump and move address
+ cmpwi cr.1, r.4, 0 // first byte zero?
+ andi. r.8, r.7, 0x3 // check alignment of next byte
+ li r.3, 0 // initialize length
+ beqlr cr.1 // return if byte is zero
+ beq wds // switch to word oriented count if
+ // now word aligned.
+nxbyte: lbz r.4, 0(r.7) // get next byte
+ addi r.7, r.7, 1 // bump address
+ cmpwi cr.1, r.4, 0 // byte equal zero?
+ andi. r.8, r.7, 0x3 // check new alignment
+ addi r.3, r.3, 1 // bump length
+ beqlr cr.1 // return if byte is zero
+ bne nxbyte
+
+//
+// We can look at the rest on a word by word basis
+//
+
+wds: lwz r.4, 0(r.7) // get first word
+
+ lis r.6, 0x7f7f // setup magic constant
+ ori r.6, r.6, 0x7f7f
+
+ addi r.3, r.3, 1 // count was one short by here
+
+//
+// See introductory comments for an explanation of the following.
+//
+
+chkwd: and r.8, r.4, r.6 // y = x & 0x7f7f7f7f
+ or r.4, r.4, r.6 // x = x | 0x7f7f7f7f
+ add r.8, r.8, r.6 // y += 0x7f7f7f7f
+ or r.8, r.8, r.4 // y |= x
+ not. r.8, r.8 // if complement = 0 then no zero bytes
+ bne bytes // non-zero means one of the bytes IS
+
+ lwzu r.4, 4(r.7) // get next word
+ addi r.3, r.3, 4 // bump count
+ b chkwd
+
+//
+// When we get here, we encountered a word that contains a zero byte. As
+// a result of the above algorithm, the zero byte is now represented within
+// the word as 0x80. All non-zero bytes are now 0x00.
+//
+// We have up to 4 bits in r.8 (if we were big endian we could use count
+// leading zeros for this), we'll slam them in the condition register and
+// look at them individually. We know at least one of them is set so we
+// only bother checking the first three.
+//
+
+bytes: rlwinm r.8, r.8, 20, 0xff000fff// posn so dont use non-volatile
+ mtcrf 0x45, r.8 // fields in CR
+ btlr 4 // jif right most is terminator
+ addi r.3, r.3, 1 // bump count
+ btlr 28 // jif 2nd from right
+ addi r.3, r.3, 1 // bump
+ btlr 20 // jif 3rd from right
+ addi r.3, r.3, 1 // bump
+
+ blr
+
+ LEAF_EXIT(strlen)
diff --git a/private/crt32/string/ppc/strrchrp.s b/private/crt32/string/ppc/strrchrp.s
new file mode 100644
index 000000000..e3b5991c5
--- /dev/null
+++ b/private/crt32/string/ppc/strrchrp.s
@@ -0,0 +1,87 @@
+// TITLE("strrchr")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strrchr.s
+//
+// Routine Description:
+//
+// This function searches a null-terminated string for the
+// last occurence of a character.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+//
+// char * strrchr
+// (
+// const char * string,
+// int ch
+// )
+//
+//
+// Arguments:
+//
+// STR1 (r.3) - A pointer to the first block of memory
+//
+// CHAR (r.4) - A search character
+//
+// Return Value:
+//
+// NULL if character is never found
+// ptr to the character in string where last match is found
+//
+//
+
+ LEAF_ENTRY(strrchr)
+
+
+ lbz r5,0(r3) # read 1st char
+ or r9,r3,r3 # cp char ptr
+ cmpi 0x6,0x0,r4,0x0 # ch ?= Null
+ cmp 0x0,0x0,r5,r4 # r5 ?= ch
+ bc 0xc,0x1a,L..2
+ addi r3,r0,0 # init to Null
+ beq L..1A # b if 1st ch matched
+
+L..1: # CASE: ch != Null
+
+ cmpi 0x6,0x0,r5,0x0 # end of str ?
+ bc 0xc,0x1a,Fini # all done
+ lbzu r5,1(r9) # read nxt char
+ cmp 0x0,0x0,r4,r5 # r4 ?= r5
+ bne L..1
+
+L..1A: # CASE: match found
+
+ or r3,r9,r9 # Update char ptr
+ lbzu r5,1(r9) # load next char
+ cmp 0x0,0x0,r4,r5 # r4 ?= r5
+ beq L..1A
+ b L..1
+
+
+L..2: # CASE: char = Null
+
+ bc 0xc,0x2,Fini # ret if null found
+ lbzu r5,1(r3)
+ cmpi 0x0,0x0,r5,0x0 # Is r5 ?= Null
+ b L..2
+
+
+Fini:
+
+ LEAF_EXIT(strrchr)
diff --git a/private/crt32/string/sources b/private/crt32/string/sources
new file mode 100644
index 000000000..3b7d2ea7c
--- /dev/null
+++ b/private/crt32/string/sources
@@ -0,0 +1,175 @@
+!IF 0
+
+Copyright (c) 1989 - 1992, Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+ karlsi 07-Apr-1992, add wide character routines, intl support
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=string
+
+TARGETNAME=string
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+NTTARGETFILE0=strcspn.c strpbrk.c
+!IF $386
+NTTARGETFILE0=$(NTTARGETFILE) i386\memmove.asm i386\strcspn.asm i386\strpbrk.asm
+!ENDIF
+
+SOURCES=strcoll.c \
+ stricoll.c \
+ strlwr.c \
+ strtok.c \
+ strupr.c \
+ strxfrm.c \
+ wcscat.c \
+ wcschr.c \
+ wcscmp.c \
+ wcscoll.c \
+ wcscspn.c \
+ wcsdup.c \
+ wcsicmp.c \
+ wcsicoll.c \
+ wcslen.c \
+ wcslwr.c \
+ wcsncat.c \
+ wcsncmp.c \
+ wcsncpy.c \
+ wcsnicmp.c \
+ wcsnset.c \
+ wcspbrk.c \
+ wcsrchr.c \
+ wcsrev.c \
+ wcsset.c \
+ wcsspn.c \
+ wcsstr.c \
+ wcstok.c \
+ wcsupr.c \
+ wcsxfrm.c
+
+i386_SOURCES=i386\memccpy.asm \
+ i386\memchr.asm \
+ i386\memcmp.asm \
+ i386\memcpy.asm \
+ i386\memicmp.asm \
+ i386\memmove.asm \
+ i386\memset.asm \
+ i386\strcat.asm \
+ i386\strchr.asm \
+ i386\strcmp.asm \
+ i386\strcspn.asm \
+ i386\strdup.asm \
+ i386\stricmp.asm \
+ i386\strlen.asm \
+ i386\strncat.asm \
+ i386\strncmp.asm \
+ i386\strncpy.asm \
+ i386\strnicmp.asm \
+ i386\strnset.asm \
+ i386\strpbrk.asm \
+ i386\strrchr.asm \
+ i386\strrev.asm \
+ i386\strset.asm \
+ i386\strspn.asm \
+ i386\strstr.asm
+
+MIPS_SOURCES=memccpy.c \
+ memchr.c \
+ memicmp.c \
+ strcspn.c \
+ strdup.c \
+ stricmp.c \
+ strncat.c \
+ strncmp.c \
+ strncpy.c \
+ strnicmp.c \
+ strnset.c \
+ strpbrk.c \
+ strrev.c \
+ strset.c \
+ strspn.c \
+ strstr.c \
+ mips\memorym.s \
+ mips\strcatm.s \
+ mips\strchrm.s \
+ mips\strcmpm.s \
+ mips\strcpym.s \
+ mips\strlenm.s \
+ mips\strrchrm.s
+
+ALPHA_SOURCES=memccpy.c \
+ memchr.c \
+ memcmp.c \
+ memcpy.c \
+ memicmp.c \
+ memmove.c \
+ memset.c \
+ alpha\strcat.c \
+ strchr.c \
+ alpha\strcmps.s \
+ strcspn.c \
+ strdup.c \
+ stricmp.c \
+ alpha\strlens.s \
+ strncat.c \
+ strncmp.c \
+ strncpy.c \
+ alpha\strcpys.s \
+ strnicmp.c \
+ strnset.c \
+ strpbrk.c \
+ strrchr.c \
+ strrev.c \
+ strset.c \
+ strspn.c \
+ strstr.c
+
+PPC_SOURCES= ppc\memccpyp.s \
+ ppc\memchrp.s \
+ ppc\memcmpp.s \
+ memcpy.c \
+ memicmp.c \
+ memmove.c \
+ memset.c \
+ ppc\strcatp.s \
+ ppc\strchrp.s \
+ ppc\strcmpp.s \
+ strcspn.c \
+ strdup.c \
+ ppc\stricmpp.s \
+ ppc\strlenp.s \
+ strncat.c \
+ strncmp.c \
+ strncpy.c \
+ strnicmp.c \
+ strnset.c \
+ strpbrk.c \
+ ppc\strrchrp.s \
+ strrev.c \
+ strset.c \
+ strspn.c \
+ strstr.c
+
diff --git a/private/crt32/string/strcat.c b/private/crt32/string/strcat.c
new file mode 100644
index 000000000..ada29471d
--- /dev/null
+++ b/private/crt32/string/strcat.c
@@ -0,0 +1,90 @@
+/***
+*strcat.c - contains strcat() and strcpy()
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Strcpy() copies one string onto another.
+*
+* Strcat() concatenates (appends) a copy of the source string to the
+* end of the destination string, returning the destination string.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up strcat() a bit (got rid of call to strcpy()).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strcat,strcpy)
+#endif /* ndef _CRUISER_ */
+
+/***
+*char *strcat(dst, src) - concatenate (append) one string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*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"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strcat (
+ char * dst,
+ const char * src
+ )
+{
+ char * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
+
+/***
+*char *strcpy(dst, src) - copy one string over another
+*
+*Purpose:
+* Copies the string src into the spot specified by
+* dest; assumes enough room.
+*
+*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"
+*
+*Exceptions:
+*******************************************************************************/
+
+char * _CALLTYPE1 strcpy(char * dst, const char * src)
+{
+ char * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return( dst );
+}
diff --git a/private/crt32/string/strchr.c b/private/crt32/string/strchr.c
new file mode 100644
index 000000000..bbabf62b2
--- /dev/null
+++ b/private/crt32/string/strchr.c
@@ -0,0 +1,52 @@
+/***
+*strchr.c - 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:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-01-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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'.
+*
+*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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strchr (
+ const char * string,
+ int ch
+ )
+{
+ while (*string && *string != (char)ch)
+ string++;
+
+ if (*string == (char)ch)
+ return((char *)string);
+ return(NULL);
+}
diff --git a/private/crt32/string/strcmp.c b/private/crt32/string/strcmp.c
new file mode 100644
index 000000000..6d41fe4cd
--- /dev/null
+++ b/private/crt32/string/strcmp.c
@@ -0,0 +1,68 @@
+/***
+*strcmp.c - routine to compare two strings (for equal, less, or greater)
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compares two string, determining their lexical order.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strcmp)
+#endif /* ndef _CRUISER_ */
+
+/***
+*strcmp - compare two strings, returning less than, equal to, or greater than
+*
+*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.
+*
+* 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).
+*
+*Entry:
+* const char * src - string for left-hand side of comparison
+* const char * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 strcmp (
+ const char * src,
+ const char * dst
+ )
+{
+ int ret = 0 ;
+
+ while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+}
diff --git a/private/crt32/string/strcoll.c b/private/crt32/string/strcoll.c
new file mode 100644
index 000000000..9f9a7590e
--- /dev/null
+++ b/private/crt32/string/strcoll.c
@@ -0,0 +1,103 @@
+/***
+*strcoll.c - Collate locale strings
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 06-20-89 JCR Removed _LOAD_DGROUP code
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 10-01-91 ETC Non-C locale support under _INTL switch.
+* 12-09-91 ETC Updated api; added multithread.
+* 08-19-92 KRS Activate NLS support.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-16-92 KRS Optimize for CompareStringW by using -1 for string len.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int strcoll() - Collate locale strings
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information.
+* [ANSI].
+*
+* Non-C locale support available under _INTL switch.
+* In the C locale, strcoll() simply resolves to strcmp().
+*Entry:
+* const char *s1 = pointer to the first string
+* const char *s2 = pointer to the second string
+*
+*Exit:
+* Less than 0 = first string less than second string
+* 0 = strings are equal
+* Greater than 0 = first string greater than second string
+*
+*Exceptions:
+* NLSCMPERROR = error
+*
+*******************************************************************************/
+
+int _CRTAPI1 strcoll (
+ const char *_string1,
+ const char *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ size_t size1, size2;
+ wchar_t *wstring1, *wstring2;
+ int ret;
+
+ _mlock (_LC_CTYPE_LOCK);
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_CTYPE_LOCK);
+ _munlock (_LC_COLLATE_LOCK);
+ return strcmp(_string1, _string2);
+ }
+
+ size1 = (strlen(_string1) + 1) * sizeof(wchar_t);
+ size2 = (strlen(_string2) + 1) * sizeof(wchar_t);
+ wstring1 = malloc (size1);
+ wstring2 = malloc (size2);
+ if (!wstring1 || !wstring2)
+ goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string1, -1,
+ wstring1, size1)) goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string2, -1,
+ wstring2, size2)) goto error_cleanup;
+ if (!(ret=CompareStringW(_lc_handle[LC_COLLATE], 0, wstring1, -1,
+ wstring2, -1))) goto error_cleanup;
+
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return (ret - 2);
+
+error_cleanup:
+
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return NLSCMPERROR;
+
+#else
+ return strcmp(_string1,_string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strcspn.c b/private/crt32/string/strcspn.c
new file mode 100644
index 000000000..7bd92963f
--- /dev/null
+++ b/private/crt32/string/strcspn.c
@@ -0,0 +1,2 @@
+#define SSTRCSPN
+#include "strspn.c"
diff --git a/private/crt32/string/strdup.c b/private/crt32/string/strdup.c
new file mode 100644
index 000000000..2e15d16cd
--- /dev/null
+++ b/private/crt32/string/strdup.c
@@ -0,0 +1,60 @@
+/***
+*strdup.c - 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:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strdup (
+ const char * string
+ )
+{
+ char *memory;
+
+ if (!string)
+ return(NULL);
+
+ if (memory = malloc(strlen(string) + 1))
+ return(strcpy(memory,string));
+
+ return(NULL);
+}
diff --git a/private/crt32/string/stricmp.c b/private/crt32/string/stricmp.c
new file mode 100644
index 000000000..8565e25e3
--- /dev/null
+++ b/private/crt32/string/stricmp.c
@@ -0,0 +1,80 @@
+/***
+*stricmp.c - contains case-insensitive string comp routine _stricmp/_strcmpi
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains _stricmp(), also known as _strcmpi()
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 07-25-90 SBM Added #include <ctype.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+* 11-08-91 GJF Fixed compiler warning.
+* 09-27-93 CFW Avoid cast bug.
+* 06-28-94 SRW Rewrite to use same ANSI specific tolower logic as x86
+* assembler version is i386\stricmp.asm
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <ctype.h>
+
+/***
+*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".
+*
+*Entry:
+* char *dst, *src - strings to compare
+*
+*Return:
+* <0 if dst < src
+* 0 if dst = src
+* >0 if dst > src
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _stricmp (
+ const char * dst,
+ const char * src
+ )
+{
+ return( _strcmpi(dst,src) );
+}
+
+
+int _CALLTYPE1 _strcmpi(const char * dst, const char * src)
+{
+ unsigned char f,l;
+
+ do {
+ f = *dst++;
+ l = *src++;
+ if (f != l) {
+ if (f>='A' && f<='Z') {
+ f = f - 'A' + 'a';
+ }
+ if (l>='A' && l<='Z') {
+ l = l - 'A' + 'a';
+ }
+ if (f!=l) {
+ return f-l;
+ }
+ }
+ }
+ while (f);
+
+ return(0);
+}
diff --git a/private/crt32/string/stricoll.c b/private/crt32/string/stricoll.c
new file mode 100644
index 000000000..ec4465d77
--- /dev/null
+++ b/private/crt32/string/stricoll.c
@@ -0,0 +1,95 @@
+/***
+*stricoll.c - Collate locale strings without regard to case
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information.
+*
+*Revision History:
+* 10-16-91 ETC Created from strcoll.c
+* 12-08-91 ETC Remove availability under !_INTL; updated api; add mt.
+* 04-06-92 KRS Make work without _INTL switches too.
+* 08-19-92 KRS Activate NLS support.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-16-92 KRS Optimize for CompareStringW by using -1 for string len.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int _stricoll() - Collate locale strings without regard to case
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information
+* without regard to case.
+*
+*Entry:
+* const char *s1 = pointer to the first string
+* const char *s2 = pointer to the second string
+*
+*Exit:
+* Less than 0 = first string less than second string
+* 0 = strings are equal
+* Greater than 0 = first string greater than second string
+*
+*Exceptions:
+* NLSCMPERROR = error
+*
+*******************************************************************************/
+
+int _CRTAPI1 _stricoll (
+ const char *_string1,
+ const char *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ size_t size1, size2;
+ wchar_t *wstring1, *wstring2;
+ int ret;
+
+ _mlock (_LC_CTYPE_LOCK);
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ return _stricmp(_string1, _string2);
+ }
+
+ size1 = strlen(_string1) + 1;
+ size2 = strlen(_string2) + 1;
+ wstring1 = malloc (size1 * sizeof(wchar_t));
+ wstring2 = malloc (size2 * sizeof(wchar_t));
+ if (!wstring1 || !wstring2)
+ goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string1, -1,
+ wstring1, size1)) goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string2, -1,
+ wstring2, size2)) goto error_cleanup;
+ if (!(ret=CompareStringW(_lc_handle[LC_COLLATE], NORM_IGNORECASE,
+ wstring1, -1, wstring2, -1))) goto error_cleanup;
+
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return (ret - 2);
+
+error_cleanup:
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return NLSCMPERROR;
+#else
+ return _stricmp(_string1, _string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strlen.c b/private/crt32/string/strlen.c
new file mode 100644
index 000000000..362173dc7
--- /dev/null
+++ b/private/crt32/string/strlen.c
@@ -0,0 +1,54 @@
+/***
+*strlen.c - 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:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up just a little bit.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strlen)
+#endif /* ndef _CRUISER_ */
+
+/***
+*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.
+*
+*Entry:
+* const char * str - string whose length is to be computed
+*
+*Exit:
+* length of the string "str", exclusive of the final null byte
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 strlen (
+ const char * str
+ )
+{
+ const char *eos = str;
+
+ while( *eos++ ) ;
+
+ return( (int)(eos - str - 1) );
+}
diff --git a/private/crt32/string/strlwr.c b/private/crt32/string/strlwr.c
new file mode 100644
index 000000000..24bc08368
--- /dev/null
+++ b/private/crt32/string/strlwr.c
@@ -0,0 +1,137 @@
+/***
+*strlwr.c - routine to map upper-case characters in a string to lower-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the upper case characters in a string to lower case,
+* in place.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 09-18-91 ETC Locale support under _INTL switch.
+* 12-08-91 ETC Updated nlsapi; added multithread.
+* 08-19-92 KRS Activated NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <limits.h> // for INT_MAX
+#include <os2dll.h>
+
+/***
+*char *_strlwr(string) - map upper-case characters in a string to lower-case
+*
+*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.
+*
+* In the C locale, this function modifies only 7-bit ASCII characters
+* in the range 0x41 through 0x5A ('A' through 'Z').
+*
+* If the locale is not the 'C' locale, MapString() is used to do
+* the work. Assumes enough space in the string to hold result.
+*
+*Entry:
+* char *string - string to change to lower case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* The original string is returned unchanged on any error.
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strlwr (
+ char * string
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ char *cp; /* traverses string for C locale conversion */
+ wchar_t *wsrc = NULL; /* wide version of string in original case */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+ _munlock (_LC_CTYPE_LOCK);
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('A' <= *cp && *cp <= 'Z')
+ *cp += 'a' - 'A';
+ }
+
+ return(string);
+ } /* C locale */
+
+ /* Algorithm for non-C locale: */
+ /* Convert string to wide-character wsrc string */
+ /* Map wrc string to wide-character wdst string in alternate case */
+ /* Convert wdst string to char string and place in user buffer */
+
+ /* Allocate maximum required space for wsrc */
+ srclen = strlen(string) + 1;
+ if ((wsrc = (wchar_t *) malloc(srclen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Convert string to wide-character wsrc string */
+ if ((srclen=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, string,
+ srclen, wsrc, srclen)) == 0)
+ goto error_cleanup;
+
+ /* Inquire size of wdst string */
+ if ((dstlen=LCMapStringW (_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ /* Convert wdst string to char string and place in user buffer */
+ srclen = INT_MAX; /* may overwrite length of user string */
+ if (WideCharToMultiByte(_lc_codepage, WC_COMPOSITECHECK|WC_SEPCHARS,
+ wdst, dstlen, string, srclen, NULL, NULL) == 0)
+ goto error_cleanup; /* can't recover here if fail */
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wsrc);
+ free (wdst);
+ return (string);
+
+#else
+ char * cp;
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('A' <= *cp && *cp <= 'Z')
+ *cp += 'a' - 'A';
+ }
+
+ return(string);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strncat.c b/private/crt32/string/strncat.c
new file mode 100644
index 000000000..a1e79343a
--- /dev/null
+++ b/private/crt32/string/strncat.c
@@ -0,0 +1,63 @@
+/***
+*strncat.c - 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:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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).
+*
+*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:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strncat (
+ char * front,
+ const char * back,
+ size_t count
+ )
+{
+ char *start = front;
+
+ while (*front++)
+ ;
+ front--;
+
+ while (count--)
+ if (!(*front++ = *back++))
+ return(start);
+
+ *front = '\0';
+ return(start);
+}
diff --git a/private/crt32/string/strncmp.c b/private/crt32/string/strncmp.c
new file mode 100644
index 000000000..3987ff769
--- /dev/null
+++ b/private/crt32/string/strncmp.c
@@ -0,0 +1,61 @@
+/***
+*strncmp.c - 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:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 strncmp (
+ const char * first,
+ const char * last,
+ size_t count
+ )
+{
+ if (!count)
+ return(0);
+
+ while (--count && *first && *first == *last)
+ {
+ first++;
+ last++;
+ }
+
+ return( *(unsigned char *)first - *(unsigned char *)last );
+}
diff --git a/private/crt32/string/strncpy.c b/private/crt32/string/strncpy.c
new file mode 100644
index 000000000..96b75a155
--- /dev/null
+++ b/private/crt32/string/strncpy.c
@@ -0,0 +1,59 @@
+/***
+*strncpy.c - 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:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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.
+*
+*
+*Entry:
+* char *dest - pointer to destination
+* char *source - source string for copy
+* unsigned count - max number of characters to copy
+*
+*Exit:
+* returns dest
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strncpy (
+ char * dest,
+ const char * source,
+ size_t count
+ )
+{
+ char *start = dest;
+
+ while (count && (*dest++ = *source++)) /* copy string */
+ count--;
+
+ if (count) /* pad out with zeroes */
+ while (--count)
+ *dest++ = '\0';
+
+ return(start);
+}
diff --git a/private/crt32/string/strnicmp.c b/private/crt32/string/strnicmp.c
new file mode 100644
index 000000000..bdba31dd9
--- /dev/null
+++ b/private/crt32/string/strnicmp.c
@@ -0,0 +1,76 @@
+/***
+*strnicmp.c - 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:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+* 09-27-93 CFW Avoid cast bug.
+* 06-28-94 SRW Rewrite to use same ANSI specific tolower logic as x86
+* assembler version is i386\strnicmp.asm
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _strnicmp (
+ const char * first,
+ const char * last,
+ size_t count
+ )
+{
+ unsigned char f,l;
+
+ if (count) do {
+ f = *first++;
+ l = *last++;
+ if (f != l) {
+ if (f>='A' && f<='Z') {
+ f = f - 'A' + 'a';
+ }
+ if (l>='A' && l<='Z') {
+ l = l - 'A' + 'a';
+ }
+ if (f!=l) {
+ return f-l;
+ }
+ }
+ }
+ while (--count && f);
+
+ return(0);
+}
diff --git a/private/crt32/string/strnset.c b/private/crt32/string/strnset.c
new file mode 100644
index 000000000..400ff2e7f
--- /dev/null
+++ b/private/crt32/string/strnset.c
@@ -0,0 +1,54 @@
+/***
+*strnset.c - 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:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strnset (
+ char * string,
+ int val,
+ size_t count
+ )
+{
+ char *start = string;
+
+ while (count-- && *string)
+ *string++ = (char)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/strpbrk.c b/private/crt32/string/strpbrk.c
new file mode 100644
index 000000000..e28815571
--- /dev/null
+++ b/private/crt32/string/strpbrk.c
@@ -0,0 +1,2 @@
+#define SSTRPBRK
+#include "strspn.c"
diff --git a/private/crt32/string/strrchr.c b/private/crt32/string/strrchr.c
new file mode 100644
index 000000000..e533aa34e
--- /dev/null
+++ b/private/crt32/string/strrchr.c
@@ -0,0 +1,59 @@
+/***
+*strrchr.c - 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:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strrchr (
+ const char * string,
+ int ch
+ )
+{
+ char *start = (char *)string;
+
+ while (*string++) /* find end of string */
+ ;
+ /* search towards front */
+ while (--string != start && *string != (char)ch)
+ ;
+
+ if (*string == (char)ch) /* char found ? */
+ return( (char *)string );
+
+ return(NULL);
+}
diff --git a/private/crt32/string/strrev.c b/private/crt32/string/strrev.c
new file mode 100644
index 000000000..5c5642b58
--- /dev/null
+++ b/private/crt32/string/strrev.c
@@ -0,0 +1,58 @@
+/***
+*strrev.c - 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:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *_strrev(string) - reverse a string in place
+*
+*Purpose:
+* Reverses the order of characters in the string. The terminating
+* null character remains in place.
+*
+*Entry:
+* char *string - string to reverse
+*
+*Exit:
+* returns string - now with reversed characters
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strrev (
+ char * string
+ )
+{
+ char *start = string;
+ char *left = string;
+ char ch;
+
+ while (*string++) /* find end of string */
+ ;
+ string -= 2;
+
+ while (left < string)
+ {
+ ch = *left;
+ *left++ = *string;
+ *string-- = ch;
+ }
+
+ return(start);
+}
diff --git a/private/crt32/string/strset.c b/private/crt32/string/strset.c
new file mode 100644
index 000000000..957f28163
--- /dev/null
+++ b/private/crt32/string/strset.c
@@ -0,0 +1,58 @@
+/***
+*strset.c - sets all characters 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:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_M_ALPHA) || defined(_M_MRX000) || defined(_M_PPC)
+#pragma function(_strset)
+#endif
+
+/***
+*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.
+*
+*
+*Entry:
+* char *string - string to modify
+* char val - value to fill string with
+*
+*Exit:
+* returns string -- now filled with val's
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strset (
+ char * string,
+ int val
+ )
+{
+ char *start = string;
+
+ while (*string)
+ *string++ = (char)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/strspn.c b/private/crt32/string/strspn.c
new file mode 100644
index 000000000..f49e8f90c
--- /dev/null
+++ b/private/crt32/string/strspn.c
@@ -0,0 +1,179 @@
+/***
+*strspn.c - find length of initial substring of chars from a control string
+*
+* Copyright (c) 1985-1993, 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:
+* 06-01-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarators.
+* 12-04-90 SRW Made it default to compiling for strspn
+* 05-21-93 GJF Used unsigned char pointers to access control and
+* source strings.
+*
+********************************************************************************
+
+/* Determine which routine we're compiling for (default to STRSPN) */
+
+#define _STRSPN 1
+#define _STRCSPN 2
+#define _STRPBRK 3
+
+#if defined(SSTRCSPN)
+#define ROUTINE _STRCSPN
+#elif defined(SSTRPBRK)
+#define ROUTINE _STRPBRK
+#else
+#define ROUTINE _STRSPN
+#endif
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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.
+*
+*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
+*
+*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.
+*
+*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.
+*
+*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.
+*
+*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.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+
+/* Routine prototype */
+#if (ROUTINE == _STRSPN)
+size_t _CALLTYPE1 strspn (
+#elif (ROUTINE == _STRCSPN)
+size_t _CALLTYPE1 strcspn (
+#else /* (ROUTINE == STRPBRK) */
+char * _CALLTYPE1 strpbrk (
+#endif
+ const char * string,
+ const char * control
+ )
+{
+ const unsigned char *str = string;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+
+ /* Clear out bit map */
+ for (count=0; count<32; count++)
+ map[count] = 0;
+
+ /* Set bits in control map */
+ while (*ctrl)
+ {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ ctrl++;
+ }
+
+#if (ROUTINE == _STRSPN)
+
+ /* 1st char NOT in control map stops search */
+ if (*str)
+ {
+ count=0;
+ while (map[*str >> 3] & (1 << (*str & 7)))
+ {
+ count++;
+ str++;
+ }
+ return(count);
+ }
+ return(0);
+
+#elif (ROUTINE == _STRCSPN)
+
+ /* 1st char in control map stops search */
+ count=0;
+ map[0] |= 1; /* null chars not considered */
+ while (!(map[*str >> 3] & (1 << (*str & 7))))
+ {
+ count++;
+ str++;
+ }
+ return(count);
+
+#else /* (ROUTINE == _STRPBRK) */
+
+ /* 1st char in control map stops search */
+ while (*str)
+ {
+ if (map[*str >> 3] & (1 << (*str & 7)))
+ return((char *)str);
+ str++;
+ }
+ return(NULL);
+
+#endif
+
+}
diff --git a/private/crt32/string/strstr.c b/private/crt32/string/strstr.c
new file mode 100644
index 000000000..d523dbbef
--- /dev/null
+++ b/private/crt32/string/strstr.c
@@ -0,0 +1,68 @@
+/***
+*strstr.c - 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-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+* 03-14-94 GJF If string2 is empty, return string1.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*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:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strstr (
+ const char * str1,
+ const char * str2
+ )
+{
+ char *cp = (char *) str1;
+ char *s1, *s2;
+
+ if ( !*str2 )
+ return(str1);
+
+ while (*cp)
+ {
+ s1 = cp;
+ s2 = (char *) str2;
+
+ while ( *s1 && *s2 && !(*s1-*s2) )
+ s1++, s2++;
+
+ if (!*s2)
+ return(cp);
+
+ cp++;
+ }
+
+ return(NULL);
+
+}
diff --git a/private/crt32/string/strtok.c b/private/crt32/string/strtok.c
new file mode 100644
index 000000000..8c51d4f94
--- /dev/null
+++ b/private/crt32/string/strtok.c
@@ -0,0 +1,125 @@
+/***
+*strtok.c - tokenize a string with given delimiters
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strtok() - breaks string into series of token
+* via repeated calls.
+*
+*Revision History:
+* 06-01-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 10-26-91 GJF Fixed nasty bug - search for end-of-token could run
+* off the end of the string.
+* 02-17-93 GJF Changed for new _getptd().
+* 05-21-93 GJF Used unsigned char pointers to access control and
+* source strings.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+
+/***
+*char *strtok(string, control) - tokenize string with delimiter in control
+*
+*Purpose:
+* strtok considers the string to consist of a sequence of zero or more
+* text tokens separated by spans of one or more control chars. the first
+* call, with string specified, returns a pointer to the first char of the
+* first token, and will write a null char into string immediately
+* following the returned token. subsequent calls with zero for the first
+* argument (string) will work thru the string until no tokens remain. the
+* control string may be different from call to call. when no tokens remain
+* in string a NULL pointer is returned. remember the control chars with a
+* bit map, one bit per ascii char. the null char is always a control char.
+*
+*Entry:
+* char *string - string to tokenize, or NULL to get next token
+* char *control - string of characters to use as delimiters
+*
+*Exit:
+* returns pointer to first token in string, or if string
+* was NULL, to next token
+* returns NULL when no more tokens remain.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 strtok (
+ char * string,
+ const char * control
+ )
+{
+ unsigned char *str = string;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+ char *token;
+
+#ifdef MTHREAD
+ _ptiddata ptd = _getptd();
+#else
+ static char *nextoken;
+#endif
+
+ /* Clear control map */
+ for (count = 0; count < 32; count++)
+ map[count] = 0;
+
+ /* Set bits in delimiter table */
+ do {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ } while (*ctrl++);
+
+ /* If string==NULL, continue with previous string */
+ if (!str)
+
+#ifdef MTHREAD
+ str = ptd->_token;
+#else
+ str = nextoken;
+#endif
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets string to point to the terminal
+ * null (*string == '\0') */
+ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
+ str++;
+
+ token = str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *str ; str++ )
+ if ( map[*str >> 3] & (1 << (*str & 7)) ) {
+ *str++ = '\0';
+ break;
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+#ifdef MTHREAD
+ ptd->_token = str;
+#else
+ nextoken = str;
+#endif
+
+ /* Determine if a token has been found. */
+ if ( token == str )
+ return NULL;
+ else
+ return token;
+}
diff --git a/private/crt32/string/strupr.c b/private/crt32/string/strupr.c
new file mode 100644
index 000000000..fcab9dbde
--- /dev/null
+++ b/private/crt32/string/strupr.c
@@ -0,0 +1,138 @@
+/***
+*strupr.c - routine to map lower-case characters in a string to upper-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the lower case characters in string to upper case
+* in place.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 09-18-91 ETC Locale support under _INTL switch.
+* 12-08-91 ETC Updated nlsapi; added multithread.
+* 08-19-92 KRS Activated NLS Support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 03-10-93 CFW Remove UNDONE comment.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <limits.h> /* for INT_MAX */
+#include <os2dll.h>
+
+/***
+*char *_strupr(string) - map lower-case characters in a string to upper-case
+*
+*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.
+*
+* In the C locale, this function modifies only 7-bit ASCII characters
+* in the range 0x61 through 0x7A ('a' through 'z').
+*
+* If the locale is not the 'C' locale, MapStringW() is used to do
+* the work. Assumes enough space in the string to hold result.
+*
+*Entry:
+* char *string - string to change to upper case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* The original string is returned unchanged on any error.
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strupr (
+ char * string
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ char *cp; /* traverses string for C locale conversion */
+ wchar_t *wsrc = NULL; /* wide version of string in original case */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+ _munlock (_LC_CTYPE_LOCK);
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('a' <= *cp && *cp <= 'z')
+ *cp += 'A' - 'a';
+ }
+
+ return(string);
+ } /* C locale */
+
+ /* Algorithm for non-C locale: */
+ /* Convert string to wide-character wsrc string */
+ /* Map wrc string to wide-character wdst string in alternate case */
+ /* Convert wdst string to char string and place in user buffer */
+
+ /* Allocate maximum required space for wsrc */
+ srclen = strlen(string) + 1;
+ if ((wsrc = (wchar_t *) malloc(srclen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Convert string to wide-character wsrc string */
+ if ((srclen=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, string,
+ srclen, wsrc, srclen)) == 0)
+ goto error_cleanup;
+
+ /* Inquire size of wdst string */
+ if ((dstlen=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if ((dstlen=LCMapStringW (_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, dstlen)) == 0)
+ goto error_cleanup;
+
+ /* Convert wdst string to char string and place in user buffer */
+ srclen = INT_MAX; /* may overwrite length of user string */
+ if (WideCharToMultiByte(_lc_codepage, WC_COMPOSITECHECK|WC_SEPCHARS,
+ wdst, dstlen, string, srclen, NULL, NULL) == 0)
+ goto error_cleanup; /* can't recover here if fail */
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wsrc);
+ free (wdst);
+ return (string);
+
+#else
+ char * cp;
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('a' <= *cp && *cp <= 'z')
+ *cp += 'A' - 'a';
+ }
+
+ return(string);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strxfrm.c b/private/crt32/string/strxfrm.c
new file mode 100644
index 000000000..9a3d4dd86
--- /dev/null
+++ b/private/crt32/string/strxfrm.c
@@ -0,0 +1,149 @@
+/***
+*strxfrm.c - Transform a string using locale information
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Transform a string using the locale information as set by
+* LC_COLLATE.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 06-20-89 JCR Removed _LOAD_DGROUP code
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 10-02-91 ETC Non-C locale support under _INTL switch.
+* 12-09-91 ETC Updated api; added multithread.
+* 12-18-91 ETC Don't convert output of LCMapString.
+* 08-18-92 KRS Activate NLS API. Fix behavior.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-11-92 SKS Need to handle count=0 in non-INTL code
+* 12-15-92 KRS Handle return value according to ANSI.
+* 01-18-93 CFW Removed unreferenced variable "dummy".
+* 09-27-93 CFW Use NLS API calls properly.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <limits.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*size_t strxfrm() - Transform a string using locale information
+*
+*Purpose:
+* Transform the string pointer to by _string2 and place the
+* resulting string into the array pointer to by _string1.
+* No more than _count characters are place into the
+* resulting string (including the null).
+*
+* The transformation is such that if strcmp() is applied to
+* the two transformed strings, the return value is equal to
+* the result of strcoll() applied to the two original strings.
+* Thus, the conversion must take the locale LC_COLLATE info
+* into account.
+* [ANSI]
+*
+* The value of the following expression is the size of the array
+* needed to hold the transformation of the source string:
+*
+* 1 + strxfrm(NULL,string,0)
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Thus, strxfrm() simply resolves to strncpy()/strlen().
+*
+*Entry:
+* char *_string1 = result string
+* const char *_string2 = source string
+* size_t _count = max chars to move
+*
+* [If _count is 0, _string1 is permitted to by NULL.]
+*
+*Exit:
+* Length of the transformed string (not including the terminating
+* null). If the value returned is >= _count, the contents of the
+* _string1 array are indeterminate.
+*
+*Exceptions:
+* Non-standard: if OM/API error, return INT_MAX.
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 strxfrm (
+ char *_string1,
+ const char *_string2,
+ size_t _count
+ )
+{
+#ifndef _INTL
+ strncpy(_string1, _string2, _count);
+ return strlen(_string2);
+#else
+ wchar_t *wsrc = NULL; /* wide version of string in original case */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+ int retval = INT_MAX; /* NON-ANSI: default if OM or API error */
+
+ _mlock (_LC_CTYPE_LOCK);
+ _mlock (_LC_COLLATE_LOCK);
+
+ if ((_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP)) {
+ _munlock (_LC_CTYPE_LOCK);
+ _munlock (_LC_COLLATE_LOCK);
+ strncpy(_string1, _string2, _count);
+ return strlen(_string2);
+ }
+
+ /* Algorithm for non-C locale: */
+ /* Convert string to wide-character wsrc string */
+ /* Map wrc string to wide-character wdst string in alternate case */
+ /* Convert wdst string to char string and place in user buffer */
+
+ /* Allocate maximum required space for wsrc */
+ srclen = strlen(_string2) * sizeof(wchar_t);
+ if ((wsrc = (wchar_t *) malloc(srclen)) == NULL)
+ goto error_cleanup;
+
+ /* Convert string to wide-character wsrc string */
+ if ((srclen=MultiByteToWideChar(_lc_codepage,MB_PRECOMPOSED, _string2,
+ -1, wsrc, srclen)) == 0)
+ goto error_cleanup;
+
+ /* Need to transform into a buffer and then copy _count bytes
+ from the buffer to user string; API will fail if target string
+ not long enough */
+
+ /* Inquire size of wdst string */
+ if ((dstlen = LCMapStringW(_lc_handle[LC_COLLATE],
+ LCMAP_SORTKEY, wsrc, srclen, NULL, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst - dstlen is in bytes */
+ if ((wdst = (wchar_t *) malloc(dstlen)) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_COLLATE], LCMAP_SORTKEY,
+ wsrc, srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ retval = strlen((char *)wdst);
+ /* Copy _count bytes to user buffer, or up to first null */
+ strncpy (_string1, (char *) wdst, _count);
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ _munlock (_LC_COLLATE_LOCK);
+ free (wsrc);
+ free (wdst);
+ return (size_t)retval;
+
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/wcscat.c b/private/crt32/string/wcscat.c
new file mode 100644
index 000000000..925492aa3
--- /dev/null
+++ b/private/crt32/string/wcscat.c
@@ -0,0 +1,87 @@
+/***
+*wcscat.c - contains wcscat() and wcscpy()
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* wcscat() appends one wchar_t string onto another.
+* wcscpy() copies one wchar_t string into another.
+*
+* wcscat() concatenates (appends) a copy of the source string to the
+* end of the destination string, returning the destination string.
+* Strings are wide-character strings.
+*
+* wcscpy() copies the source string to the spot pointed to be
+* the destination string, returning the destination string.
+* Strings are wide-character strings.
+*
+*Revision History:
+* 09-09-91 ETC Created from strcat.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcscat(dst, src) - concatenate (append) one wchar_t string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*Entry:
+* wchar_t *dst - wchar_t string to which "src" is to be appended
+* const wchar_t *src - wchar_t string to be appended to the end of "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcscat (
+ wchar_t * dst,
+ const wchar_t * src
+ )
+{
+ wchar_t * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
+
+/***
+*wchar_t *wcscpy(dst, src) - copy one wchar_t string over another
+*
+*Purpose:
+* Copies the wchar_t string src into the spot specified by
+* dest; assumes enough room.
+*
+*Entry:
+* wchar_t * dst - wchar_t string over which "src" is to be copied
+* const wchar_t * src - wchar_t string to be copied over "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcscpy(wchar_t * dst, const wchar_t * src)
+{
+ wchar_t * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return( dst );
+}
diff --git a/private/crt32/string/wcschr.c b/private/crt32/string/wcschr.c
new file mode 100644
index 000000000..3f5814859
--- /dev/null
+++ b/private/crt32/string/wcschr.c
@@ -0,0 +1,48 @@
+/***
+*wcschr.c - search a wchar_t string for a given wchar_t character
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcschr() - search a wchar_t string for a wchar_t character
+*
+*Revision History:
+* 09-09-91 ETC Created from strchr.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcschr(string, c) - search a string for a wchar_t character
+*
+*Purpose:
+* Searches a wchar_t string for a given wchar_t character,
+* which may be the null character L'\0'.
+*
+*Entry:
+* wchar_t *string - wchar_t string to search in
+* wchar_t c - wchar_t character to search for
+*
+*Exit:
+* returns pointer to the first occurence of c in string
+* returns NULL if c does not occur in string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcschr (
+ const wchar_t * string,
+ wchar_t ch
+ )
+{
+ while (*string && *string != (wchar_t)ch)
+ string++;
+
+ if (*string == (wchar_t)ch)
+ return((wchar_t *)string);
+ return(NULL);
+}
diff --git a/private/crt32/string/wcscmp.c b/private/crt32/string/wcscmp.c
new file mode 100644
index 000000000..7b9d3b26c
--- /dev/null
+++ b/private/crt32/string/wcscmp.c
@@ -0,0 +1,59 @@
+/***
+*wcscmp.c - routine to compare two wchar_t strings (for equal, less, or greater)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compares two wide-character strings, determining their lexical order.
+*
+*Revision History:
+* 09-09-91 ETC Created from strcmp.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wcscmp - compare two wchar_t strings,
+* returning less than, equal to, or greater than
+*
+*Purpose:
+* wcscmp compares two wide-character 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.
+*
+* Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
+* say that Null wchar_t(0) is less than any other character.
+*
+*Entry:
+* const wchar_t * src - string for left-hand side of comparison
+* const wchar_t * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 wcscmp (
+ const wchar_t * src,
+ const wchar_t * dst
+ )
+{
+ int ret = 0 ;
+
+ while( ! (ret = (int)(*src - *dst)) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+}
diff --git a/private/crt32/string/wcscoll.c b/private/crt32/string/wcscoll.c
new file mode 100644
index 000000000..8b24fc7b8
--- /dev/null
+++ b/private/crt32/string/wcscoll.c
@@ -0,0 +1,70 @@
+/***
+*wcscoll.c - Collate wide-character locale strings
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information.
+*
+*Revision History:
+* 09-09-91 ETC Created from strcoll.c.
+* 04-06-92 KRS Make work without _INTL also.
+* 08-19-92 KRS Activate NLS support.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int wcscoll() - Collate wide-character locale strings
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information.
+* In the C locale, wcscmp() is used to make the comparison.
+*
+*Entry:
+* const wchar_t *s1 = pointer to the first string
+* const wchar_t *s2 = pointer to the second string
+*
+*Exit:
+* -1 = first string less than second string
+* 0 = strings are equal
+* 1 = first string greater than second string
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcscoll (
+ const wchar_t *_string1,
+ const wchar_t *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ int ret;
+
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ return (wcscmp(_string1, _string2));
+ }
+ if (!(ret = CompareStringW(_lc_handle[LC_COLLATE], 0, _string1, -1,
+ _string2, -1))) {
+ _munlock (_LC_COLLATE_LOCK);
+ return (NLSCMPERROR);
+ }
+
+ _munlock (_LC_COLLATE_LOCK);
+ return (ret - 2);
+#else
+ return wcscmp(_string1, _string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/wcscspn.c b/private/crt32/string/wcscspn.c
new file mode 100644
index 000000000..fde1815a3
--- /dev/null
+++ b/private/crt32/string/wcscspn.c
@@ -0,0 +1,61 @@
+/***
+*wcscspn.c - find length of initial substring of wide characters
+* not in a control string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcscspn()- finds the length of the initial substring of
+* a string consisting entirely of characters not in a control string
+* (wide-character strings).
+*
+*Revision History:
+* 11-04-91 ETC Created with source from crtdll.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*size_t wcscspn(string, control) - search for init substring w/o control wchars
+*
+*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 (wide-character strings).
+*
+*Entry:
+* wchar_t *string - string to search
+* wchar_t *control - set of characters not allowed in init substring
+*
+*Exit:
+* returns the index of the first wchar_t in string
+* that is in the set of characters specified by control.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcscspn (
+ const wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *str = (wchar_t *) string;
+ wchar_t *wcset;
+
+ /* 1st char in control string stops search */
+ while (*str) {
+ for (wcset = (wchar_t *)control; *wcset; wcset++) {
+ if (*wcset == *str) {
+ return str - string;
+ }
+ }
+ str++;
+ }
+ return str - string;
+}
diff --git a/private/crt32/string/wcsdup.c b/private/crt32/string/wcsdup.c
new file mode 100644
index 000000000..22238df23
--- /dev/null
+++ b/private/crt32/string/wcsdup.c
@@ -0,0 +1,57 @@
+/***
+*wcsdup.c - duplicate a wide-character string in malloc'd memory
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsdup() - grab new memory, and duplicate the string into it
+* (wide-character).
+*
+*Revision History:
+* 09-09-91 ETC Created from strdup.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsdup(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 (wide-character).
+*
+*Entry:
+* wchar_t *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:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsdup (
+ const wchar_t * string
+ )
+{
+ wchar_t *memory;
+
+ if (!string)
+ return(NULL);
+
+ if (memory = (wchar_t *) malloc((wcslen(string)+1) * sizeof(wchar_t)))
+ return(wcscpy(memory,string));
+
+ return(NULL);
+}
diff --git a/private/crt32/string/wcsicmp.c b/private/crt32/string/wcsicmp.c
new file mode 100644
index 000000000..7b85d6595
--- /dev/null
+++ b/private/crt32/string/wcsicmp.c
@@ -0,0 +1,90 @@
+/***
+*wcsicmp.c - contains case-insensitive wide string comp routine _wcsicmp
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains _wcsicmp()
+*
+*Revision History:
+* 09-09-91 ETC Created from stricmp.c.
+* 12-09-91 ETC Use C for neutral locale.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+* 08-19-92 KRS Actived use of CompareStringW.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-15-92 KRS Added robustness to non-_INTL code. Optimize.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <locale.h>
+#include <ctype.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int _wcsicmp(dst, src) - compare wide-character strings, ignore case
+*
+*Purpose:
+* _wcsicmp perform a case-insensitive wchar_t string comparision.
+* _wcsicmp is independent of locale.
+*
+* *** NOTE: the comparison should be done in a neutral locale,
+* provided by the NLSAPI. ****
+*
+*Entry:
+* wchar_t *dst, *src - strings to compare
+*
+*Return:
+* <0 if dst < src
+* 0 if dst = src
+* >0 if dst > src
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _wcsicmp (
+ const wchar_t * dst,
+ const wchar_t * src
+ )
+{
+ wchar_t f,l;
+ int ret;
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+/* _mlock (_LC_CTYPE_LOCK); */
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+#endif /* _INTL */
+ do {
+ f = ((*dst <= L'Z') && (*dst >= L'A'))
+ ? *dst + ((wchar_t)(L'a' - L'A'))
+ : *dst;
+ l = ((*src <= L'Z') && (*src >= L'A'))
+ ? *src + ((wchar_t)(L'a' - L'A'))
+ : *src;
+ dst++;
+ src++;
+ } while ((f) && (f == l));
+ ret = (int)((unsigned int)f - (unsigned int)l);
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ }
+ else
+ {
+ ret = CompareStringW(LANG_NEUTRAL,NORM_IGNORECASE,dst,-1,src,-1);
+ /* map return into normal CMP area (-1,0, 1 or ERROR) */
+ ret = (ret) ? (ret-2) : NLSCMPERROR;
+ }
+
+/* _munlock (_LC_CTYPE_LOCK); */
+#endif /* _INTL */
+
+ return ret;
+}
diff --git a/private/crt32/string/wcsicoll.c b/private/crt32/string/wcsicoll.c
new file mode 100644
index 000000000..995a81309
--- /dev/null
+++ b/private/crt32/string/wcsicoll.c
@@ -0,0 +1,73 @@
+/***
+*wcsicoll.c - Collate wide-character locale strings without regard to case
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information
+* without regard to case.
+*
+*Revision History:
+* 10-16-91 ETC Created from wcscoll.c.
+* 12-08-91 ETC Added multithread lock.
+* 04-06-92 KRS Make work without _INTL also.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int _wcsicoll() - Collate wide-character locale strings without regard to case
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information
+* without regard to case.
+* In the C locale, _wcsicmp() is used to make the comparison.
+*
+*Entry:
+* const wchar_t *s1 = pointer to the first string
+* const wchar_t *s2 = pointer to the second string
+*
+*Exit:
+* -1 = first string less than second string
+* 0 = strings are equal
+* 1 = first string greater than second string
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _wcsicoll (
+ const wchar_t *_string1,
+ const wchar_t *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ int ret;
+
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ return (_wcsicmp(_string1, _string2));
+ }
+ ret = CompareStringW(_lc_handle[LC_COLLATE], NORM_IGNORECASE,
+ _string1, -1, _string2, -1);
+
+ _munlock (_LC_COLLATE_LOCK);
+
+ if (!ret)
+ return NLSCMPERROR;
+ else
+ return (ret - 2);
+#else
+ return _wcsicmp(_string1, _string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/wcslen.c b/private/crt32/string/wcslen.c
new file mode 100644
index 000000000..5395f8b07
--- /dev/null
+++ b/private/crt32/string/wcslen.c
@@ -0,0 +1,45 @@
+/***
+*wcslen.c - contains wcslen() routine
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* wcslen returns the length of a null-terminated wide-character string,
+* not including the null wchar_t itself.
+*
+*Revision History:
+* 09-09-91 ETC Created from strlen.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wcslen - return the length of a null-terminated wide-character string
+*
+*Purpose:
+* Finds the length in wchar_t's of the given string, not including
+* the final null wchar_t (wide-characters).
+*
+*Entry:
+* const wchar_t * wcs - string whose length is to be computed
+*
+*Exit:
+* length of the string "wcs", exclusive of the final null wchar_t
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcslen (
+ const wchar_t * wcs
+ )
+{
+ const wchar_t *eos = wcs;
+
+ while( *eos++ ) ;
+
+ return( (size_t)(eos - wcs - 1) );
+}
diff --git a/private/crt32/string/wcslwr.c b/private/crt32/string/wcslwr.c
new file mode 100644
index 000000000..b8cf567cc
--- /dev/null
+++ b/private/crt32/string/wcslwr.c
@@ -0,0 +1,100 @@
+/***
+*wcslwr.c - routine to map upper-case characters in a wchar_t string
+* to lower-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the upper case characters in a wchar_t string
+* to lower case, in place.
+*
+*Revision History:
+* 09-09-91 ETC Created from strlwr.c.
+* 04-06-92 KRS Make work without _INTL also.
+* 08-19-92 KRS Activate NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <ctype.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*wchar_t *_wcslwr(string) - map upper-case characters in a string to lower-case
+*
+*Purpose:
+* wcslwr converts upper-case characters in a null-terminated wchar_t
+* string to their lower-case equivalents. The result may be longer or
+* shorter than the original string. Assumes enough space in string
+* to hold the result.
+*
+*Entry:
+* wchar_t *wsrc - wchar_t string to change to lower case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* on an error, the original string is unaltered
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcslwr (
+ wchar_t * wsrc
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t *p; /* traverses string for C locale conversion */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) {
+ _munlock (_LC_CTYPE_LOCK);
+ for (p=wsrc; *p; p++)
+ if (iswupper(*p))
+ *p = *p - L'A' + L'a';
+ return (wsrc);
+ } /* C locale */
+
+ /* Inquire size of wdst string */
+ srclen = wcslen(wsrc) + 1;
+ if ((dstlen=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ /* Copy wdst string to user string */
+ wcscpy (wsrc, wdst);
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wdst);
+#else
+ wchar_t * p;
+
+ for (p=wsrc; *p; ++p)
+ {
+ if (L'A' <= *p && *p <= L'Z')
+ *p += (wchar_t)L'a' - (wchar_t)L'A';
+ }
+#endif /* _INTL */
+ return (wsrc);
+}
diff --git a/private/crt32/string/wcsncat.c b/private/crt32/string/wcsncat.c
new file mode 100644
index 000000000..98b8e5ba4
--- /dev/null
+++ b/private/crt32/string/wcsncat.c
@@ -0,0 +1,61 @@
+/***
+*wcsncat.c - append n chars of string to new string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncat() - appends n characters of string onto
+* end of other string
+*
+*Revision History:
+* 09-09-91 ETC Created from strncat.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsncat(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 wcsncpy, this routine does not pad out
+* to count characters).
+*
+*Entry:
+* wchar_t *front - string to append onto
+* wchar_t *back - string to append
+* size_t count - count of max characters to append
+*
+*Exit:
+* returns a pointer to string appended onto (front).
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsncat (
+ wchar_t * front,
+ const wchar_t * back,
+ size_t count
+ )
+{
+ wchar_t *start = front;
+
+ while (*front++)
+ ;
+ front--;
+
+ while (count--)
+ if (!(*front++ = *back++))
+ return(start);
+
+ *front = L'\0';
+ return(start);
+}
diff --git a/private/crt32/string/wcsncmp.c b/private/crt32/string/wcsncmp.c
new file mode 100644
index 000000000..b9fd8db65
--- /dev/null
+++ b/private/crt32/string/wcsncmp.c
@@ -0,0 +1,57 @@
+/***
+*wcsncmp.c - compare first n characters of two wide-character strings
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncmp() - compare first n characters of two wchar_t strings
+* for lexical order.
+*
+*Revision History:
+* 09-09-91 ETC Created from strncmp.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*int wcsncmp(first, last, count) - compare first count chars of wchar_t 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 (wide-character strings).
+*
+*Entry:
+* wchar_t *first, *last - strings to compare
+* size_t count - maximum number of characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 wcsncmp (
+ const wchar_t * first,
+ const wchar_t * last,
+ size_t count
+ )
+{
+ if (!count)
+ return(0);
+
+ while (--count && *first && *first == *last)
+ {
+ first++;
+ last++;
+ }
+
+ return((int)(*first - *last));
+}
diff --git a/private/crt32/string/wcsncpy.c b/private/crt32/string/wcsncpy.c
new file mode 100644
index 000000000..2d23573a5
--- /dev/null
+++ b/private/crt32/string/wcsncpy.c
@@ -0,0 +1,57 @@
+/***
+*wcsncpy.c - copy at most n characters of wide-character string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncpy() - copy at most n characters of wchar_t string
+*
+*Revision History:
+* 09-09-91 ETC Created from strncpy.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsncpy(dest, source, count) - copy at most n wide 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 (wide-characters).
+*
+*
+*Entry:
+* wchar_t *dest - pointer to destination
+* wchar_t *source - source string for copy
+* size_t count - max number of characters to copy
+*
+*Exit:
+* returns dest
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsncpy (
+ wchar_t * dest,
+ const wchar_t * source,
+ size_t count
+ )
+{
+ wchar_t *start = dest;
+
+ while (count && (*dest++ = *source++)) /* copy string */
+ count--;
+
+ if (count) /* pad out with zeroes */
+ while (--count)
+ *dest++ = L'\0';
+
+ return(start);
+}
diff --git a/private/crt32/string/wcsnicmp.c b/private/crt32/string/wcsnicmp.c
new file mode 100644
index 000000000..98a68620d
--- /dev/null
+++ b/private/crt32/string/wcsnicmp.c
@@ -0,0 +1,91 @@
+/***
+*wcsnicmp.c - compare n chars of wide-character strings, ignoring case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsnicmp() - Compares at most n characters of two wchar_t
+* strings, without regard to case.
+*
+*Revision History:
+* 09-09-91 ETC Created from strnicmp.c and wcsicmp.c.
+* 12-09-91 ETC Use C for neutral locale.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
+#ifdef _INTL
+#include <setlocal.h>
+#include <os2dll.h>
+#endif
+
+/***
+*int _wcsnicmp(first, last, count) - compares count wchar_t 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 (wide-characters).
+*
+* *** NOTE: the comparison should be done in a neutral locale,
+* provided by the NLSAPI. Currently, the comparison is done
+* in the C locale. ***
+*
+*Entry:
+* wchar_t *first, *last - strings to compare
+* size_t count - maximum number of characters to compare
+*
+*Exit:
+* -1 if first < last
+* 0 if first == last
+* 1 if first > last
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _wcsnicmp (
+ const wchar_t * first,
+ const wchar_t * last,
+ size_t count
+ )
+{
+ wchar_t f,l;
+ int result = 0;
+
+ if (count)
+ {
+#if defined(_INTL) && !defined(_NTSUBSET_)
+
+ _mlock (_LC_CTYPE_LOCK);
+#endif
+
+ do
+ {
+ f = iswupper(*first)
+ ? *first - (wchar_t)L'A' + (wchar_t)L'a'
+ : *first;
+ l = iswupper(*last)
+ ? *last - (wchar_t)L'A' + (wchar_t)L'a'
+ : *last;
+ first++;
+ last++;
+ } while (--count && f && l && f == l);
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ _munlock (_LC_CTYPE_LOCK);
+#endif
+
+ result = (int)(f - l);
+ }
+ return result ;
+}
diff --git a/private/crt32/string/wcsnset.c b/private/crt32/string/wcsnset.c
new file mode 100644
index 000000000..415f14b45
--- /dev/null
+++ b/private/crt32/string/wcsnset.c
@@ -0,0 +1,51 @@
+/***
+*wcsnset.c - set first n wide-characters to single wide-character
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsnset() - sets at most the first n characters of a
+* wchar_t string to a given character.
+*
+*Revision History:
+* 09-09-91 ETC Created from strnset.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsnset(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 (wide-characters).
+*
+*Entry:
+* wchar_t *string - string to set characters in
+* wchar_t val - character to fill with
+* size_t count - count of characters to fill
+*
+*Exit:
+* returns string, now filled with count copies of val.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsnset (
+ wchar_t * string,
+ wchar_t val,
+ size_t count
+ )
+{
+ wchar_t *start = string;
+
+ while (count-- && *string)
+ *string++ = (wchar_t)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/wcspbrk.c b/private/crt32/string/wcspbrk.c
new file mode 100644
index 000000000..52e801e31
--- /dev/null
+++ b/private/crt32/string/wcspbrk.c
@@ -0,0 +1,56 @@
+/***
+*wcspbrk.c - scans wide character string for a character from control string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcspbrk()- returns pointer to the first wide-character in
+* a wide-character string in the control string.
+*
+*Revision History:
+* 11-04-91 ETC Created with source from crtdll.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcspbrk(string, control) - scans string for a character from control
+*
+*Purpose:
+* Returns pointer to the first wide-character in
+* a wide-character string in the control string.
+*
+*Entry:
+* wchar_t *string - string to search in
+* wchar_t *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.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcspbrk (
+ const wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *wcset;
+
+ /* 1st char in control string stops search */
+ while (*string) {
+ for (wcset = (wchar_t *) control; *wcset; wcset++) {
+ if (*wcset == *string) {
+ return (wchar_t *) string;
+ }
+ }
+ string++;
+ }
+ return NULL;
+}
diff --git a/private/crt32/string/wcsrchr.c b/private/crt32/string/wcsrchr.c
new file mode 100644
index 000000000..9dc3b004a
--- /dev/null
+++ b/private/crt32/string/wcsrchr.c
@@ -0,0 +1,56 @@
+/***
+*wcsrchr.c - find last occurrence of wchar_t character in wide string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsrchr() - find the last occurrence of a given character
+* in a string (wide-characters).
+*
+*Revision History:
+* 09-09-91 ETC Created from strrchr.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsrchr(string, ch) - find last occurrence of ch in wide string
+*
+*Purpose:
+* Finds the last occurrence of ch in string. The terminating
+* null character is used as part of the search (wide-characters).
+*
+*Entry:
+* wchar_t *string - string to search in
+* wchar_t 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
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsrchr (
+ const wchar_t * string,
+ wchar_t ch
+ )
+{
+ wchar_t *start = (wchar_t *)string;
+
+ while (*string++) /* find end of string */
+ ;
+ /* search towards front */
+ while (--string != start && *string != (wchar_t)ch)
+ ;
+
+ if (*string == (wchar_t)ch) /* wchar_t found ? */
+ return( (wchar_t *)string );
+
+ return(NULL);
+}
diff --git a/private/crt32/string/wcsrev.c b/private/crt32/string/wcsrev.c
new file mode 100644
index 000000000..0ea09b944
--- /dev/null
+++ b/private/crt32/string/wcsrev.c
@@ -0,0 +1,56 @@
+/***
+*wcsrev.c - reverse a wide-character string in place
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsrev() - reverse a wchar_t string in place (not including
+* L'\0' character)
+*
+*Revision History:
+* 09-09-91 ETC Created from strrev.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsrev(string) - reverse a wide-character string in place
+*
+*Purpose:
+* Reverses the order of characters in the string. The terminating
+* null character remains in place (wide-characters).
+*
+*Entry:
+* wchar_t *string - string to reverse
+*
+*Exit:
+* returns string - now with reversed characters
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsrev (
+ wchar_t * string
+ )
+{
+ wchar_t *start = string;
+ wchar_t *left = string;
+ wchar_t ch;
+
+ while (*string++) /* find end of string */
+ ;
+ string -= 2;
+
+ while (left < string)
+ {
+ ch = *left;
+ *left++ = *string;
+ *string-- = ch;
+ }
+
+ return(start);
+}
diff --git a/private/crt32/string/wcsset.c b/private/crt32/string/wcsset.c
new file mode 100644
index 000000000..c5e6d9f88
--- /dev/null
+++ b/private/crt32/string/wcsset.c
@@ -0,0 +1,51 @@
+/***
+*wcsset.c - sets all characters of wchar_t string to given character
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsset() - sets all of the characters in a string (except
+* the L'\0') equal to a given character (wide-characters).
+*
+*Revision History:
+* 09-09-91 ETC Created from strset.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsset(string, val) - sets all of string to val (wide-characters)
+*
+*Purpose:
+* Sets all of wchar_t characters in string (except the terminating '/0'
+* character) equal to val (wide-characters).
+*
+*
+*Entry:
+* wchar_t *string - string to modify
+* wchar_t val - value to fill string with
+*
+*Exit:
+* returns string -- now filled with val's
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsset (
+ wchar_t * string,
+ wchar_t val
+ )
+{
+ wchar_t *start = string;
+
+ while (*string)
+ *string++ = (wchar_t)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/wcsspn.c b/private/crt32/string/wcsspn.c
new file mode 100644
index 000000000..7aed8505e
--- /dev/null
+++ b/private/crt32/string/wcsspn.c
@@ -0,0 +1,67 @@
+/***
+*wcsspn.c - find length of initial substring of chars from a control string
+* (wide-character strings)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsspn() - finds the length of the initial substring of
+* a string consisting entirely of characters from a control string
+* (wide-character strings).
+*
+*Revision History:
+* 11-04-91 ETC Created with source from crtdll.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*int wcsspn(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 L'\0' character
+* that terminates control is not considered in the matching process
+* (wide-character strings).
+*
+*Entry:
+* wchar_t *string - string to search
+* wchar_t *control - string containing characters not to search for
+*
+*Exit:
+* returns index of first wchar_t in string not in control
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcsspn (
+ const wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *str = (wchar_t *) string;
+ wchar_t *ctl;
+
+ /* 1st char not in control string stops search */
+ while (*str) {
+ for (ctl = (wchar_t *)control; *ctl != *str; ctl++) {
+ if (*ctl == (wchar_t)0) {
+ /*
+ * reached end of control string without finding a match
+ */
+ return str - string;
+ }
+ }
+ str++;
+ }
+ /*
+ * The whole string consisted of characters from control
+ */
+ return str - string;
+}
diff --git a/private/crt32/string/wcsstr.c b/private/crt32/string/wcsstr.c
new file mode 100644
index 000000000..df6d3d638
--- /dev/null
+++ b/private/crt32/string/wcsstr.c
@@ -0,0 +1,62 @@
+/***
+*wcsstr.c - search for one wide-character string inside another
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsstr() - search for one wchar_t string inside another
+*
+*Revision History:
+* 09-09-91 ETC Created from strstr.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsstr(string1, string2) - search for string2 in string1
+* (wide strings)
+*
+*Purpose:
+* finds the first occurrence of string2 in string1 (wide strings)
+*
+*Entry:
+* wchar_t *string1 - string to search in
+* wchar_t *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:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsstr (
+ const wchar_t * wcs1,
+ const wchar_t * wcs2
+ )
+{
+ wchar_t *cp = (wchar_t *) wcs1;
+ wchar_t *s1, *s2;
+
+ while (*cp)
+ {
+ s1 = cp;
+ s2 = (wchar_t *) wcs2;
+
+ while ( *s1 && *s2 && !(*s1-*s2) )
+ s1++, s2++;
+
+ if (!*s2)
+ return(cp);
+
+ cp++;
+ }
+
+ return(NULL);
+}
diff --git a/private/crt32/string/wcstok.c b/private/crt32/string/wcstok.c
new file mode 100644
index 000000000..4d1c324ae
--- /dev/null
+++ b/private/crt32/string/wcstok.c
@@ -0,0 +1,174 @@
+/***
+*wcstok.c - tokenize a wide-character string with given delimiters
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcstok() - breaks wide-character string into series of token
+* via repeated calls.
+*
+*Revision History:
+* 09-09-91 ETC Created from strtok.c.
+* 08-17-92 KRS Activate multithread support.
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+
+/***
+*wchar_t *wcstok(string, control) - tokenize string with delimiter in control
+* (wide-characters)
+*
+*Purpose:
+* wcstok considers the string to consist of a sequence of zero or more
+* text tokens separated by spans of one or more control chars. the first
+* call, with string specified, returns a pointer to the first wchar_t of
+* the first token, and will write a null wchar_t into string immediately
+* following the returned token. subsequent calls with zero for the first
+* argument (string) will work thru the string until no tokens remain. the
+* control string may be different from call to call. when no tokens remain
+* in string a NULL pointer is returned. remember the control chars with a
+* bit map, one bit per wchar_t. the null wchar_t is always a control char
+* (wide-characters).
+*
+*Entry:
+* wchar_t *string - wchar_t string to tokenize, or NULL to get next token
+* wchar_t *control - wchar_t string of characters to use as delimiters
+*
+*Exit:
+* returns pointer to first token in string, or if string
+* was NULL, to next token
+* returns NULL when no more tokens remain.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 wcstok (
+ wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *token;
+ const wchar_t *ctl;
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+ tdata = _gettidtab(); /* init tid's data address */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+
+ static wchar_t *nextoken;
+
+#endif
+
+ /* If string==NULL, continue with previous string */
+ if (!string)
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ string = tdata->_wtoken;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ string = ptd->_wtoken;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+
+ string = nextoken;
+
+#endif
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets string to point to the terminal
+ * null (*string == '\0') */
+
+ while (*string) {
+ for (ctl=control; *ctl && *ctl != *string; ctl++)
+ ;
+ if (!*ctl) break;
+ string++;
+ }
+
+ token = string;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *string ; string++ ) {
+ for (ctl=control; *ctl && *ctl != *string; ctl++)
+ ;
+ if (*ctl) {
+ *string++ = '\0';
+ break;
+ }
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ tdata->_wtoken = string;
+
+#else /* _CRUISER_ */
+
+#ifdef _WIN32_
+
+ ptd->_wtoken = string;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+ nextoken = string;
+#endif
+
+ /* Determine if a token has been found. */
+ if ( token == string )
+ return NULL;
+ else
+ return token;
+}
diff --git a/private/crt32/string/wcsupr.c b/private/crt32/string/wcsupr.c
new file mode 100644
index 000000000..5a302db66
--- /dev/null
+++ b/private/crt32/string/wcsupr.c
@@ -0,0 +1,104 @@
+/***
+*wcsupr.c - routine to map lower-case characters in a wchar_t string
+* to upper-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the lower case characters in a wchar_t string
+* to upper case, in place.
+*
+*Revision History:
+* 09-09-91 ETC Created from strupr.c and wcslwr.c
+# 04-06-92 KRS Make work without _INTL also.
+# 08-19-92 KRS Activate NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 02-16-93 CFW Optimize test for lowercase in "C" locale.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <ctype.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*wchar_t *_wcsupr(string) - map lower-case characters in a string to upper-case
+*
+*Purpose:
+* wcsupr converts lower-case characters in a null-terminated wchar_t
+* string to their upper-case equivalents. The result may be longer or
+* shorter than the original string. Assumes enough space in string
+* to hold the result.
+*
+*Entry:
+* wchar_t *wsrc - wchar_t string to change to upper case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* on an error, the original string is unaltered
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsupr (
+ wchar_t * wsrc
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t *p; /* traverses string for C locale conversion */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) {
+ _munlock (_LC_CTYPE_LOCK);
+ for (p=wsrc; *p; p++)
+ {
+ if (*p >= (wchar_t)L'a' && *p <= (wchar_t)L'z')
+ *p = *p - (L'a' - L'A');
+ }
+ return (wsrc);
+ } /* C locale */
+
+ /* Inquire size of wdst string */
+ srclen = wcslen(wsrc) + 1;
+ if ((dstlen=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ /* Copy wdst string to user string */
+ wcscpy (wsrc, wdst);
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wdst);
+#else
+ wchar_t * p;
+
+ for (p=wsrc; *p; ++p)
+ {
+ if (L'a' <= *p && *p <= L'z')
+ *p += (wchar_t)(L'A' - L'a');
+ }
+
+#endif /* _INTL */
+ return (wsrc);
+}
diff --git a/private/crt32/string/wcsxfrm.c b/private/crt32/string/wcsxfrm.c
new file mode 100644
index 000000000..b812450ca
--- /dev/null
+++ b/private/crt32/string/wcsxfrm.c
@@ -0,0 +1,126 @@
+/***
+*wcsxfrm.c - Transform a wide-character string using locale information
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Transform a wide-character string using the locale information as set by
+* LC_COLLATE.
+*
+*Revision History:
+* 09-09-91 ETC Created from strxfrm.c.
+* 12-09-91 ETC Updated api; Added multithread lock.
+* 12-18-91 ETC Changed back LCMAP_SORTKEYA --> LCMAP_SORTKEY.
+* 04-06-92 KRS Fix so it works without _INTL too.
+* 08-19-92 KRS Activate use of NLS API.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-15-92 KRS Fix return value to match ANSI/ISO Std.
+* 09-23-93 CFW Complete re-write. Non-C locale totally broken.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*size_t wcsxfrm() - Transform a string using locale information
+*
+*Purpose:
+* Transform the wide string pointed to by _string2 and place the
+* resulting wide string into the array pointed to by _string1.
+* No more than _count wide characters are placed into the
+* resulting string (including the null).
+*
+* The transformation is such that if wcscmp() is applied to
+* the two transformed strings, the return value is equal to
+* the result of wcscoll() applied to the two original strings.
+* Thus, the conversion must take the locale LC_COLLATE info
+* into account.
+*
+* In the C locale, wcsxfrm() simply resolves to wcsncpy()/wcslen().
+*
+*Entry:
+* wchar_t *_string1 = result string
+* const wchar_t *_string2 = source string
+* size_t _count = max wide chars to move
+*
+* [If _count is 0, _string1 is permitted to be NULL.]
+*
+*Exit:
+* Length of the transformed string (not including the terminating
+* null). If the value returned is >= _count, the contents of the
+* _string1 array are indeterminate.
+*
+*Exceptions:
+* Non-standard: if OM/API error, return INT_MAX.
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 wcsxfrm (
+ wchar_t *_string1,
+ const wchar_t *_string2,
+ size_t _count
+ )
+{
+#ifndef _INTL
+ if (_string1)
+ wcsncpy(_string1, _string2, _count);
+ return wcslen(_string2);
+#else
+ int size;
+ unsigned char *bbuffer;
+
+
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ wcsncpy(_string1, _string2, _count);
+ return wcslen(_string2);
+ }
+
+ /*
+ * When using LCMAP_SORTKEY, LCMapStringW handles BYTES not wide
+ * chars. We use a byte buffer to hold bytes and then convert the
+ * byte string to a wide char string and return this so it can be
+ * compared using wcscmp(). User's buffer is _count wide chars, so
+ * use an internal buffer of _count bytes.
+ */
+
+ if (NULL == (bbuffer = (unsigned char *)malloc(_count)))
+ {
+ size = INT_MAX;
+ goto error_cleanup;
+ }
+
+ if (0 == (size = LCMapStringW(_lc_handle[LC_COLLATE], LCMAP_SORTKEY,
+ _string2, -1, (wchar_t *)bbuffer, _count)))
+ {
+ /* buffer not big enough, get size required. */
+
+ if (0 == (size = LCMapStringW(_lc_handle[LC_COLLATE], LCMAP_SORTKEY,
+ _string2, -1, NULL, 0)))
+ size = INT_MAX; /* default error */
+ else
+ size--; /* don't count NULL */
+
+ } else {
+ int i;
+ /* string successfully mapped, convert to wide char */
+
+ for (i = 0; i < size; i++)
+ _string1[i] = (wchar_t)bbuffer[i];
+
+ size--; /* don't count NULL */
+ }
+
+error_cleanup:
+ _munlock (_LC_COLLATE_LOCK);
+ return (size_t)size;
+#endif /* _INTL */
+}