123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- /* 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
- * under the GNU Library General Public License.
- */
- #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
- These functions are in seperate files.
- strpbrk.o strsep.o strstr.o strtok.o strcspn.o
- strspn.o strcasecmp.o strncasecmp.o
- */
- /********************** Function strlen ************************************/
- #ifdef L_strlen
- size_t strlen(str)
- 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;
- {
- (void) strcpy(d+strlen(d), s);
- return d;
- }
- #endif
- /********************** Function strcpy ************************************/
- #ifdef L_strcpy
- char * strcpy(d, s)
- 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 */
- return memcpy(d, s, strlen(s)+1);
- }
- #endif
- /********************** Function strcmp ************************************/
- #ifdef L_strcmp
- int strcmp(d, s)
- 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 */
- }
- #endif
- /********************** Function strncat ************************************/
- #ifdef L_strncat
- char * strncat(d, s, l)
- char *d;
- const char *s;
- size_t l;
- {
- register char *s1=d+strlen(d), *s2;
-
- s2 = memchr(s, 0, l);
- if( s2 )
- memcpy(s1, s, s2-s+1);
- else
- {
- memcpy(s1, s, l);
- s1[l] = '\0';
- }
- return d;
- }
- #endif
- /********************** 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;
- {
- 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;
- }
- #endif
- /********************** Function strncmp ************************************/
- #ifdef L_strncmp
- int strncmp(d, s, l)
- const char *d, *s;
- size_t l;
- {
- #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
- }
- #endif
- /********************** Function strchr ************************************/
- #ifdef L_strchr
- char *
- strchr(s, c)
- 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(;;)
- {
- if( (ch= *s) == c ) return s;
- if( ch == 0 ) return 0;
- s++;
- }
- #endif /* ifdef BCC_AX_ASM */
- }
- #endif
- /********************** Function strrchr ************************************/
- #ifdef L_strrchr
- char * strrchr(s, c)
- char * s;
- int c;
- {
- register char * prev = 0;
- register char * p = s;
- /* For null it's just like strlen */
- if( c == '\0' ) return p+strlen(p);
- /* everything else just step along the string. */
- while( (p=strchr(p, c)) != 0 )
- {
- prev = p; p++;
- }
- return prev;
- }
- #endif
- /********************** Function strdup ************************************/
- #ifdef L_strdup
- char * strdup(s)
- const char * s;
- {
- register size_t len;
- register char * p;
- len = strlen(s)+1;
- p = (char *) malloc(len);
- if(p) memcpy(p, s, len); /* Faster than strcpy */
- return p;
- }
- #endif
- /********************** Function memcpy ************************************/
- #ifdef L_memcpy
- void *
- memcpy(d, s, l)
- 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
- /********************** Function memccpy ************************************/
- #ifdef L_memccpy
- void * memccpy(d, s, c, l) /* Do we need a fast one ? */
- void *s, *d;
- int c;
- size_t l;
- {
- register char *s1=d, *s2=s;
- while(l-- > 0)
- if((*s1++ = *s2++) == c )
- return s1;
- return 0;
- }
- #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
- void * memset(str, c, l)
- 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
- /********************** Function memmove ************************************/
- #ifdef L_memmove
- void *
- memmove(d, s, l)
- void *d, *s;
- size_t l;
- {
- register char *s1=d, *s2=s;
- /* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
- if( s1-s2 >= l ) return memcpy(d,s,l);
- /* This reverse copy only used if we absolutly have to */
- s1+=l; s2+=l;
- while(l-- >0)
- *(--s1) = *(--s2);
- return d;
- }
- #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 ********************************************/
|