Add some missing libc functions: setenv, unsetenv, strdup.

--HG--
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
extra : source : 64d6e6eec18d76bf8f3947ec5d171db94acdb282
This commit is contained in:
David Given 2013-05-29 21:41:58 +01:00
parent f522aba4af
commit d273497077
7 changed files with 162 additions and 28 deletions

View 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

View 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,

View 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

View file

@ -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;
}

View 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)
{
register char **v = environ;
register const char *p, *q;
int offset;
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(_findenv(name,&offset));
}
return (char *)NULL;
/*
* _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)
{
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);
}

View file

@ -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;
}

View file

@ -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;
}