aboutsummaryrefslogtreecommitdiff
path: root/user/lib/libc/string.c
diff options
context:
space:
mode:
authornthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
committernthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
commitc63f340d90800895f007de64b7d2d14624263331 (patch)
tree2c0849fa597dd6da831c8707b6f2603403778d7b /user/lib/libc/string.c
Created student weenix repository
Diffstat (limited to 'user/lib/libc/string.c')
-rw-r--r--user/lib/libc/string.c509
1 files changed, 509 insertions, 0 deletions
diff --git a/user/lib/libc/string.c b/user/lib/libc/string.c
new file mode 100644
index 0000000..ae3042d
--- /dev/null
+++ b/user/lib/libc/string.c
@@ -0,0 +1,509 @@
+#include "string.h"
+#include "errno.h"
+#include "sys/types.h"
+#include <stdlib.h>
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ signed char res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ {
+ if ((res = *su1 - *su2) != 0)
+ {
+ break;
+ }
+ }
+ return res;
+}
+
+void *memcpy(void *dest, const void *src, size_t count)
+{
+ char *tmp = (char *)dest;
+ const char *s = src;
+
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+
+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;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+ register signed char __res;
+
+ while (1)
+ {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ {
+ break;
+ }
+ }
+
+ return __res;
+}
+
+char *strcpy(char *dest, const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0') /* nothing */
+ ;
+ return tmp;
+}
+
+char *strncpy(char *dest, const char *src, size_t count)
+{
+ char *tmp = dest;
+
+ while (count)
+ {
+ if ((*dest = *src) != 0)
+ src++;
+ dest++;
+ count--;
+ }
+
+ return tmp;
+}
+
+void *memset(void *s, int c, size_t count)
+{
+ char *xs = (char *)s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+}
+
+size_t strnlen(const char *s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ {
+ /* nothing */}
+ return sc - s;
+}
+
+char *strcat(char *dest, const char *src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+
+ while ((*dest++ = *src++) != '\0')
+ ;
+
+ return tmp;
+}
+
+size_t strlen(const char *s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ {
+ /* nothing */}
+ return sc - s;
+}
+
+char *strchr(const char *s, int c)
+{
+ for (; *s != (char)c; ++s)
+ {
+ if (*s == '\0')
+ {
+ return NULL;
+ }
+ }
+ return (char *)s;
+}
+
+char *strrchr(const char *s, int c)
+{
+ char *r = NULL;
+ for (; *s; ++s)
+ {
+ if (*s == (char)c)
+ {
+ r = (char *)s;
+ }
+ }
+ return r;
+}
+
+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;
+}
+
+char *strdup(const char *s)
+{
+ size_t len = strlen(s) + 1;
+ char *str = (char *)malloc(len);
+ memcpy(str, s, len);
+ return str;
+}
+
+/*
+ * The following three functions were ripped out of OpenSolaris. Legally, they
+ * might have to be in a separate file. Leaving it here out of laziness.
+ * Got this from /onnv-gate/usr/src/common/uti/string.c.
+ */
+
+char *strpbrk(const char *string, const char *brkset)
+{
+ const char *p;
+
+ do
+ {
+ for (p = brkset; *p != '\0' && *p != *string; ++p)
+ ;
+ if (*p != '\0')
+ {
+ return ((char *)string);
+ }
+ } while (*string++);
+
+ return (NULL);
+}
+
+size_t strspn(const char *string, const char *charset)
+{
+ const char *p, *q;
+
+ for (q = string; *q != '\0'; ++q)
+ {
+ for (p = charset; *p != '\0' && *p != *q; ++p)
+ ;
+ if (*p == '\0')
+ {
+ break;
+ }
+ }
+
+ return (q - string);
+}
+
+char *strtok(char *string, const char *sepset)
+{
+ char *p, *q, *r;
+ static char *savept;
+
+ /*
+ * Set `p' to our current location in the string.
+ */
+ p = (string == NULL) ? savept : string;
+ if (p == NULL)
+ {
+ return (NULL);
+ }
+
+ /*
+ * Skip leading separators; bail if no tokens remain.
+ */
+ q = p + strspn(p, sepset);
+ if (*q == '\0')
+ {
+ return (NULL);
+ }
+
+ /*
+ * Mark the end of the token and set `savept' for the next iteration.
+ */
+ if ((r = strpbrk(q, sepset)) == NULL)
+ {
+ savept = NULL;
+ }
+ else
+ {
+ *r = '\0';
+ savept = ++r;
+ }
+
+ return (q);
+}
+
+/* created with the help of:
+ * perl -p -e 's/#define\s+(\w+)\s+\d+\s+\/\* ([^\t\*]+)\s*\*\/\s*$/case $1:
+ * return "$2";\n/' < /usr/include/sys/errno.h
+ */
+char *strerror(int errnum)
+{
+ switch (errnum)
+ {
+ case EPERM:
+ return "Not super-user";
+ case ENOENT:
+ return "No such file or directory";
+ case ESRCH:
+ return "No such process";
+ case EINTR:
+ return "interrupted system call";
+ case EIO:
+ return "I/O error";
+ case ENXIO:
+ return "No such device or address";
+ case E2BIG:
+ return "Arg list too long";
+ case ENOEXEC:
+ return "Exec format error";
+ case EBADF:
+ return "Bad file number";
+ case ECHILD:
+ return "No children";
+ case EAGAIN:
+ return "Resource temporarily unavailable";
+ case ENOMEM:
+ return "Not enough core";
+ case EACCES:
+ return "Permission denied";
+ case EFAULT:
+ return "Bad address";
+ case ENOTBLK:
+ return "Block device required";
+ case EBUSY:
+ return "Mount device busy";
+ case EEXIST:
+ return "File exists";
+ case EXDEV:
+ return "Cross-device link";
+ case ENODEV:
+ return "No such device";
+ case ENOTDIR:
+ return "Not a directory";
+ case EISDIR:
+ return "Is a directory";
+ case EINVAL:
+ return "Invalid argument";
+ case ENFILE:
+ return "File table overflow";
+ case EMFILE:
+ return "Too many open files";
+ case ENOTTY:
+ return "Inappropriate ioctl for device";
+ case ETXTBSY:
+ return "Text file busy";
+ case EFBIG:
+ return "File too large";
+ case ENOSPC:
+ return "No space left on device";
+ case ESPIPE:
+ return "Illegal seek";
+ case EROFS:
+ return "Read only file system";
+ case EMLINK:
+ return "Too many links";
+ case EPIPE:
+ return "Broken pipe";
+ case EDOM:
+ return "Math arg out of domain of func";
+ case ERANGE:
+ return "Math result not representable";
+ case ENOMSG:
+ return "No message of desired type";
+ case EIDRM:
+ return "Identifier removed";
+ case ECHRNG:
+ return "Channel number out of range";
+ case EL2NSYNC:
+ return "Level 2 not synchronized";
+ case EL3HLT:
+ return "Level 3 halted";
+ case EL3RST:
+ return "Level 3 reset";
+ case ELNRNG:
+ return "Link number out of range";
+ case EUNATCH:
+ return "Protocol driver not attached";
+ case ENOCSI:
+ return "No CSI structure available";
+ case EL2HLT:
+ return "Level 2 halted";
+ case EDEADLK:
+ return "Deadlock condition.";
+ case ENOLCK:
+ return "No record locks available.";
+ case ECANCELED:
+ return "Operation canceled";
+ case ENOTSUP:
+ return "Operation not supported";
+ case EDQUOT:
+ return "Disc quota exceeded";
+ case EBADE:
+ return "invalid exchange";
+ case EBADR:
+ return "invalid request descriptor";
+ case EXFULL:
+ return "exchange full";
+ case ENOANO:
+ return "no anode";
+ case EBADRQC:
+ return "invalid request code";
+ case EBADSLT:
+ return "invalid slot";
+ case EBFONT:
+ return "bad font file fmt";
+ case EOWNERDEAD:
+ return "process died with the lock";
+ case ENOTRECOVERABLE:
+ return "lock is not recoverable";
+ case ENOSTR:
+ return "Device not a stream";
+ case ENODATA:
+ return "no data (for no delay io)";
+ case ETIME:
+ return "timer expired";
+ case ENOSR:
+ return "out of streams resources";
+ case ENONET:
+ return "Machine is not on the network";
+ case ENOPKG:
+ return "Package not installed";
+ case EREMOTE:
+ return "The object is remote";
+ case ENOLINK:
+ return "the link has been severed";
+ case EADV:
+ return "advertise error";
+ case ESRMNT:
+ return "srmount error";
+ case ECOMM:
+ return "Communication error on send";
+ case EPROTO:
+ return "Protocol error";
+ case EMULTIHOP:
+ return "multihop attempted";
+ case EBADMSG:
+ return "trying to read unreadable message";
+ case ENAMETOOLONG:
+ return "path name is too long";
+ case EOVERFLOW:
+ return "value too large to be stored in data type";
+ case ENOTUNIQ:
+ return "given log. name not unique";
+ case EBADFD:
+ return "f.d. invalid for this operation";
+ case EREMCHG:
+ return "Remote address changed";
+ case ELIBACC:
+ return "Can't access a needed shared lib.";
+ case ELIBBAD:
+ return "Accessing a corrupted shared lib.";
+ case ELIBSCN:
+ return ".lib section in a.out corrupted.";
+ case ELIBMAX:
+ return "Attempting to link in too many libs.";
+ case ELIBEXEC:
+ return "Attempting to exec a shared library.";
+ case EILSEQ:
+ return "Illegal byte sequence.";
+ case ENOSYS:
+ return "Unsupported file system operation";
+ case ELOOP:
+ return "Symbolic link loop";
+ case ERESTART:
+ return "Restartable system call";
+ case ESTRPIPE:
+ return "if pipe/FIFO, don't sleep in stream head";
+ case ENOTEMPTY:
+ return "directory not empty";
+ case EUSERS:
+ return "Too many users (for UFS)";
+ case ENOTSOCK:
+ return "Socket operation on non-socket";
+ case EDESTADDRREQ:
+ return "Destination address required";
+ case EMSGSIZE:
+ return "Message too long";
+ case EPROTOTYPE:
+ return "Protocol wrong type for socket";
+ case ENOPROTOOPT:
+ return "Protocol not available";
+ case EPROTONOSUPPORT:
+ return "Protocol not supported";
+ case ESOCKTNOSUPPORT:
+ return "Socket type not supported";
+ case EPFNOSUPPORT:
+ return "Protocol family not supported";
+ case EAFNOSUPPORT:
+ return "Address family not supported by protocol family";
+ case EADDRINUSE:
+ return "Address already in use";
+ case EADDRNOTAVAIL:
+ return "Can't assign requested address";
+ case ENETDOWN:
+ return "Network is down";
+ case ENETUNREACH:
+ return "Network is unreachable";
+ case ENETRESET:
+ return "Network dropped connection because of reset";
+ case ECONNABORTED:
+ return "Software caused connection abort";
+ case ECONNRESET:
+ return "Connection reset by peer";
+ case ENOBUFS:
+ return "No buffer space available";
+ case EISCONN:
+ return "Socket is already connected";
+ case ENOTCONN:
+ return "Socket is not connected";
+ case ESHUTDOWN:
+ return "Can't send after socket shutdown";
+ case ETOOMANYREFS:
+ return "Too many references: can't splice";
+ case ETIMEDOUT:
+ return "Connection timed out";
+ case ECONNREFUSED:
+ return "Connection refused";
+ case EHOSTDOWN:
+ return "Host is down";
+ case EHOSTUNREACH:
+ return "No route to host";
+ case EALREADY:
+ return "operation already in progress";
+ case EINPROGRESS:
+ return "operation now in progress";
+ case ESTALE:
+ return "Stale NFS file handle";
+ default:
+ return 0;
+ }
+}