/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
|
/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
|
* This file is part of the Linux-8086 C library and is distributed
|
* This file is part of the Linux-8086 C library and is distributed
|
* under the GNU Library General Public License.
|
* under the GNU Library General Public License.
|
*/
|
*/
|
|
|
#include <string.h>
|
#include <string.h>
|
#include <malloc.h>
|
#include <malloc.h>
|
|
|
#ifdef __AS386_16__
|
#ifdef __AS386_16__
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
#define BCC_AX_ASM /* BCC Assembler that can cope with arg in AX */
|
#define BCC_AX_ASM /* BCC Assembler that can cope with arg in AX */
|
#else
|
#else
|
#define BCC_AX_ASM
|
#define BCC_AX_ASM
|
#define BCC_ASM /* Use 16 bit BCC assembler */
|
#define BCC_ASM /* Use 16 bit BCC assembler */
|
#endif
|
#endif
|
|
|
#define PARANOID /* Include extra code for cld and ES register */
|
#define PARANOID /* Include extra code for cld and ES register */
|
#endif
|
#endif
|
|
|
/* This is a basic string package; it includes the most used functions
|
/* This is a basic string package; it includes the most used functions
|
|
|
strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup
|
strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup
|
memcpy memccpy memchr memset memcmp memmove
|
memcpy memccpy memchr memset memcmp memmove
|
|
|
These functions are in seperate files.
|
These functions are in seperate files.
|
strpbrk.o strsep.o strstr.o strtok.o strcspn.o
|
strpbrk.o strsep.o strstr.o strtok.o strcspn.o
|
strspn.o strcasecmp.o strncasecmp.o
|
strspn.o strcasecmp.o strncasecmp.o
|
*/
|
*/
|
|
|
/********************** Function strlen ************************************/
|
/********************** Function strlen ************************************/
|
|
|
#ifdef L_strlen
|
#ifdef L_strlen
|
size_t strlen(str)
|
size_t strlen(str)
|
const char * str;
|
const char * str;
|
{
|
{
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
#asm
|
#asm
|
#if !__FIRST_ARG_IN_AX__
|
#if !__FIRST_ARG_IN_AX__
|
mov bx,sp
|
mov bx,sp
|
#endif
|
#endif
|
push di
|
push di
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ; Im not sure if this is needed, so just in case.
|
push ds ; Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif ! This is almost the same as memchr, but it can
|
#endif ! This is almost the same as memchr, but it can
|
! stay as a special.
|
! stay as a special.
|
|
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
mov di,ax
|
mov di,ax
|
#else
|
#else
|
mov di,[bx+2]
|
mov di,[bx+2]
|
#endif
|
#endif
|
mov cx,#-1
|
mov cx,#-1
|
xor ax,ax
|
xor ax,ax
|
repne
|
repne
|
scasb
|
scasb
|
not cx
|
not cx
|
dec cx
|
dec cx
|
mov ax,cx
|
mov ax,cx
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop di
|
pop di
|
#endasm
|
#endasm
|
#else
|
#else
|
register char * p =(char *) str;
|
register char * p =(char *) str;
|
while(*p) p++;
|
while(*p) p++;
|
return p-str;
|
return p-str;
|
#endif /* ifdef BCC_AX_ASM */
|
#endif /* ifdef BCC_AX_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strcat ************************************/
|
/********************** Function strcat ************************************/
|
|
|
#ifdef L_strcat
|
#ifdef L_strcat
|
char * strcat(d, s)
|
char * strcat(d, s)
|
char *d;
|
char *d;
|
const char * s;
|
const char * s;
|
{
|
{
|
(void) strcpy(d+strlen(d), s);
|
(void) strcpy(d+strlen(d), s);
|
return d;
|
return d;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strcpy ************************************/
|
/********************** Function strcpy ************************************/
|
|
|
#ifdef L_strcpy
|
#ifdef L_strcpy
|
char * strcpy(d, s)
|
char * strcpy(d, s)
|
char *d;
|
char *d;
|
const char * s;
|
const char * s;
|
{
|
{
|
/* This is probably the quickest on an 8086 but a CPU with a cache will
|
/* This is probably the quickest on an 8086 but a CPU with a cache will
|
* prefer to do this in one pass */
|
* prefer to do this in one pass */
|
return memcpy(d, s, strlen(s)+1);
|
return memcpy(d, s, strlen(s)+1);
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strcmp ************************************/
|
/********************** Function strcmp ************************************/
|
|
|
#ifdef L_strcmp
|
#ifdef L_strcmp
|
int strcmp(d, s)
|
int strcmp(d, s)
|
const char *d;
|
const char *d;
|
const char * s;
|
const char * s;
|
{
|
{
|
/* There are a number of ways to do this and it really does depend on the
|
/* 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
|
types of strings given as to which is better, nevertheless the Glib
|
method is quite reasonable so we'll take that */
|
method is quite reasonable so we'll take that */
|
|
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push di
|
push di
|
push si
|
push si
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ; Im not sure if this is needed, so just in case.
|
push ds ; Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
mov di,ax ; dest
|
mov di,ax ; dest
|
mov si,[bx+2] ; source
|
mov si,[bx+2] ; source
|
#else
|
#else
|
mov di,[bx+2] ; dest
|
mov di,[bx+2] ; dest
|
mov si,[bx+4] ; source
|
mov si,[bx+4] ; source
|
#endif
|
#endif
|
sc_1:
|
sc_1:
|
lodsb
|
lodsb
|
scasb
|
scasb
|
jne sc_2 ; If bytes are diff skip out.
|
jne sc_2 ; If bytes are diff skip out.
|
testb al,al
|
testb al,al
|
jne sc_1 ; If this byte in str1 is nul the strings are equal
|
jne sc_1 ; If this byte in str1 is nul the strings are equal
|
xor ax,ax ; so return zero
|
xor ax,ax ; so return zero
|
jmp sc_3
|
jmp sc_3
|
sc_2:
|
sc_2:
|
sbb ax,ax ; Collect correct val (-1,1).
|
sbb ax,ax ; Collect correct val (-1,1).
|
orb al,#1
|
orb al,#1
|
sc_3:
|
sc_3:
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop si
|
pop si
|
pop di
|
pop di
|
#endasm
|
#endasm
|
#else /* ifdef BCC_AX_ASM */
|
#else /* ifdef BCC_AX_ASM */
|
register char *s1=(char *)d, *s2=(char *)s, c1,c2;
|
register char *s1=(char *)d, *s2=(char *)s, c1,c2;
|
while((c1= *s1++) == (c2= *s2++) && c1 );
|
while((c1= *s1++) == (c2= *s2++) && c1 );
|
return c1 - c2;
|
return c1 - c2;
|
#endif /* ifdef BCC_AX_ASM */
|
#endif /* ifdef BCC_AX_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strncat ************************************/
|
/********************** Function strncat ************************************/
|
|
|
#ifdef L_strncat
|
#ifdef L_strncat
|
char * strncat(d, s, l)
|
char * strncat(d, s, l)
|
char *d;
|
char *d;
|
const char *s;
|
const char *s;
|
size_t l;
|
size_t l;
|
{
|
{
|
register char *s1=d+strlen(d), *s2;
|
register char *s1=d+strlen(d), *s2;
|
|
|
s2 = memchr(s, 0, l);
|
s2 = memchr(s, 0, l);
|
if( s2 )
|
if( s2 )
|
memcpy(s1, s, s2-s+1);
|
memcpy(s1, s, s2-s+1);
|
else
|
else
|
{
|
{
|
memcpy(s1, s, l);
|
memcpy(s1, s, l);
|
s1[l] = '\0';
|
s1[l] = '\0';
|
}
|
}
|
return d;
|
return d;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strncpy ************************************/
|
/********************** Function strncpy ************************************/
|
|
|
#ifdef L_strncpy
|
#ifdef L_strncpy
|
char * strncpy(d, s, l) /* FIXME need the fast version of this */
|
char * strncpy(d, s, l) /* FIXME need the fast version of this */
|
char *d;
|
char *d;
|
const char *s;
|
const char *s;
|
size_t l;
|
size_t l;
|
{
|
{
|
register char *s1=d;
|
register char *s1=d;
|
register const char *s2=s;
|
register const char *s2=s;
|
while(l > 0)
|
while(l > 0)
|
{
|
{
|
l--;
|
l--;
|
if( (*s1++ = *s2++) == '\0')
|
if( (*s1++ = *s2++) == '\0')
|
break;
|
break;
|
}
|
}
|
|
|
/* This _is_ correct strncpy is supposed to zap */
|
/* This _is_ correct strncpy is supposed to zap */
|
for(; l>0; l--) *s1++ = '\0';
|
for(; l>0; l--) *s1++ = '\0';
|
return d;
|
return d;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strncmp ************************************/
|
/********************** Function strncmp ************************************/
|
|
|
#ifdef L_strncmp
|
#ifdef L_strncmp
|
int strncmp(d, s, l)
|
int strncmp(d, s, l)
|
const char *d, *s;
|
const char *d, *s;
|
size_t l;
|
size_t l;
|
{
|
{
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push si
|
push si
|
push di
|
push di
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ! Im not sure if this is needed, so just in case.
|
push ds ! Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
mov si,ax
|
mov si,ax
|
mov di,[bx+2]
|
mov di,[bx+2]
|
mov cx,[bx+4]
|
mov cx,[bx+4]
|
#else
|
#else
|
mov si,[bx+2] ! Fetch
|
mov si,[bx+2] ! Fetch
|
mov di,[bx+4]
|
mov di,[bx+4]
|
mov cx,[bx+6]
|
mov cx,[bx+6]
|
#endif
|
#endif
|
|
|
inc cx
|
inc cx
|
lp1:
|
lp1:
|
dec cx
|
dec cx
|
je lp2
|
je lp2
|
lodsb
|
lodsb
|
scasb
|
scasb
|
jne lp3
|
jne lp3
|
testb al,al
|
testb al,al
|
jne lp1
|
jne lp1
|
lp2:
|
lp2:
|
xor ax,ax
|
xor ax,ax
|
jmp lp4
|
jmp lp4
|
lp3:
|
lp3:
|
sbb ax,ax
|
sbb ax,ax
|
or al,#1
|
or al,#1
|
lp4:
|
lp4:
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop di
|
pop di
|
pop si
|
pop si
|
#endasm
|
#endasm
|
#else
|
#else
|
register char c1=0, c2=0;
|
register char c1=0, c2=0;
|
while(l-- >0)
|
while(l-- >0)
|
if( (c1= *d++) != (c2= *s++) || c1 == '\0' )
|
if( (c1= *d++) != (c2= *s++) || c1 == '\0' )
|
break;
|
break;
|
return c1-c2;
|
return c1-c2;
|
#endif
|
#endif
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strchr ************************************/
|
/********************** Function strchr ************************************/
|
|
|
#ifdef L_strchr
|
#ifdef L_strchr
|
char *
|
char *
|
strchr(s, c)
|
strchr(s, c)
|
char * s;
|
char * s;
|
int c;
|
int c;
|
{
|
{
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push si
|
push si
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
mov bx,[bx+2]
|
mov bx,[bx+2]
|
mov si,ax
|
mov si,ax
|
#else
|
#else
|
mov si,[bx+2]
|
mov si,[bx+2]
|
mov bx,[bx+4]
|
mov bx,[bx+4]
|
#endif
|
#endif
|
xor ax,ax
|
xor ax,ax
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
cld
|
cld
|
#endif
|
#endif
|
|
|
in_loop:
|
in_loop:
|
lodsb
|
lodsb
|
cmp al,bl
|
cmp al,bl
|
jz got_it
|
jz got_it
|
or al,al
|
or al,al
|
jnz in_loop
|
jnz in_loop
|
pop si
|
pop si
|
ret
|
ret
|
got_it:
|
got_it:
|
lea ax,[si-1]
|
lea ax,[si-1]
|
pop si
|
pop si
|
|
|
#endasm
|
#endasm
|
#else /* ifdef BCC_AX_ASM */
|
#else /* ifdef BCC_AX_ASM */
|
register char ch;
|
register char ch;
|
for(;;)
|
for(;;)
|
{
|
{
|
if( (ch= *s) == c ) return s;
|
if( (ch= *s) == c ) return s;
|
if( ch == 0 ) return 0;
|
if( ch == 0 ) return 0;
|
s++;
|
s++;
|
}
|
}
|
#endif /* ifdef BCC_AX_ASM */
|
#endif /* ifdef BCC_AX_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strrchr ************************************/
|
/********************** Function strrchr ************************************/
|
|
|
#ifdef L_strrchr
|
#ifdef L_strrchr
|
char * strrchr(s, c)
|
char * strrchr(s, c)
|
char * s;
|
char * s;
|
int c;
|
int c;
|
{
|
{
|
register char * prev = 0;
|
register char * prev = 0;
|
register char * p = s;
|
register char * p = s;
|
/* For null it's just like strlen */
|
/* For null it's just like strlen */
|
if( c == '\0' ) return p+strlen(p);
|
if( c == '\0' ) return p+strlen(p);
|
|
|
/* everything else just step along the string. */
|
/* everything else just step along the string. */
|
while( (p=strchr(p, c)) != 0 )
|
while( (p=strchr(p, c)) != 0 )
|
{
|
{
|
prev = p; p++;
|
prev = p; p++;
|
}
|
}
|
return prev;
|
return prev;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function strdup ************************************/
|
/********************** Function strdup ************************************/
|
|
|
#ifdef L_strdup
|
#ifdef L_strdup
|
char * strdup(s)
|
char * strdup(s)
|
const char * s;
|
const char * s;
|
{
|
{
|
register size_t len;
|
register size_t len;
|
register char * p;
|
register char * p;
|
|
|
len = strlen(s)+1;
|
len = strlen(s)+1;
|
p = (char *) malloc(len);
|
p = (char *) malloc(len);
|
if(p) memcpy(p, s, len); /* Faster than strcpy */
|
if(p) memcpy(p, s, len); /* Faster than strcpy */
|
return p;
|
return p;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function memcpy ************************************/
|
/********************** Function memcpy ************************************/
|
|
|
#ifdef L_memcpy
|
#ifdef L_memcpy
|
void *
|
void *
|
memcpy(d, s, l)
|
memcpy(d, s, l)
|
void *d;
|
void *d;
|
const void *s;
|
const void *s;
|
size_t l;
|
size_t l;
|
{
|
{
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push di
|
push di
|
push si
|
push si
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ; Im not sure if this is needed, so just in case.
|
push ds ; Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
mov di,ax ; dest
|
mov di,ax ; dest
|
mov si,[bx+2] ; source
|
mov si,[bx+2] ; source
|
mov cx,[bx+4] ; count
|
mov cx,[bx+4] ; count
|
#else
|
#else
|
mov di,[bx+2] ; dest
|
mov di,[bx+2] ; dest
|
mov si,[bx+4] ; source
|
mov si,[bx+4] ; source
|
mov cx,[bx+6] ; count
|
mov cx,[bx+6] ; count
|
|
|
mov ax,di
|
mov ax,di
|
#endif
|
#endif
|
; If di is odd mov 1 byte before doing word move
|
; If di is odd mov 1 byte before doing word move
|
; this will speed slightly but
|
; this will speed slightly but
|
; NB 8086 has no problem with mis-aligned access.
|
; NB 8086 has no problem with mis-aligned access.
|
|
|
shr cx,#1 ; Do this faster by doing a mov word
|
shr cx,#1 ; Do this faster by doing a mov word
|
rep
|
rep
|
movsw
|
movsw
|
adc cx,cx ; Retrieve the leftover 1 bit from cflag.
|
adc cx,cx ; Retrieve the leftover 1 bit from cflag.
|
rep
|
rep
|
movsb
|
movsb
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop si
|
pop si
|
pop di
|
pop di
|
#endasm
|
#endasm
|
#else /* ifdef BCC_AX_ASM */
|
#else /* ifdef BCC_AX_ASM */
|
register char *s1=d, *s2=(char *)s;
|
register char *s1=d, *s2=(char *)s;
|
for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
|
for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
|
return d;
|
return d;
|
#endif /* ifdef BCC_AX_ASM */
|
#endif /* ifdef BCC_AX_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function memccpy ************************************/
|
/********************** Function memccpy ************************************/
|
|
|
#ifdef L_memccpy
|
#ifdef L_memccpy
|
void * memccpy(d, s, c, l) /* Do we need a fast one ? */
|
void * memccpy(d, s, c, l) /* Do we need a fast one ? */
|
void *s, *d;
|
void *s, *d;
|
int c;
|
int c;
|
size_t l;
|
size_t l;
|
{
|
{
|
register char *s1=d, *s2=s;
|
register char *s1=d, *s2=s;
|
while(l-- > 0)
|
while(l-- > 0)
|
if((*s1++ = *s2++) == c )
|
if((*s1++ = *s2++) == c )
|
return s1;
|
return s1;
|
return 0;
|
return 0;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function memchr ************************************/
|
/********************** Function memchr ************************************/
|
|
|
#ifdef L_memchr
|
#ifdef L_memchr
|
void * memchr(str, c, l)
|
void * memchr(str, c, l)
|
const void * str;
|
const void * str;
|
int c;
|
int c;
|
size_t l;
|
size_t l;
|
{
|
{
|
#ifdef BCC_ASM
|
#ifdef BCC_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push di
|
push di
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ; Im not sure if this is needed, so just in case.
|
push ds ; Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
mov di,[bx+2]
|
mov di,[bx+2]
|
mov ax,[bx+4]
|
mov ax,[bx+4]
|
mov cx,[bx+6]
|
mov cx,[bx+6]
|
test cx,cx
|
test cx,cx
|
je is_z ! Zero length, do not find.
|
je is_z ! Zero length, do not find.
|
|
|
repne ! Scan
|
repne ! Scan
|
scasb
|
scasb
|
jne is_z ! Not found, ret zero
|
jne is_z ! Not found, ret zero
|
dec di ! Adjust ptr
|
dec di ! Adjust ptr
|
mov ax,di ! return
|
mov ax,di ! return
|
jmp xit
|
jmp xit
|
is_z:
|
is_z:
|
xor ax,ax
|
xor ax,ax
|
xit:
|
xit:
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop di
|
pop di
|
#endasm
|
#endasm
|
#else /* ifdef BCC_ASM */
|
#else /* ifdef BCC_ASM */
|
register char *p=(char *)str;
|
register char *p=(char *)str;
|
while(l-- > 0)
|
while(l-- > 0)
|
{
|
{
|
if(*p == c) return p;
|
if(*p == c) return p;
|
p++;
|
p++;
|
}
|
}
|
return 0;
|
return 0;
|
#endif /* ifdef BCC_ASM */
|
#endif /* ifdef BCC_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function memset ************************************/
|
/********************** Function memset ************************************/
|
|
|
#ifdef L_memset
|
#ifdef L_memset
|
void * memset(str, c, l)
|
void * memset(str, c, l)
|
void * str;
|
void * str;
|
int c;
|
int c;
|
size_t l;
|
size_t l;
|
{
|
{
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push di
|
push di
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ; Im not sure if this is needed, so just in case.
|
push ds ; Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
#if __FIRST_ARG_IN_AX__
|
#if __FIRST_ARG_IN_AX__
|
mov di,ax ; Fetch
|
mov di,ax ; Fetch
|
mov ax,[bx+2]
|
mov ax,[bx+2]
|
mov cx,[bx+4]
|
mov cx,[bx+4]
|
#else
|
#else
|
mov di,[bx+2] ; Fetch
|
mov di,[bx+2] ; Fetch
|
mov ax,[bx+4]
|
mov ax,[bx+4]
|
mov cx,[bx+6]
|
mov cx,[bx+6]
|
#endif
|
#endif
|
|
|
; How much difference does this alignment make ?
|
; How much difference does this alignment make ?
|
; I don`t think it`s significant cause most will already be aligned.
|
; I don`t think it`s significant cause most will already be aligned.
|
|
|
; test cx,cx ; Zero size - skip
|
; test cx,cx ; Zero size - skip
|
; je xit
|
; je xit
|
;
|
;
|
; test di,#1 ; Line it up
|
; test di,#1 ; Line it up
|
; je s_1
|
; je s_1
|
; stosb
|
; stosb
|
; dec cx
|
; dec cx
|
;s_1:
|
;s_1:
|
|
|
mov ah,al ; Replicate byte
|
mov ah,al ; Replicate byte
|
shr cx,#1 ; Do this faster by doing a sto word
|
shr cx,#1 ; Do this faster by doing a sto word
|
rep ; Bzzzzz ...
|
rep ; Bzzzzz ...
|
stosw
|
stosw
|
adc cx,cx ; Retrieve the leftover 1 bit from cflag.
|
adc cx,cx ; Retrieve the leftover 1 bit from cflag.
|
|
|
rep ; ... z
|
rep ; ... z
|
stosb
|
stosb
|
|
|
xit:
|
xit:
|
mov ax,[bx+2]
|
mov ax,[bx+2]
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop di
|
pop di
|
#endasm
|
#endasm
|
#else /* ifdef BCC_AX_ASM */
|
#else /* ifdef BCC_AX_ASM */
|
register char *s1=str;
|
register char *s1=str;
|
while(l-->0) *s1++ = c;
|
while(l-->0) *s1++ = c;
|
return str;
|
return str;
|
#endif /* ifdef BCC_AX_ASM */
|
#endif /* ifdef BCC_AX_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function memcmp ************************************/
|
/********************** Function memcmp ************************************/
|
|
|
#ifdef L_memcmp
|
#ifdef L_memcmp
|
int memcmp(s, d, l)
|
int memcmp(s, d, l)
|
const void *s, *d;
|
const void *s, *d;
|
size_t l;
|
size_t l;
|
{
|
{
|
#ifdef BCC_ASM
|
#ifdef BCC_ASM
|
#asm
|
#asm
|
mov bx,sp
|
mov bx,sp
|
push di
|
push di
|
push si
|
push si
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
push ds ! Im not sure if this is needed, so just in case.
|
push ds ! Im not sure if this is needed, so just in case.
|
pop es
|
pop es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
mov si,[bx+2] ! Fetch
|
mov si,[bx+2] ! Fetch
|
mov di,[bx+4]
|
mov di,[bx+4]
|
mov cx,[bx+6]
|
mov cx,[bx+6]
|
xor ax,ax
|
xor ax,ax
|
|
|
rep ! Bzzzzz
|
rep ! Bzzzzz
|
cmpsb
|
cmpsb
|
je xit ! All the same!
|
je xit ! All the same!
|
sbb ax,ax
|
sbb ax,ax
|
sbb ax,#-1 ! choose +/-1
|
sbb ax,#-1 ! choose +/-1
|
xit:
|
xit:
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop si
|
pop si
|
pop di
|
pop di
|
#endasm
|
#endasm
|
#else /* ifdef BCC_ASM */
|
#else /* ifdef BCC_ASM */
|
register const char *s1=d, *s2=s;
|
register const char *s1=d, *s2=s;
|
register char c1=0, c2=0;
|
register char c1=0, c2=0;
|
while(l-- > 0)
|
while(l-- > 0)
|
if( (c1= *s1++) != (c2= *s2++) )
|
if( (c1= *s1++) != (c2= *s2++) )
|
break;
|
break;
|
return c1-c2;
|
return c1-c2;
|
#endif /* ifdef BCC_ASM */
|
#endif /* ifdef BCC_ASM */
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function memmove ************************************/
|
/********************** Function memmove ************************************/
|
|
|
#ifdef L_memmove
|
#ifdef L_memmove
|
void *
|
void *
|
memmove(d, s, l)
|
memmove(d, s, l)
|
void *d, *s;
|
void *d, *s;
|
size_t l;
|
size_t l;
|
{
|
{
|
register char *s1=d, *s2=s;
|
register char *s1=d, *s2=s;
|
/* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
|
/* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
|
if( s1-s2 >= l ) return memcpy(d,s,l);
|
if( s1-s2 >= l ) return memcpy(d,s,l);
|
|
|
/* This reverse copy only used if we absolutly have to */
|
/* This reverse copy only used if we absolutly have to */
|
s1+=l; s2+=l;
|
s1+=l; s2+=l;
|
while(l-- >0)
|
while(l-- >0)
|
*(--s1) = *(--s2);
|
*(--s1) = *(--s2);
|
return d;
|
return d;
|
}
|
}
|
#endif
|
#endif
|
|
|
/********************** Function movedata ***********************************/
|
/********************** Function movedata ***********************************/
|
|
|
#ifdef L_movedata
|
#ifdef L_movedata
|
|
|
/* NB There isn't any C version of this function ... */
|
/* NB There isn't any C version of this function ... */
|
|
|
#ifdef BCC_AX_ASM
|
#ifdef BCC_AX_ASM
|
void
|
void
|
__movedata(srcseg, srcoff, destseg, destoff, len)
|
__movedata(srcseg, srcoff, destseg, destoff, len)
|
unsigned int srcseg, srcoff, destseg, destoff, len;
|
unsigned int srcseg, srcoff, destseg, destoff, len;
|
{
|
{
|
#asm
|
#asm
|
push bp
|
push bp
|
mov bp,sp
|
mov bp,sp
|
push si
|
push si
|
push di
|
push di
|
push ds
|
push ds
|
#ifdef PARANOID
|
#ifdef PARANOID
|
push es
|
push es
|
cld
|
cld
|
#endif
|
#endif
|
|
|
! sei ! Are we _really_ paranoid ?
|
! sei ! Are we _really_ paranoid ?
|
|
|
#if !__FIRST_ARG_IN_AX__
|
#if !__FIRST_ARG_IN_AX__
|
mov ds,[bp+4] ! Careful, [bp+xx] is SS based.
|
mov ds,[bp+4] ! Careful, [bp+xx] is SS based.
|
mov si,[bp+6]
|
mov si,[bp+6]
|
mov es,[bp+8]
|
mov es,[bp+8]
|
mov di,[bp+10]
|
mov di,[bp+10]
|
mov cx,[bp+12]
|
mov cx,[bp+12]
|
#else
|
#else
|
mov ds,ax
|
mov ds,ax
|
mov si,[bp+4]
|
mov si,[bp+4]
|
mov es,[bp+6]
|
mov es,[bp+6]
|
mov di,[bp+8]
|
mov di,[bp+8]
|
mov cx,[bp+10]
|
mov cx,[bp+10]
|
#endif
|
#endif
|
rep
|
rep
|
movsb
|
movsb
|
|
|
! cli ! Are we _really_ paranoid ?
|
! cli ! Are we _really_ paranoid ?
|
|
|
#ifdef PARANOID
|
#ifdef PARANOID
|
pop es
|
pop es
|
#endif
|
#endif
|
pop ds
|
pop ds
|
pop di
|
pop di
|
pop si
|
pop si
|
pop bp
|
pop bp
|
#endasm
|
#endasm
|
}
|
}
|
#endif
|
#endif
|
|
|
#endif
|
#endif
|
|
|
/********************** THE END ********************************************/
|
/********************** THE END ********************************************/
|
|
|
|
|