From 074b42aa9791f5dd15b32d0b124cb216aac3a555 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 29 May 2013 21:41:58 +0100 Subject: [PATCH] Add some missing libc functions: setenv, unsetenv, strdup. --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 | 2 + lang/cem/libcc.ansi/headers/stdlib.h | 3 + lang/cem/libcc.ansi/headers/string.h | 3 + lang/cem/libcc.ansi/misc/putenv.c | 22 ++++--- lang/cem/libcc.ansi/stdlib/getenv.c | 58 +++++++++++++------ lang/cem/libcc.ansi/stdlib/setenv.c | 87 ++++++++++++++++++++++++++++ lang/cem/libcc.ansi/string/strdup.c | 17 ++++++ 7 files changed, 163 insertions(+), 29 deletions(-) create mode 100644 lang/cem/libcc.ansi/stdlib/setenv.c create mode 100644 lang/cem/libcc.ansi/string/strdup.c diff --git a/lang/cem/libcc.ansi/build.mk b/lang/cem/libcc.ansi/build.mk index 6140b4b50..5987de9e3 100644 --- a/lang/cem/libcc.ansi/build.mk +++ b/lang/cem/libcc.ansi/build.mk @@ -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 diff --git a/lang/cem/libcc.ansi/headers/stdlib.h b/lang/cem/libcc.ansi/headers/stdlib.h index c14db91a8..64a6de16c 100644 --- a/lang/cem/libcc.ansi/headers/stdlib.h +++ b/lang/cem/libcc.ansi/headers/stdlib.h @@ -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, diff --git a/lang/cem/libcc.ansi/headers/string.h b/lang/cem/libcc.ansi/headers/string.h index b9d50617b..eef924f74 100644 --- a/lang/cem/libcc.ansi/headers/string.h +++ b/lang/cem/libcc.ansi/headers/string.h @@ -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 diff --git a/lang/cem/libcc.ansi/misc/putenv.c b/lang/cem/libcc.ansi/misc/putenv.c index dc448fef2..a1f94aba4 100644 --- a/lang/cem/libcc.ansi/misc/putenv.c +++ b/lang/cem/libcc.ansi/misc/putenv.c @@ -10,18 +10,17 @@ #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; } diff --git a/lang/cem/libcc.ansi/stdlib/getenv.c b/lang/cem/libcc.ansi/stdlib/getenv.c index 01b887a1d..592e0c05d 100644 --- a/lang/cem/libcc.ansi/stdlib/getenv.c +++ b/lang/cem/libcc.ansi/stdlib/getenv.c @@ -5,23 +5,47 @@ /* $Id$ */ #include -#include +#include -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 index 000000000..086b2118d --- /dev/null +++ b/lang/cem/libcc.ansi/stdlib/setenv.c @@ -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 +#include + +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 index 000000000..730796b5f --- /dev/null +++ b/lang/cem/libcc.ansi/string/strdup.c @@ -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 + +char* +strdup(const char *s) +{ + int len = strlen(s); + char *p = malloc(len+1); + if (p) + memcpy(p, s, len+1); + return p; +} -- 2.34.1