I suggest using something like Gnu's autoconf package to test for the existance of various functions before compiling and define symbols like HAVE_STRCHR if the functions exist.
The string functions normally need the string.h header file. Some older version use strings.h instead, but the easiest thing is usually to just provide your own function prototypes if string.h isn't available.
I've supplied implementations of some of the functions that your system may be missing. They are mostly not very efficient and should only be used if nothing is available from the system libraries, since the system libraries should usually be better. All of the C code on this page is public domain and may be used without concern for licenses. Some was contributed by Dan Cross.
#ifndef HAVE_MEMMOVE char *memmove(char *dst, char *src, int n) { if (src > dst) for ( ; n > 0; n--) *(dst++)= *(src++); else for (dst+= n-1, src+= n-1; n > 0; n--) *(dst--)= *(src--); } #endif
#ifndef HAVE_STRCASECMP #define ccmp(a) ((a) == (b) ? 0 : ((a) > (b) ? 1 : -1)) int strcasecmp(unsigned char *s1, unsigned char *s2) { unsigned char c1, c2; for ( ; ; ) { if (*s1 == '\0' || *s2 == '\0') return ccmp(*s1,*s2); c1= (isascii(*s1) && isupper(*s1)) ? tolower(*s1) : *s1; c2= (isascii(*s2) && isupper(*s2)) ? tolower(*s2) : *s2; if (c1 != c2) return ccmp(c1,c2); s1++; s2++; } } #undef ccmp #endif
#ifndef HAVE_STRCHR # define strchr(a,b) index(a,b) # define strrchr(a,b) rindex(a,b) #endifAny system that doesn't have strchr(), will have index().
Dan Cross has provided the following simple public domain implementation of strlcpy():
#ifndef HAVE_STRLCPY size_t strlcpy(char *dst, const char *src, size_t size) { size_t len, srclen; srclen = strlen(src); if (--size <= 0) return(srclen); len = (size < srclen) ? size : srclen; memmove(dst, src, len); dst[len] = '\0'; return(srclen); } #endif
#ifndef HAVE_STRDUP char *strdup(char *str) { char *dup= (char *)malloc( strlen(str)+1 ); if (dup) strcpy(dup,str); return dup; } #ifndef HAVE_STRNDUP char *strndup(char *str, size_t len) { char *dup= (char *)malloc( len+1 ); if (dup) { strncpy(dup,str,len); dup[len]= '\0'; } return dup; } #endif
#ifndef HAVE_STRERROR char *strerror(int errno) { extern int sys_nerr; extern char *sys_errlist[]; if (errno < 0 || errno > sys_nerr) return "Unknown Error"; else return sys_errlist[errno]; } #endif
#ifndef HAVE_STRNLEN size_t strnlen(char *s, size_t maxlen) { size_t i; for (i= 0; i < maxlen && *s != '\0'; i++, s++) ; return i; } #endif
#ifndef HAVE_STRSEP char * strsep(char **sp, char *sep) { char *p, *s; if (sp == NULL || *sp == NULL || **sp == '\0') return(NULL); s = *sp; p = s + strcspn(s, sep); if (*p != '\0') *p++ = '\0'; *sp = p; return(s); } #endif
#ifndef HAVE_STRSTR char *strstr(s,p) char *s, *p; { char *sp, *pp; for(sp= s, pp= p; *sp && *pp; ) { if (*sp == *pp) { sp++; pp++; } else { sp= sp - (pp - p) + 1; pp= p; } } return (*pp ? NULL : sp-(pp-p)); } #endifDan Cross provided the following reimplemention of strcasestr() which, unfortunately, relies on the availability of strcspn(), and strncasecmp:
#ifndef HAVE_STRCASESTR char *strcasestr(char *a, char *b) { size_t l; char f[3]; snprintf(f, sizeof(f), "%c%c", tolower(*b), toupper(*b)); for (l = strcspn(a, f); l != strlen(a); l += strcspn(a + l + 1, f) + 1) if (strncasecmp(a + l, b, strlen(b)) == 0) return(a + l); return(NULL); } #endif