diff options
author | Eric Andersen <andersen@codepoet.org> | 2000-10-05 05:10:27 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2000-10-05 05:10:27 +0000 |
commit | 8187b0ccda766ff2000e954f01ba918faefc05d2 (patch) | |
tree | 7dfa36055a9689a672c14185d37a7396e5746b4b /libc/string/string.c | |
parent | 6ba17041381afeb8c1274cce4c6ffebda0253328 (diff) |
Major update to string handling. strcmp and friends were horribly
broken. They now test out as working properly.
-Erik
Diffstat (limited to 'libc/string/string.c')
-rw-r--r-- | libc/string/string.c | 580 |
1 files changed, 116 insertions, 464 deletions
diff --git a/libc/string/string.c b/libc/string/string.c index 0025cec2b..1777ce03c 100644 --- a/libc/string/string.c +++ b/libc/string/string.c @@ -6,21 +6,10 @@ #include <string.h> #include <malloc.h> -#ifdef __AS386_16__ -#if __FIRST_ARG_IN_AX__ -#define BCC_AX_ASM /* BCC Assembler that can cope with arg in AX */ -#else -#define BCC_AX_ASM -#define BCC_ASM /* Use 16 bit BCC assembler */ -#endif - -#define PARANOID /* Include extra code for cld and ES register */ -#endif - /* This is a basic string package; it includes the most used functions strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup - memcpy memccpy memchr memset memcmp memmove + memcpy memccpy memset memmove These functions are in seperate files. strpbrk.o strsep.o strstr.o strtok.o strcspn.o @@ -30,56 +19,18 @@ /********************** Function strlen ************************************/ #ifdef L_strlen -size_t strlen(str) -const char * str; +size_t strlen(const char * str) { -#ifdef BCC_AX_ASM -#asm -#if !__FIRST_ARG_IN_AX__ - mov bx,sp -#endif - push di - -#ifdef PARANOID - push es - push ds ; Im not sure if this is needed, so just in case. - pop es - cld -#endif ! This is almost the same as memchr, but it can - ! stay as a special. - -#if __FIRST_ARG_IN_AX__ - mov di,ax -#else - mov di,[bx+2] -#endif - mov cx,#-1 - xor ax,ax - repne - scasb - not cx - dec cx - mov ax,cx - -#ifdef PARANOID - pop es -#endif - pop di -#endasm -#else register char * p =(char *) str; while(*p) p++; return p-str; -#endif /* ifdef BCC_AX_ASM */ } #endif /********************** Function strcat ************************************/ #ifdef L_strcat -char * strcat(d, s) -char *d; -const char * s; +char * strcat(char *d, const char * s) { (void) strcpy(d+strlen(d), s); return d; @@ -89,9 +40,7 @@ const char * s; /********************** Function strcpy ************************************/ #ifdef L_strcpy -char * strcpy(d, s) -char *d; -const char * s; +char * strcpy( char *d, const char * s) { /* This is probably the quickest on an 8086 but a CPU with a cache will * prefer to do this in one pass */ @@ -102,68 +51,29 @@ const char * s; /********************** Function strcmp ************************************/ #ifdef L_strcmp -int strcmp(d, s) -const char *d; -const char * s; +int strcmp(const char *d, const char * s) { - /* There are a number of ways to do this and it really does depend on the - types of strings given as to which is better, nevertheless the Glib - method is quite reasonable so we'll take that */ - -#ifdef BCC_AX_ASM -#asm - mov bx,sp - push di - push si - -#ifdef PARANOID - push es - push ds ; Im not sure if this is needed, so just in case. - pop es - cld -#endif - -#if __FIRST_ARG_IN_AX__ - mov di,ax ; dest - mov si,[bx+2] ; source -#else - mov di,[bx+2] ; dest - mov si,[bx+4] ; source -#endif -sc_1: - lodsb - scasb - jne sc_2 ; If bytes are diff skip out. - testb al,al - jne sc_1 ; If this byte in str1 is nul the strings are equal - xor ax,ax ; so return zero - jmp sc_3 -sc_2: - sbb ax,ax ; Collect correct val (-1,1). - orb al,#1 -sc_3: - -#ifdef PARANOID - pop es -#endif - pop si - pop di -#endasm -#else /* ifdef BCC_AX_ASM */ - register char *s1=(char *)d, *s2=(char *)s, c1,c2; - while((c1= *s1++) == (c2= *s2++) && c1 ); - return c1 - c2; -#endif /* ifdef BCC_AX_ASM */ + register const unsigned char *s1 = (const unsigned char *) d; + register const unsigned char *s2 = (const unsigned char *) s; + unsigned register char c1, c2; + + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; } #endif /********************** Function strncat ************************************/ #ifdef L_strncat -char * strncat(d, s, l) -char *d; -const char *s; -size_t l; +char * strncat( char *d, const char *s, size_t l) { register char *s1=d+strlen(d), *s2; @@ -182,86 +92,110 @@ size_t l; /********************** Function strncpy ************************************/ #ifdef L_strncpy -char * strncpy(d, s, l) /* FIXME need the fast version of this */ -char *d; -const char *s; -size_t l; +char * strncpy ( char *s1, const char *s2, size_t n) { - register char *s1=d; - register const char *s2=s; - while(l > 0) - { - l--; - if( (*s1++ = *s2++) == '\0') - break; - } - - /* This _is_ correct strncpy is supposed to zap */ - for(; l>0; l--) *s1++ = '\0'; - return d; + register char c; + char *s = s1; + + --s1; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n = n - (s1 - s) - 1; + if (n == 0) + return s; + goto zero_fill; + } + +last_chars: + n &= 3; + if (n == 0) + return s; + + do + { + c = *s2++; + *++s1 = c; + if (--n == 0) + return s; + } + while (c != '\0'); + +zero_fill: + do + *++s1 = '\0'; + while (--n > 0); + + return s; } #endif /********************** Function strncmp ************************************/ #ifdef L_strncmp -int strncmp(d, s, l) -const char *d, *s; -size_t l; +int strncmp (const char *s1, const char *s2, size_t n) { -#ifdef BCC_AX_ASM -#asm - mov bx,sp - push si - push di - -#ifdef PARANOID - push es - push ds ! Im not sure if this is needed, so just in case. - pop es - cld -#endif - -#if __FIRST_ARG_IN_AX__ - mov si,ax - mov di,[bx+2] - mov cx,[bx+4] -#else - mov si,[bx+2] ! Fetch - mov di,[bx+4] - mov cx,[bx+6] -#endif - - inc cx -lp1: - dec cx - je lp2 - lodsb - scasb - jne lp3 - testb al,al - jne lp1 -lp2: - xor ax,ax - jmp lp4 -lp3: - sbb ax,ax - or al,#1 -lp4: - -#ifdef PARANOID - pop es -#endif - pop di - pop si -#endasm -#else - register char c1=0, c2=0; - while(l-- >0) - if( (c1= *d++) != (c2= *s++) || c1 == '\0' ) - break; - return c1-c2; -#endif + unsigned register char c1 = '\0'; + unsigned register char c2 = '\0'; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + + return c1 - c2; } #endif @@ -273,37 +207,6 @@ strchr(s, c) const char * s; int c; { -#ifdef BCC_AX_ASM -#asm - mov bx,sp - push si -#if __FIRST_ARG_IN_AX__ - mov bx,[bx+2] - mov si,ax -#else - mov si,[bx+2] - mov bx,[bx+4] -#endif - xor ax,ax - -#ifdef PARANOID - cld -#endif - -in_loop: - lodsb - cmp al,bl - jz got_it - or al,al - jnz in_loop - pop si - ret -got_it: - lea ax,[si-1] - pop si - -#endasm -#else /* ifdef BCC_AX_ASM */ register char ch; for(;;) { @@ -311,7 +214,6 @@ got_it: if( ch == 0 ) return 0; s++; } -#endif /* ifdef BCC_AX_ASM */ } #endif @@ -361,52 +263,9 @@ void *d; const void *s; size_t l; { -#ifdef BCC_AX_ASM -#asm - mov bx,sp - push di - push si - -#ifdef PARANOID - push es - push ds ; Im not sure if this is needed, so just in case. - pop es - cld -#endif - -#if __FIRST_ARG_IN_AX__ - mov di,ax ; dest - mov si,[bx+2] ; source - mov cx,[bx+4] ; count -#else - mov di,[bx+2] ; dest - mov si,[bx+4] ; source - mov cx,[bx+6] ; count - - mov ax,di -#endif - ; If di is odd mov 1 byte before doing word move - ; this will speed slightly but - ; NB 8086 has no problem with mis-aligned access. - - shr cx,#1 ; Do this faster by doing a mov word - rep - movsw - adc cx,cx ; Retrieve the leftover 1 bit from cflag. - rep - movsb - -#ifdef PARANOID - pop es -#endif - pop si - pop di -#endasm -#else /* ifdef BCC_AX_ASM */ register char *s1=d, *s2=(char *)s; for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++); return d; -#endif /* ifdef BCC_AX_ASM */ } #endif @@ -427,59 +286,6 @@ size_t l; } #endif -/********************** Function memchr ************************************/ - -#ifdef L_memchr -void * memchr(str, c, l) -const void * str; -int c; -size_t l; -{ -#ifdef BCC_ASM -#asm - mov bx,sp - push di - -#ifdef PARANOID - push es - push ds ; Im not sure if this is needed, so just in case. - pop es - cld -#endif - - mov di,[bx+2] - mov ax,[bx+4] - mov cx,[bx+6] - test cx,cx - je is_z ! Zero length, do not find. - - repne ! Scan - scasb - jne is_z ! Not found, ret zero - dec di ! Adjust ptr - mov ax,di ! return - jmp xit -is_z: - xor ax,ax -xit: - -#ifdef PARANOID - pop es -#endif - pop di -#endasm -#else /* ifdef BCC_ASM */ - register char *p=(char *)str; - while(l-- > 0) - { - if(*p == c) return p; - p++; - } - return 0; -#endif /* ifdef BCC_ASM */ -} -#endif - /********************** Function memset ************************************/ #ifdef L_memset @@ -488,109 +294,9 @@ void * str; int c; size_t l; { -#ifdef BCC_AX_ASM -#asm - mov bx,sp - push di - -#ifdef PARANOID - push es - push ds ; Im not sure if this is needed, so just in case. - pop es - cld -#endif - -#if __FIRST_ARG_IN_AX__ - mov di,ax ; Fetch - mov ax,[bx+2] - mov cx,[bx+4] -#else - mov di,[bx+2] ; Fetch - mov ax,[bx+4] - mov cx,[bx+6] -#endif - -; How much difference does this alignment make ? -; I don`t think it`s significant cause most will already be aligned. - -; test cx,cx ; Zero size - skip -; je xit -; -; test di,#1 ; Line it up -; je s_1 -; stosb -; dec cx -;s_1: - - mov ah,al ; Replicate byte - shr cx,#1 ; Do this faster by doing a sto word - rep ; Bzzzzz ... - stosw - adc cx,cx ; Retrieve the leftover 1 bit from cflag. - - rep ; ... z - stosb - -xit: - mov ax,[bx+2] -#ifdef PARANOID - pop es -#endif - pop di -#endasm -#else /* ifdef BCC_AX_ASM */ register char *s1=str; while(l-->0) *s1++ = c; return str; -#endif /* ifdef BCC_AX_ASM */ -} -#endif - -/********************** Function memcmp ************************************/ - -#ifdef L_memcmp -int memcmp(s, d, l) -const void *s, *d; -size_t l; -{ -#ifdef BCC_ASM -#asm - mov bx,sp - push di - push si - -#ifdef PARANOID - push es - push ds ! Im not sure if this is needed, so just in case. - pop es - cld -#endif - - mov si,[bx+2] ! Fetch - mov di,[bx+4] - mov cx,[bx+6] - xor ax,ax - - rep ! Bzzzzz - cmpsb - je xit ! All the same! - sbb ax,ax - sbb ax,#-1 ! choose +/-1 -xit: -#ifdef PARANOID - pop es -#endif - pop si - pop di -#endasm -#else /* ifdef BCC_ASM */ - register const char *s1=d, *s2=s; - register char c1=0, c2=0; - while(l-- > 0) - if( (c1= *s1++) != (c2= *s2++) ) - break; - return c1-c2; -#endif /* ifdef BCC_ASM */ } #endif @@ -615,60 +321,6 @@ size_t l; } #endif -/********************** Function movedata ***********************************/ - -#ifdef L_movedata - -/* NB There isn't any C version of this function ... */ - -#ifdef BCC_AX_ASM -void -__movedata(srcseg, srcoff, destseg, destoff, len) -unsigned int srcseg, srcoff, destseg, destoff, len; -{ -#asm - push bp - mov bp,sp - push si - push di - push ds -#ifdef PARANOID - push es - cld -#endif - - ! sei ! Are we _really_ paranoid ? - -#if !__FIRST_ARG_IN_AX__ - mov ds,[bp+4] ! Careful, [bp+xx] is SS based. - mov si,[bp+6] - mov es,[bp+8] - mov di,[bp+10] - mov cx,[bp+12] -#else - mov ds,ax - mov si,[bp+4] - mov es,[bp+6] - mov di,[bp+8] - mov cx,[bp+10] -#endif - rep - movsb - - ! cli ! Are we _really_ paranoid ? - -#ifdef PARANOID - pop es -#endif - pop ds - pop di - pop si - pop bp -#endasm -} -#endif - -#endif /********************** THE END ********************************************/ |