summaryrefslogtreecommitdiff
path: root/libc/string
diff options
context:
space:
mode:
Diffstat (limited to 'libc/string')
-rw-r--r--libc/string/Makefile37
-rw-r--r--libc/string/config.c93
-rw-r--r--libc/string/strcasecmp.c26
-rw-r--r--libc/string/strcspn.c32
-rw-r--r--libc/string/string.c672
-rw-r--r--libc/string/strncasecmp.c28
-rw-r--r--libc/string/strpbrk.c21
-rw-r--r--libc/string/strsep.c38
-rw-r--r--libc/string/strspn.c44
-rw-r--r--libc/string/strstr.c54
-rw-r--r--libc/string/strtok.c71
11 files changed, 1116 insertions, 0 deletions
diff --git a/libc/string/Makefile b/libc/string/Makefile
new file mode 100644
index 000000000..af288e6e6
--- /dev/null
+++ b/libc/string/Makefile
@@ -0,0 +1,37 @@
+# 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.
+
+LIBC=../libc.a
+
+CC=m68k-pic-coff-gcc
+AR=m68k-pic-coff-ar
+RANLIB=m68k-pic-coff-ranlib
+
+CCFLAGS= -O2 -m68000 -msoft-float -I../include
+
+SSRC=string.c
+SOBJ=strlen.o strcat.o strcpy.o strcmp.o strncat.o strncpy.o strncmp.o \
+ strchr.o strrchr.o strdup.o memcpy.o memccpy.o memchr.o memset.o \
+ memcmp.o memmove.o movedata.o
+
+OBJ=$(SOBJ) strpbrk.o strsep.o strstr.o strtok.o strcspn.o \
+ strspn.o strcasecmp.o strncasecmp.o config.o
+
+CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS)
+
+all: $(LIBC)
+ @$(RM) $(OBJ)
+
+$(LIBC): $(LIBC)($(OBJ))
+
+$(LIBC)($(SOBJ)): $(SSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(AR) $(ARFLAGS) $@ $*.o
+
+transfer:
+ -@rm -f ../include/string.h
+ cp -p string.h ../include/.
+
+clean:
+ rm -f *.o
diff --git a/libc/string/config.c b/libc/string/config.c
new file mode 100644
index 000000000..545207f6a
--- /dev/null
+++ b/libc/string/config.c
@@ -0,0 +1,93 @@
+/* config.c: Config file reader.
+ *
+ * Copyright 1999 D. Jeff Dionne, <jeff@rt-control.com>
+ *
+ * This is free software, under the LGPL V2.0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <cfgfile.h>
+
+/* This is a quick and dirty config file parser. It reads the file once for
+ * each request, there is no cache. Each line must be less than 128bytes.
+ */
+
+static char *args[16];
+static char cfgbuf[128];
+
+static char *
+ws(char **buf)
+{
+ char *b = *buf;
+ char *p;
+
+ /* eat ws */
+ while (*b &&
+ (*b == ' ' ||
+ *b == '\n' ||
+ *b == '\t')) b++;
+ p = b;
+
+ /* find the end */
+ while (*p &&
+ !(*p == ' ' ||
+ *p == '\n' ||
+ *p == '\t')) p++;
+ *p = 0;
+ *buf = p+1;
+ return b;
+}
+
+char **
+cfgread(FILE *fp)
+{
+ char *ebuf;
+ char *p;
+ int i;
+ int j;
+
+ if (!fp) {
+ errno = EIO;
+ return (void *)0;
+ }
+
+ while (fgets(cfgbuf, sizeof(cfgbuf), fp)) {
+
+ /* ship comment lines */
+ if (cfgbuf[0] == '#') continue;
+
+ ebuf = cfgbuf + strlen(cfgbuf);
+
+ p = cfgbuf;
+ for (i = 0; i < 16 && p < ebuf; i++) {
+ args[i] = ws(&p);
+ }
+ args[i] = (void *)0;
+
+ /* return if we found something */
+ if (strlen(args[0])) return args;
+ }
+ return (void *)0;
+}
+
+char **
+cfgfind(FILE *fp, char *var)
+{
+ char **ret;
+ char search[80];
+
+ if (!fp || !var) {
+ errno = EIO;
+ return (void *)0;
+ }
+
+ strncpy(search, var, sizeof(search));
+
+ fseek(fp, 0, SEEK_SET);
+ while (ret = cfgread(fp)) {
+ if (!strcmp(ret[0], search)) return ret;
+ }
+ return (void *)0;
+}
diff --git a/libc/string/strcasecmp.c b/libc/string/strcasecmp.c
new file mode 100644
index 000000000..0e7b0388f
--- /dev/null
+++ b/libc/string/strcasecmp.c
@@ -0,0 +1,26 @@
+/* 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 <ctype.h>
+
+int
+strcasecmp(s, d)
+char *s;
+char *d;
+{
+ for(;;)
+ {
+ if( *s != *d )
+ {
+ if( tolower(*s) != tolower(*d) )
+ return *s - *d;
+ }
+ else if( *s == '\0' ) break;
+ s++; d++;
+ }
+ return 0;
+}
+
diff --git a/libc/string/strcspn.c b/libc/string/strcspn.c
new file mode 100644
index 000000000..619c8be6b
--- /dev/null
+++ b/libc/string/strcspn.c
@@ -0,0 +1,32 @@
+/* strcspn.c */
+
+/* from Schumacher's Atari library, improved */
+
+#include <string.h>
+
+size_t strcspn(string, set)
+register char *string;
+char *set;
+/*
+ * Return the length of the sub-string of <string> that consists
+ * entirely of characters not found in <set>. The terminating '\0'
+ * in <set> is not considered part of the match set. If the first
+ * character if <string> is in <set>, 0 is returned.
+ */
+{
+ register char *setptr;
+ char *start;
+
+ start = string;
+ while (*string)
+ {
+ setptr = set;
+ do
+ if (*setptr == *string)
+ goto break2;
+ while (*setptr++);
+ ++string;
+ }
+break2:
+ return string - start;
+}
diff --git a/libc/string/string.c b/libc/string/string.c
new file mode 100644
index 000000000..664929b22
--- /dev/null
+++ b/libc/string/string.c
@@ -0,0 +1,672 @@
+/* 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 ********************************************/
+
diff --git a/libc/string/strncasecmp.c b/libc/string/strncasecmp.c
new file mode 100644
index 000000000..561f72a76
--- /dev/null
+++ b/libc/string/strncasecmp.c
@@ -0,0 +1,28 @@
+/* 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 <ctype.h>
+
+int
+strncasecmp(s, d, l)
+char *s;
+char *d;
+size_t l;
+{
+ while(l>0)
+ {
+ if( *s != *d )
+ {
+ if( tolower(*s) != tolower(*d) )
+ return *s - *d;
+ }
+ else
+ if( *s == '\0' ) return 0;
+ s++; d++; l--;
+ }
+ return 0;
+}
+
diff --git a/libc/string/strpbrk.c b/libc/string/strpbrk.c
new file mode 100644
index 000000000..3fc27ec70
--- /dev/null
+++ b/libc/string/strpbrk.c
@@ -0,0 +1,21 @@
+/* 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>
+
+/* This uses strchr, strchr should be in assembler */
+
+char *strpbrk(str, set)
+register char *str;
+char *set;
+{
+ while (*str != '\0')
+ if (strchr(set, *str) == 0)
+ ++str;
+ else
+ return (char *) str;
+
+ return 0;
+}
diff --git a/libc/string/strsep.c b/libc/string/strsep.c
new file mode 100644
index 000000000..21aa1bb58
--- /dev/null
+++ b/libc/string/strsep.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+char *
+strsep(pp, delim)
+char **pp;
+char *delim;
+{
+ char *p, *q;
+
+ if (!(p = *pp))
+ return 0;
+ if (q = strpbrk (p, delim))
+ {
+ *pp = q + 1;
+ *q = '\0';
+ }
+ else
+ *pp = 0;
+ return p;
+}
diff --git a/libc/string/strspn.c b/libc/string/strspn.c
new file mode 100644
index 000000000..2094caa86
--- /dev/null
+++ b/libc/string/strspn.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+/* Return the length of the maximum initial segment
+ of S which contains only characters in ACCEPT. */
+size_t
+strspn(s, accept)
+char *s;
+char *accept;
+{
+ register char *p;
+ register char *a;
+ register size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p)
+ {
+ for (a = accept; *a != '\0'; ++a)
+ if (*p == *a)
+ break;
+ if (*a == '\0')
+ return count;
+ else
+ ++count;
+ }
+
+ return count;
+}
diff --git a/libc/string/strstr.c b/libc/string/strstr.c
new file mode 100644
index 000000000..aafcaf967
--- /dev/null
+++ b/libc/string/strstr.c
@@ -0,0 +1,54 @@
+/* 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>
+
+#if 1
+/* We've now got a nice fast strchr and memcmp use them */
+
+char *
+strstr(s1, s2)
+char *s1; char *s2;
+{
+ register int l = strlen(s2);
+ register char * p = s1;
+
+ if( l==0 ) return p;
+
+ while (p = strchr(p, *s2))
+ {
+ if( memcmp(p, s2, l) == 0 )
+ return p;
+ p++;
+ }
+ return (char *) 0;
+}
+
+#else
+/* This is a nice simple self contained strstr,
+ now go and work out why the GNU one is faster :-) */
+
+char *strstr(str1, str2)
+char *str1, *str2;
+{
+ register char *Sptr, *Tptr;
+ int len = strlen(str1) -strlen(str2) + 1;
+
+ if (*str2)
+ for (; len > 0; len--, str1++){
+ if (*str1 != *str2)
+ continue;
+
+ for (Sptr = str1, Tptr = str2; *Tptr != '\0'; Sptr++, Tptr++)
+ if (*Sptr != *Tptr)
+ break;
+
+ if (*Tptr == '\0')
+ return (char*) str1;
+ }
+
+ return (char*)0;
+}
+#endif
diff --git a/libc/string/strtok.c b/libc/string/strtok.c
new file mode 100644
index 000000000..27d8f25b6
--- /dev/null
+++ b/libc/string/strtok.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+
+static char *olds = 0;
+
+/* Parse S into tokens separated by characters in DELIM.
+ If S is NULL, the last string strtok() was called with is
+ used. For example:
+ char s[] = "-abc=-def";
+ x = strtok(s, "-"); // x = "abc"
+ x = strtok(NULL, "=-"); // x = "def"
+ x = strtok(NULL, "="); // x = NULL
+ // s = "abc\0-def\0"
+*/
+char *
+strtok(s, delim)
+register char *s;
+register char *delim;
+{
+ char *token;
+
+ if (s == 0)
+ {
+ if (olds == 0)
+ {
+ return 0;
+ }
+ else
+ s = olds;
+ }
+
+ /* Scan leading delimiters. */
+ s += strspn(s, delim);
+ if (*s == '\0')
+ {
+ olds = 0;
+ return 0;
+ }
+
+ /* Find the end of the token. */
+ token = s;
+ s = strpbrk(token, delim);
+ if (s == 0)
+ /* This token finishes the string. */
+ olds = 0;
+ else
+ {
+ /* Terminate the token and make OLDS point past it. */
+ *s = '\0';
+ olds = s + 1;
+ }
+ return token;
+}