From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/crt32/string/alpha/strcat.c | 63 ++ private/crt32/string/alpha/strcmps.s | 357 ++++++++++ private/crt32/string/alpha/strcpys.s | 257 +++++++ private/crt32/string/alpha/strlens.s | 95 +++ private/crt32/string/i386/memccpy.asm | 103 +++ private/crt32/string/i386/memchr.asm | 96 +++ private/crt32/string/i386/memcmp.asm | 101 +++ private/crt32/string/i386/memcpy.asm | 354 ++++++++++ private/crt32/string/i386/memicmp.asm | 132 ++++ private/crt32/string/i386/memmove.asm | 19 + private/crt32/string/i386/memset.asm | 127 ++++ private/crt32/string/i386/strcat.asm | 155 ++++ private/crt32/string/i386/strchr.asm | 94 +++ private/crt32/string/i386/strcmp.asm | 104 +++ private/crt32/string/i386/strcspn.asm | 19 + private/crt32/string/i386/strdup.asm | 126 ++++ private/crt32/string/i386/stricmp.asm | 127 ++++ private/crt32/string/i386/strlen.asm | 84 +++ private/crt32/string/i386/strlwr.asm | 104 +++ private/crt32/string/i386/strncat.asm | 117 +++ private/crt32/string/i386/strncmp.asm | 120 ++++ private/crt32/string/i386/strncpy.asm | 108 +++ private/crt32/string/i386/strnicmp.asm | 153 ++++ private/crt32/string/i386/strnset.asm | 104 +++ private/crt32/string/i386/strpbrk.asm | 19 + private/crt32/string/i386/strrchr.asm | 105 +++ private/crt32/string/i386/strrev.asm | 121 ++++ private/crt32/string/i386/strset.asm | 93 +++ private/crt32/string/i386/strspn.asm | 277 ++++++++ private/crt32/string/i386/strstr.asm | 135 ++++ private/crt32/string/i386/strupr.asm | 104 +++ private/crt32/string/makefile | 6 + private/crt32/string/makefile.inc | 9 + private/crt32/string/memccpy.c | 59 ++ private/crt32/string/memchr.c | 57 ++ private/crt32/string/memcmp.c | 65 ++ private/crt32/string/memcpy.c | 80 +++ private/crt32/string/memicmp.c | 77 ++ private/crt32/string/memmove.c | 93 +++ private/crt32/string/memset.c | 70 ++ private/crt32/string/mips/memcmpm.s | 125 ++++ private/crt32/string/mips/memcmpt.c | 334 +++++++++ private/crt32/string/mips/memcpym.s | 298 ++++++++ private/crt32/string/mips/memorym.s | 1218 ++++++++++++++++++++++++++++++++ private/crt32/string/mips/memsetm.s | 105 +++ private/crt32/string/mips/memsett.c | 20 + private/crt32/string/mips/strcatm.s | 98 +++ private/crt32/string/mips/strchrm.s | 26 + private/crt32/string/mips/strchrt.c | 20 + private/crt32/string/mips/strcmpm.s | 50 ++ private/crt32/string/mips/strcpym.s | 148 ++++ private/crt32/string/mips/strcpyt.c | 23 + private/crt32/string/mips/strlenm.s | 19 + private/crt32/string/mips/strrchrm.s | 24 + private/crt32/string/mips/strrchrt.c | 20 + private/crt32/string/mips/wcscmpm.s | 67 ++ private/crt32/string/mips/wcscmpt.c | 62 ++ private/crt32/string/mips/wcscpym.s | 139 ++++ private/crt32/string/mips/wcslenm.s | 45 ++ private/crt32/string/ppc/memccpyp.s | 78 ++ private/crt32/string/ppc/memchrp.s | 74 ++ private/crt32/string/ppc/memcmpp.s | 71 ++ private/crt32/string/ppc/strcatp.s | 137 ++++ private/crt32/string/ppc/strchrp.s | 70 ++ private/crt32/string/ppc/strcmpp.s | 74 ++ private/crt32/string/ppc/stricmpp.s | 89 +++ private/crt32/string/ppc/strlenp.s | 164 +++++ private/crt32/string/ppc/strrchrp.s | 87 +++ private/crt32/string/sources | 175 +++++ private/crt32/string/strcat.c | 90 +++ private/crt32/string/strchr.c | 52 ++ private/crt32/string/strcmp.c | 68 ++ private/crt32/string/strcoll.c | 103 +++ private/crt32/string/strcspn.c | 2 + private/crt32/string/strdup.c | 60 ++ private/crt32/string/stricmp.c | 80 +++ private/crt32/string/stricoll.c | 95 +++ private/crt32/string/strlen.c | 54 ++ private/crt32/string/strlwr.c | 137 ++++ private/crt32/string/strncat.c | 63 ++ private/crt32/string/strncmp.c | 61 ++ private/crt32/string/strncpy.c | 59 ++ private/crt32/string/strnicmp.c | 76 ++ private/crt32/string/strnset.c | 54 ++ private/crt32/string/strpbrk.c | 2 + private/crt32/string/strrchr.c | 59 ++ private/crt32/string/strrev.c | 58 ++ private/crt32/string/strset.c | 58 ++ private/crt32/string/strspn.c | 179 +++++ private/crt32/string/strstr.c | 68 ++ private/crt32/string/strtok.c | 125 ++++ private/crt32/string/strupr.c | 138 ++++ private/crt32/string/strxfrm.c | 149 ++++ private/crt32/string/wcscat.c | 87 +++ private/crt32/string/wcschr.c | 48 ++ private/crt32/string/wcscmp.c | 59 ++ private/crt32/string/wcscoll.c | 70 ++ private/crt32/string/wcscspn.c | 61 ++ private/crt32/string/wcsdup.c | 57 ++ private/crt32/string/wcsicmp.c | 90 +++ private/crt32/string/wcsicoll.c | 73 ++ private/crt32/string/wcslen.c | 45 ++ private/crt32/string/wcslwr.c | 100 +++ private/crt32/string/wcsncat.c | 61 ++ private/crt32/string/wcsncmp.c | 57 ++ private/crt32/string/wcsncpy.c | 57 ++ private/crt32/string/wcsnicmp.c | 91 +++ private/crt32/string/wcsnset.c | 51 ++ private/crt32/string/wcspbrk.c | 56 ++ private/crt32/string/wcsrchr.c | 56 ++ private/crt32/string/wcsrev.c | 56 ++ private/crt32/string/wcsset.c | 51 ++ private/crt32/string/wcsspn.c | 67 ++ private/crt32/string/wcsstr.c | 62 ++ private/crt32/string/wcstok.c | 174 +++++ private/crt32/string/wcsupr.c | 104 +++ private/crt32/string/wcsxfrm.c | 126 ++++ 117 files changed, 11998 insertions(+) create mode 100644 private/crt32/string/alpha/strcat.c create mode 100644 private/crt32/string/alpha/strcmps.s create mode 100644 private/crt32/string/alpha/strcpys.s create mode 100644 private/crt32/string/alpha/strlens.s create mode 100644 private/crt32/string/i386/memccpy.asm create mode 100644 private/crt32/string/i386/memchr.asm create mode 100644 private/crt32/string/i386/memcmp.asm create mode 100644 private/crt32/string/i386/memcpy.asm create mode 100644 private/crt32/string/i386/memicmp.asm create mode 100644 private/crt32/string/i386/memmove.asm create mode 100644 private/crt32/string/i386/memset.asm create mode 100644 private/crt32/string/i386/strcat.asm create mode 100644 private/crt32/string/i386/strchr.asm create mode 100644 private/crt32/string/i386/strcmp.asm create mode 100644 private/crt32/string/i386/strcspn.asm create mode 100644 private/crt32/string/i386/strdup.asm create mode 100644 private/crt32/string/i386/stricmp.asm create mode 100644 private/crt32/string/i386/strlen.asm create mode 100644 private/crt32/string/i386/strlwr.asm create mode 100644 private/crt32/string/i386/strncat.asm create mode 100644 private/crt32/string/i386/strncmp.asm create mode 100644 private/crt32/string/i386/strncpy.asm create mode 100644 private/crt32/string/i386/strnicmp.asm create mode 100644 private/crt32/string/i386/strnset.asm create mode 100644 private/crt32/string/i386/strpbrk.asm create mode 100644 private/crt32/string/i386/strrchr.asm create mode 100644 private/crt32/string/i386/strrev.asm create mode 100644 private/crt32/string/i386/strset.asm create mode 100644 private/crt32/string/i386/strspn.asm create mode 100644 private/crt32/string/i386/strstr.asm create mode 100644 private/crt32/string/i386/strupr.asm create mode 100644 private/crt32/string/makefile create mode 100644 private/crt32/string/makefile.inc create mode 100644 private/crt32/string/memccpy.c create mode 100644 private/crt32/string/memchr.c create mode 100644 private/crt32/string/memcmp.c create mode 100644 private/crt32/string/memcpy.c create mode 100644 private/crt32/string/memicmp.c create mode 100644 private/crt32/string/memmove.c create mode 100644 private/crt32/string/memset.c create mode 100644 private/crt32/string/mips/memcmpm.s create mode 100644 private/crt32/string/mips/memcmpt.c create mode 100644 private/crt32/string/mips/memcpym.s create mode 100644 private/crt32/string/mips/memorym.s create mode 100644 private/crt32/string/mips/memsetm.s create mode 100644 private/crt32/string/mips/memsett.c create mode 100644 private/crt32/string/mips/strcatm.s create mode 100644 private/crt32/string/mips/strchrm.s create mode 100644 private/crt32/string/mips/strchrt.c create mode 100644 private/crt32/string/mips/strcmpm.s create mode 100644 private/crt32/string/mips/strcpym.s create mode 100644 private/crt32/string/mips/strcpyt.c create mode 100644 private/crt32/string/mips/strlenm.s create mode 100644 private/crt32/string/mips/strrchrm.s create mode 100644 private/crt32/string/mips/strrchrt.c create mode 100644 private/crt32/string/mips/wcscmpm.s create mode 100644 private/crt32/string/mips/wcscmpt.c create mode 100644 private/crt32/string/mips/wcscpym.s create mode 100644 private/crt32/string/mips/wcslenm.s create mode 100644 private/crt32/string/ppc/memccpyp.s create mode 100644 private/crt32/string/ppc/memchrp.s create mode 100644 private/crt32/string/ppc/memcmpp.s create mode 100644 private/crt32/string/ppc/strcatp.s create mode 100644 private/crt32/string/ppc/strchrp.s create mode 100644 private/crt32/string/ppc/strcmpp.s create mode 100644 private/crt32/string/ppc/stricmpp.s create mode 100644 private/crt32/string/ppc/strlenp.s create mode 100644 private/crt32/string/ppc/strrchrp.s create mode 100644 private/crt32/string/sources create mode 100644 private/crt32/string/strcat.c create mode 100644 private/crt32/string/strchr.c create mode 100644 private/crt32/string/strcmp.c create mode 100644 private/crt32/string/strcoll.c create mode 100644 private/crt32/string/strcspn.c create mode 100644 private/crt32/string/strdup.c create mode 100644 private/crt32/string/stricmp.c create mode 100644 private/crt32/string/stricoll.c create mode 100644 private/crt32/string/strlen.c create mode 100644 private/crt32/string/strlwr.c create mode 100644 private/crt32/string/strncat.c create mode 100644 private/crt32/string/strncmp.c create mode 100644 private/crt32/string/strncpy.c create mode 100644 private/crt32/string/strnicmp.c create mode 100644 private/crt32/string/strnset.c create mode 100644 private/crt32/string/strpbrk.c create mode 100644 private/crt32/string/strrchr.c create mode 100644 private/crt32/string/strrev.c create mode 100644 private/crt32/string/strset.c create mode 100644 private/crt32/string/strspn.c create mode 100644 private/crt32/string/strstr.c create mode 100644 private/crt32/string/strtok.c create mode 100644 private/crt32/string/strupr.c create mode 100644 private/crt32/string/strxfrm.c create mode 100644 private/crt32/string/wcscat.c create mode 100644 private/crt32/string/wcschr.c create mode 100644 private/crt32/string/wcscmp.c create mode 100644 private/crt32/string/wcscoll.c create mode 100644 private/crt32/string/wcscspn.c create mode 100644 private/crt32/string/wcsdup.c create mode 100644 private/crt32/string/wcsicmp.c create mode 100644 private/crt32/string/wcsicoll.c create mode 100644 private/crt32/string/wcslen.c create mode 100644 private/crt32/string/wcslwr.c create mode 100644 private/crt32/string/wcsncat.c create mode 100644 private/crt32/string/wcsncmp.c create mode 100644 private/crt32/string/wcsncpy.c create mode 100644 private/crt32/string/wcsnicmp.c create mode 100644 private/crt32/string/wcsnset.c create mode 100644 private/crt32/string/wcspbrk.c create mode 100644 private/crt32/string/wcsrchr.c create mode 100644 private/crt32/string/wcsrev.c create mode 100644 private/crt32/string/wcsset.c create mode 100644 private/crt32/string/wcsspn.c create mode 100644 private/crt32/string/wcsstr.c create mode 100644 private/crt32/string/wcstok.c create mode 100644 private/crt32/string/wcsupr.c create mode 100644 private/crt32/string/wcsxfrm.c (limited to 'private/crt32/string') 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 , 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 +#include + +#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 A0 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 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 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 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 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 +else + _MEM_ equ +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 ; + je short toend ; + ;jb short firstbig ; + +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 + +elseifdef SSTRPBRK + + _STRSPN_ equ + +else + +; Default is to build strspn() + + SSTRSPN equ 1 + _STRSPN_ equ + +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 ; set ecx to -1 + + align @WordSize +lab dstnext + +_ifnd SSTRPBRK + + 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 , fixed +* copyright. Also, fixed compiler warning. +* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant +* #include +* 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 +#include + +/*** +*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 , fixed +* copyright. +* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant +* #include +* 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 +#include + +/*** +*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 , 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 +#include + +#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 , 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 +#include + +#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 , 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 +#include +#include + +/*** +*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 , 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 +#include + +#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 , 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 +#include + +#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 +#include + +#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 + +/* + * 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 + +#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 +#include + +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 + +/* 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 +#include +#include + +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 + + .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 + +/* 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 +#include + +#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 + +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 +#include +#include + +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 + + .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 +#include + +#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 + +.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 + +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 + +// +// 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 + +// +// 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 + +// +// 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 + +//++ +// +// 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 + +// +// *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 + +// +// 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 + +// 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 + + 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 +// +// 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 , 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 +#include + +#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 , fixed +* copyright. +* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant +* #include +* 10-01-90 GJF New-style function declarator. +* +*******************************************************************************/ + +#include +#include + +/*** +*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 , 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 +#include + +#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 , 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 +#include +#include +#include +#include +#include + +/*** +*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 , fixed +* copyright. +* 08-14-90 SBM Removed now redundant #include +* 10-02-90 GJF New-style function declarator. +* 01-18-91 GJF ANSI naming. +* +*******************************************************************************/ + +#include +#include +#include + +/*** +*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 , fixed +* copyright. +* 07-25-90 SBM Added #include +* 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 +#include +#include + +/*** +*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 +#include +#include +#include +#include +#include + +/*** +*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 , 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 +#include + +#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 , 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 +#include +#include +#include +#include +#include // for INT_MAX +#include + +/*** +*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 , fixed +* copyright. +* 10-02-90 GJF New-style function declarator. +* +*******************************************************************************/ + +#include +#include + +/*** +*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 , 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 +#include + +/*** +*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 , fixed +* copyright. +* 10-02-90 GJF New-style function declarator. +* +*******************************************************************************/ + +#include +#include + +/*** +*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 , 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 +#include +#include + +/*** +*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 , 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 +#include + +/*** +*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 , fixed +* copyright. +* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant +* #include +* 10-02-90 GJF New-style function declarator. +* +*******************************************************************************/ + +#include +#include + +/*** +*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 , fixed +* copyright. +* 10-02-90 GJF New-style function declarator. +* 01-18-91 GJF ANSI naming. +* +*******************************************************************************/ + +#include +#include + +/*** +*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 , 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 +#include + +#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 , fixed +* copyright. +* 08-14-90 SBM Removed now redundant #include +* 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 +#include + +/*** +*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 , fixed +* copyright. +* 08-14-90 SBM Removed now redundant #include +* 10-02-90 GJF New-style function declarator. +* 03-14-94 GJF If string2 is empty, return string1. +* +*******************************************************************************/ + +#include +#include + +/*** +*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 , fixed +* copyright. +* 08-14-90 SBM Removed now redundant #include +* 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 +#include +#ifdef MTHREAD +#include +#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 , 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 +#include +#include +#include +#include +#include /* for INT_MAX */ +#include + +/*** +*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 , 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 +#include +#include +#include +#include +#include +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include +#include +#include +#include + +/*** +*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 +#include + +/*** +*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 +#include +#include + +/*** +*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 +#include +#include +#include +#include +#include + +/*** +*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 +#include +#include +#include +#include + +/*** +*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 +#include + +/*** +*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 +#include +#include +#include +#include +#include +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include +#include +#include +#ifdef _INTL +#include +#include +#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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include + +/*** +*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 +#include +#ifdef MTHREAD +#include +#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 +#include +#include +#include +#include +#include +#include + +/*** +*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 +#include +#include +#include +#include +#include +#include + +/*** +*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 */ +} -- cgit v1.2.3