Add some missing libc functions: setenv, unsetenv, strdup.
authorDavid Given <dg@cowlark.com>
Wed, 29 May 2013 20:41:58 +0000 (21:41 +0100)
committerDavid Given <dg@cowlark.com>
Wed, 29 May 2013 20:41:58 +0000 (21:41 +0100)
--HG--
branch : dtrg-videocore
rename : lang/cem/libcc.ansi/stdlib/getenv.c => lang/cem/libcc.ansi/stdlib/setenv.c
rename : lang/cem/libcc.ansi/string/strlen.c => lang/cem/libcc.ansi/string/strdup.c

lang/cem/libcc.ansi/build.mk
lang/cem/libcc.ansi/headers/stdlib.h
lang/cem/libcc.ansi/headers/string.h
lang/cem/libcc.ansi/misc/putenv.c
lang/cem/libcc.ansi/stdlib/getenv.c
lang/cem/libcc.ansi/stdlib/setenv.c [new file with mode: 0644]
lang/cem/libcc.ansi/string/strdup.c [new file with mode: 0644]

index 6140b4b..5987de9 100644 (file)
@@ -186,6 +186,7 @@ $(call ackfile, lang/cem/libcc.ansi/stdlib/div.c)
 $(call ackfile, lang/cem/libcc.ansi/stdlib/atexit.c)
 $(call ackfile, lang/cem/libcc.ansi/stdlib/exit.c)
 $(call ackfile, lang/cem/libcc.ansi/stdlib/getenv.c)
+$(call ackfile, lang/cem/libcc.ansi/stdlib/setenv.c)
 $(call ackfile, lang/cem/libcc.ansi/stdlib/labs.c)
 $(call ackfile, lang/cem/libcc.ansi/stdlib/ldiv.c)
 $(call ackfile, lang/cem/libcc.ansi/stdlib/mblen.c)
@@ -238,6 +239,7 @@ $(call ackfile, lang/cem/libcc.ansi/string/strpbrk.c)
 $(call ackfile, lang/cem/libcc.ansi/string/strspn.c)
 $(call ackfile, lang/cem/libcc.ansi/string/strncmp.c)
 $(call ackfile, lang/cem/libcc.ansi/string/strxfrm.c)
+$(call ackfile, lang/cem/libcc.ansi/string/strdup.c)
 
 # Time
 
index c14db91..64a6de1 100644 (file)
@@ -36,6 +36,9 @@ extern int atexit(void (*_func)(void));
 extern void exit(int _status);
 extern void _Exit(int _status);
 extern char* getenv(const char *_name);
+extern int setenv(const char *_name, const char *_value, int _overwrite);
+extern int unsetenv(const char *_name);
+extern int putenv(char *_string);
 extern int system(const char *_string);
 extern void* bsearch(const void *_key, const void *_base,
                        size_t _nmemb, size_t _size,
index b9d5061..eef924f 100644 (file)
@@ -33,5 +33,8 @@ extern char   *strtok(char *_s1, const char *_s2);
 extern void    *memset(void *_s, int _c, size_t _n);
 extern char    *strerror(int _errnum);
 extern size_t  strlen(const char *_s);
+extern char *strdup(const char *_s);
+
+#define bcopy(s, d, z) memmove(d, s, z)
 
 #endif
index dc448fe..a1f94ab 100644 (file)
 #define        ENTRY_INC       10
 #define        rounded(x)      (((x / ENTRY_INC) + 1) * ENTRY_INC)
 
-extern const char **_penvp;
-extern const char **environ;   /* environ is a shadow name for _penvp */
+extern char **environ;
 
 int
 putenv(char *name)
 {
-       register const char **v = _penvp;
+       register char **v = environ;
        register char *r;
        static int size = 0;
        /* When size != 0, it contains the number of entries in the
         * table (including the final NULL pointer). This means that the
-        * last non-null entry  is _penvp[size - 2].
+        * last non-null entry  is environ[size - 2].
         */
 
        if (!name) return 0;
@@ -48,11 +47,11 @@ putenv(char *name)
                        }
                }
                *r = '=';
-               v = _penvp;
+               v = environ;
        }
 
        if (!size) {
-               register const char **p;
+               register char **p;
                register int i = 0;
 
                if (v)
@@ -62,18 +61,17 @@ putenv(char *name)
                if (!(v = malloc(rounded(i) * sizeof(char **))))
                        return 1;
                size = i;
-               p = _penvp;
-               _penvp = v;
+               p = environ;
+               environ = v;
                while (*v++ = *p++);            /* copy the environment */
-               v = _penvp;
+               v = environ;
        } else if (!(size % ENTRY_INC)) {
-               if (!(v = realloc(_penvp, rounded(size) * sizeof(char **))))
+               if (!(v = realloc(environ, rounded(size) * sizeof(char **))))
                        return 1;
-               _penvp = v;
+               environ = v;
        }
        v[size - 1] = name;
        v[size] = NULL;
        size++;
