/*
       *  linux/lib/string.c
       *
       *  Copyright (C) 1991, 1992  Linus Torvalds
       */
      
      /*
       * stupid library routines.. The optimized versions should generally be found
       * as inline code in <asm-xx/string.h>
       *
       * These are buggy as well..
       *
       * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
       * -  Added strsep() which will replace strtok() soon (because strsep() is
       *    reentrant and should be faster). Use only strsep() in new code, please.
       */
       
      #include <linux/types.h>
      #include <linux/string.h>
      #include <linux/ctype.h>
      
      #ifndef __HAVE_ARCH_STRNICMP
  23  int strnicmp(const char *s1, const char *s2, size_t len)
      {
      	/* Yes, Virginia, it had better be unsigned */
      	unsigned char c1, c2;
      
      	c1 = 0;	c2 = 0;
  29  	if (len) {
  30  		do {
      			c1 = *s1; c2 = *s2;
      			s1++; s2++;
  33  			if (!c1)
  34  				break;
  35  			if (!c2)
  36  				break;
  37  			if (c1 == c2)
  38  				continue;
      			c1 = tolower(c1);
      			c2 = tolower(c2);
  41  			if (c1 != c2)
  42  				break;
  43  		} while (--len);
      	}
  45  	return (int)c1 - (int)c2;
      }
      #endif
      
      char * ___strtok;
      
      #ifndef __HAVE_ARCH_STRCPY
      char * strcpy(char * dest,const char *src)
      {
      	char *tmp = dest;
      
      	while ((*dest++ = *src++) != '\0')
      		/* nothing */;
      	return tmp;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRNCPY
      char * strncpy(char * dest,const char *src,size_t count)
      {
      	char *tmp = dest;
      
      	while (count-- && (*dest++ = *src++) != '\0')
      		/* nothing */;
      
      	return tmp;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRCAT
      char * strcat(char * dest, const char * src)
      {
      	char *tmp = dest;
      
      	while (*dest)
      		dest++;
      	while ((*dest++ = *src++) != '\0')
      		;
      
      	return tmp;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRNCAT
      char * strncat(char *dest, const char *src, size_t count)
      {
      	char *tmp = dest;
      
      	if (count) {
      		while (*dest)
      			dest++;
      		while ((*dest++ = *src++)) {
      			if (--count == 0) {
      				*dest = '\0';
      				break;
      			}
      		}
      	}
      
      	return tmp;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRCMP
      int strcmp(const char * cs,const char * ct)
      {
      	register signed char __res;
      
      	while (1) {
      		if ((__res = *cs - *ct++) != 0 || !*cs++)
      			break;
      	}
      
      	return __res;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRNCMP
      int strncmp(const char * cs,const char * ct,size_t count)
      {
      	register signed char __res = 0;
      
      	while (count) {
      		if ((__res = *cs - *ct++) != 0 || !*cs++)
      			break;
      		count--;
      	}
      
      	return __res;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRCHR
      char * strchr(const char * s, int c)
      {
      	for(; *s != (char) c; ++s)
      		if (*s == '\0')
      			return NULL;
      	return (char *) s;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRRCHR
      char * strrchr(const char * s, int c)
      {
             const char *p = s + strlen(s);
             do {
                 if (*p == (char)c)
                     return (char *)p;
             } while (--p >= s);
             return NULL;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRLEN
      size_t strlen(const char * s)
      {
      	const char *sc;
      
      	for (sc = s; *sc != '\0'; ++sc)
      		/* nothing */;
      	return sc - s;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRNLEN
      size_t strnlen(const char * s, size_t count)
      {
      	const char *sc;
      
      	for (sc = s; count-- && *sc != '\0'; ++sc)
      		/* nothing */;
      	return sc - s;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRSPN
 182  size_t strspn(const char *s, const char *accept)
      {
      	const char *p;
      	const char *a;
      	size_t count = 0;
      
 188  	for (p = s; *p != '\0'; ++p) {
 189  		for (a = accept; *a != '\0'; ++a) {
 190  			if (*p == *a)
 191  				break;
      		}
 193  		if (*a == '\0')
 194  			return count;
      		++count;
      	}
      
 198  	return count;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRPBRK
 203  char * strpbrk(const char * cs,const char * ct)
      {
      	const char *sc1,*sc2;
      
 207  	for( sc1 = cs; *sc1 != '\0'; ++sc1) {
 208  		for( sc2 = ct; *sc2 != '\0'; ++sc2) {
 209  			if (*sc1 == *sc2)
 210  				return (char *) sc1;
      		}
      	}
 213  	return NULL;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRTOK
 218  char * strtok(char * s,const char * ct)
      {
      	char *sbegin, *send;
      
      	sbegin  = s ? s : ___strtok;
 223  	if (!sbegin) {
 224  		return NULL;
      	}
      	sbegin += strspn(sbegin,ct);
 227  	if (*sbegin == '\0') {
      		___strtok = NULL;
 229  		return( NULL );
      	}
      	send = strpbrk( sbegin, ct);
 232  	if (send && *send != '\0')
      		*send++ = '\0';
      	___strtok = send;
 235  	return (sbegin);
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRSEP
      
 241  char * strsep(char **s, const char * ct)
      {
      	char *sbegin=*s;
 244  	if (!sbegin) 
 245  		return NULL;
      	
      	sbegin += strspn(sbegin,ct);
 248  	if (*sbegin == '\0') 
 249  		return NULL;
      	
      	*s = strpbrk( sbegin, ct);
 252  	if (*s && **s != '\0')
      		*(*s)++ = '\0';
 254  	return (sbegin);
      }
      #endif
      
      #ifndef __HAVE_ARCH_MEMSET
      void * memset(void * s,int c,size_t count)
      {
      	char *xs = (char *) s;
      
      	while (count--)
      		*xs++ = c;
      
      	return s;
      }
      #endif
      
      #ifndef __HAVE_ARCH_BCOPY
 271  char * bcopy(const char * src, char * dest, int count)
      {
      	char *tmp = dest;
      
 275  	while (count--)
      		*tmp++ = *src++;
      
 278  	return dest;
      }
      #endif
      
      #ifndef __HAVE_ARCH_MEMCPY
      void * memcpy(void * dest,const void *src,size_t count)
      {
      	char *tmp = (char *) dest, *s = (char *) src;
      
      	while (count--)
      		*tmp++ = *s++;
      
      	return dest;
      }
      #endif
      
      #ifndef __HAVE_ARCH_MEMMOVE
      void * memmove(void * dest,const void *src,size_t count)
      {
      	char *tmp, *s;
      
      	if (dest <= src) {
      		tmp = (char *) dest;
      		s = (char *) src;
      		while (count--)
      			*tmp++ = *s++;
      		}
      	else {
      		tmp = (char *) dest + count;
      		s = (char *) src + count;
      		while (count--)
      			*--tmp = *--s;
      		}
      
      	return dest;
      }
      #endif
      
      #ifndef __HAVE_ARCH_MEMCMP
 317  int memcmp(const void * cs,const void * ct,size_t count)
      {
      	const unsigned char *su1, *su2;
      	signed char res = 0;
      
 322  	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
 323  		if ((res = *su1 - *su2) != 0)
 324  			break;
 325  	return res;
      }
      #endif
      
      /*
       * find the first occurrence of byte 'c', or 1 past the area if none
       */
      #ifndef __HAVE_ARCH_MEMSCAN
      void * memscan(void * addr, int c, size_t size)
      {
      	unsigned char * p = (unsigned char *) addr;
      
      	while (size) {
      		if (*p == c)
      			return (void *) p;
      		p++;
      		size--;
      	}
        	return (void *) p;
      }
      #endif
      
      #ifndef __HAVE_ARCH_STRSTR
      char * strstr(const char * s1,const char * s2)
      {
      	int l1, l2;
      
      	l2 = strlen(s2);
      	if (!l2)
      		return (char *) s1;
      	l1 = strlen(s1);
      	while (l1 >= l2) {
      		l1--;
      		if (!memcmp(s1,s2,l2))
      			return (char *) s1;
      		s1++;
      	}
      	return NULL;
      }
      #endif
      
      #ifndef __HAVE_ARCH_MEMCHR
      void *memchr(const void *s, int c, size_t n)
      {
      	const unsigned char *p = s;
      	while (n-- != 0) {
              	if ((unsigned char)c == *p++) {
      			return (void *)(p-1);
      		}
      	}
      	return NULL;
      }
      
      #endif