-       environ = _penvp;
        return 0;
 }
index 01b887a..592e0c0 100644 (file)
@@ -5,23 +5,47 @@
 /* $Id$ */
 
 #include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
 
-char *
-getenv(const char *name)
+extern char* _findenv(const char* name, int* offset);
+
+/*
+ * getenv(name) --
+ *     Returns ptr to value associated with name, if any, else NULL.
+ */
+char* getenv(const char* name)
+{
+    int offset;
+
+    return(_findenv(name,&offset));
+}
+
+/*
+ * _findenv(name,offset) --
+ *     Returns pointer to value associated with name, if any, else NULL.
+ *     Sets offset to be the offset of the name/value combination in the
+ *     environmental array, for use by setenv(3) and unsetenv(3).
+ *     Explicitly removes '=' in argument name.
+ *
+ *     This routine *should* be a static; don't use it.
+ */
+char* _findenv(register const char* name, int* offset)
 {
-       register char **v = environ;
-       register const char *p, *q;
-
-       if (v == NULL || name == NULL)
-               return (char *)NULL;
-       while ((p = *v++) != NULL) {
-               q = name;
-               while (*q && (*q == *p++))
-                       q++;
-               if (*q || (*p != '='))
-                       continue;
-               return (char *)p + 1;
-       }
-       return (char *)NULL;
+    extern char **environ;
+    register int    len;
+    register char **P;
+    register const char *C;
+
+       if (!environ)
+               return NULL;
+
+    for (C = name,len = 0;*C && *C != '=';++C,++len);
+    for (P = environ;*P;++P)
+        if (!strncmp(*P,name,len))
+            if (*(C = *P + len) == '=') {
+                *offset = P - environ;
+                return (char*)(++C);
+            }
+    return(NULL);
 }
+
diff --git a/lang/cem/libcc.ansi/stdlib/setenv.c b/lang/cem/libcc.ansi/stdlib/setenv.c
new file mode 100644 (file)
index 0000000..086b211
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id$ */
+
+#include <stdlib.h>
+#include <string.h>
+
+extern char* _findenv(const char* name, int* offset);
+extern char **environ;
+
+/*
+ * setenv(name,value,rewrite)
+ *     Set the value of the environmental variable "name" to be
+ *     "value".  If rewrite is set, replace any current value.
+ */
+int setenv(register const char* name, register const char* value, int rewrite)
+{
+    static int  alloced = 0;        /* if allocated space before */
+    register char   *C;
+    int l_value,
+        offset;
+
+    if (*value == '=')          /* no `=' in value */
+        ++value;
+    l_value = strlen(value);
+    if ((C = _findenv(name,&offset))) { /* find if already exists */
+        if (!rewrite)
+            return(0);
+        if (strlen(C) >= l_value) { /* old larger; copy over */
+            while (*C++ = *value++);
+            return(0);
+        }
+    }
+    else {                  /* create new slot */
+        register int    cnt = 0;
+        register char   **P;
+
+               if (environ)
+                       for (P = environ;*P;++P,++cnt);
+        if (alloced) {          /* just increase size */
+            environ = (char **)realloc((char *)environ,
+                (unsigned)(sizeof(char *) * (cnt + 2)));
+            if (!environ)
+                return(-1);
+        }
+        else {              /* get new space */
+            alloced = 1;        /* copy old entries into it */
+            P = (char **)malloc((unsigned)(sizeof(char *) *
+                (cnt + 2)));
+            if (!P)
+                return(-1);
+            if (environ)
+                               bcopy(environ,P,cnt * sizeof(char *));
+            environ = P;
+        }
+        environ[cnt + 1] = NULL;
+        offset = cnt;
+    }
+    for (C = name;*C && *C != '=';++C); /* no `=' in name */
+    if (!(environ[offset] =         /* name + `=' + value */
+        malloc((unsigned)((int)(C - name) + l_value + 2))))
+        return(-1);
+    for (C = environ[offset];(*C = *name++) && *C != '=';++C);
+    for (*C++ = '=';*C++ = *value++;);
+    return(0);
+}
+
+/*
+ * unsetenv(name) --
+ *     Delete environmental variable "name".
+ */
+int
+unsetenv(const char* name)
+{
+    register char   **P;
+    int offset;
+
+    while (_findenv(name,&offset))      /* if set multiple times */
+        for (P = &environ[offset];;++P)
+            if (!(*P = *(P + 1)))
+                break;
+
+    return 0;
+}
+
diff --git a/lang/cem/libcc.ansi/string/strdup.c b/lang/cem/libcc.ansi/string/strdup.c
new file mode 100644 (file)
index 0000000..730796b
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Id$ */
+
+#include       <string.h>
+
+char*
+strdup(const char *s)
+{
+       int len = strlen(s);
+       char *p = malloc(len+1);
+       if (p)
+               memcpy(p, s, len+1);
+       return p;
+}