1
0
Fork 0
mirror of https://gitlab.com/sortix/sortix.git synced 2023-02-13 20:55:38 -05:00

Move stdlib.h functions into their own directory.

This commit is contained in:
Jonas 'Sortie' Termansen 2013-06-24 23:52:59 +02:00
parent ab0177113f
commit 18356edb69
34 changed files with 65 additions and 65 deletions

31
libc/stdlib/_Exit.cpp Normal file
View file

@ -0,0 +1,31 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/_Exit.cpp
Terminates the current process.
*******************************************************************************/
#include <stdlib.h>
#include <unistd.h>
extern "C" void _Exit(int status)
{
_exit(status);
}

53
libc/stdlib/abort.cpp Normal file
View file

@ -0,0 +1,53 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/abort.cpp
Abnormal process termination.
*******************************************************************************/
#include <sys/stat.h>
#include <calltrace.h>
#include <stdlib.h>
#if defined(SORTIX_KERNEL)
#include <sortix/kernel/platform.h>
#include <sortix/kernel/panic.h>
extern "C" void abort(void)
{
Sortix::PanicF("abort()");
}
#else
extern "C" void abort(void)
{
struct stat st;
if ( getenv("LIBC_DEBUG_CALLTRACE") || stat("/etc/calltrace", &st) == 0 )
calltrace();
if ( getenv("LIBC_DEBUG_LOOP") || stat("/etc/calltrace_loop", &st) == 0 )
while ( true );
// TODO: Send SIGABRT instead!
_Exit(128 + 6);
}
#endif

37
libc/stdlib/abs.cpp Normal file
View file

@ -0,0 +1,37 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/abs.cpp
Allows taking the absolute value of integer types.
*******************************************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
template <class T> T Absolute(T t)
{
return t < 0 ? -t : t;
}
extern "C" int abs(int val) { return Absolute(val); }
extern "C" long int labs(long int val) { return Absolute(val); }
extern "C" long long int llabs(long long int val) { return Absolute(val); }
extern "C" intmax_t imaxabs(intmax_t val) { return Absolute(val); }

30
libc/stdlib/atof.cpp Normal file
View file

@ -0,0 +1,30 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/atof.cpp
Converts floating numbers represented as strings to binary representation.
*******************************************************************************/
#include <stdlib.h>
extern "C" double atof(const char* str)
{
return strtod(str, NULL);
}

30
libc/stdlib/atoi.cpp Normal file
View file

@ -0,0 +1,30 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/atoi.cpp
Converts integers represented as strings to binary representation.
*******************************************************************************/
#include <stdlib.h>
extern "C" int atoi(const char* str)
{
return (int) strtol(str, (char**) NULL, 10);
}

30
libc/stdlib/atol.cpp Normal file
View file

@ -0,0 +1,30 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/atol.cpp
Converts integers represented as strings to binary representation.
*******************************************************************************/
#include <stdlib.h>
extern "C" long atol(const char* str)
{
return strtol(str, (char**) NULL, 10);
}

30
libc/stdlib/atoll.cpp Normal file
View file

@ -0,0 +1,30 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/atoll.cpp
Converts integers represented as strings to binary representation.
*******************************************************************************/
#include <stdlib.h>
extern "C" long long atoll(const char* str)
{
return strtoll(str, (char **) NULL, 10);
}

40
libc/stdlib/bsearch.cpp Normal file
View file

@ -0,0 +1,40 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/bsearch.cpp
Binary search.
*******************************************************************************/
#include <stdint.h>
#include <stdlib.h>
extern "C" void* bsearch(const void* key, const void* base, size_t nmemb,
size_t size, int (*compare)(const void*, const void*))
{
const uint8_t* baseptr = (const uint8_t*) base;
// TODO: Just a quick and surprisingly correct yet slow implementation.
for ( size_t i = 0; i < nmemb; i++ )
{
const void* candidate = baseptr + i * size;
if ( !compare(key, candidate) )
return (void*) candidate;
}
return NULL;
}

36
libc/stdlib/calloc.cpp Normal file
View file

@ -0,0 +1,36 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/calloc.cpp
Allocates zeroed memory.
*******************************************************************************/
#include <stdlib.h>
#include <string.h>
extern "C" void* calloc(size_t nmemb, size_t size)
{
size_t total = nmemb * size;
void* result = malloc(total);
if ( !result )
return NULL;
memset(result, 0, total);
return result;
}

View file

@ -0,0 +1,31 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/canonicalize_file_name.cpp
Return the canonicalized filename.
*******************************************************************************/
#include <fcntl.h>
#include <stdlib.h>
extern "C" char* canonicalize_file_name(const char* path)
{
return canonicalize_file_name_at(AT_FDCWD, path);
}

View file

@ -0,0 +1,206 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/canonicalize_file_name_at.cpp
Return the canonicalized filename.
*******************************************************************************/
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int dup_handles_cwd(int fd)
{
if ( fd == AT_FDCWD )
return open(".", O_RDONLY | O_DIRECTORY);
return dup(fd);
}
static char* FindDirectoryEntryAt(int dirfd, ino_t inode, dev_t dev)
{
int dupdirfd = dup_handles_cwd(dirfd);
if ( dupdirfd < 0 )
return NULL;
DIR* dir = fdopendir(dupdirfd);
if ( !dir ) { close(dupdirfd); return NULL; }
struct dirent* entry;
while ( (entry = readdir(dir)) )
{
if ( !strcmp(entry->d_name, "..") )
continue;
struct stat st;
if ( fstatat(dupdirfd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) )
continue; // Not ideal, but missing permissions, broken symlinks..
if ( st.st_ino == inode && st.st_dev == dev )
{
char* result = strdup(entry->d_name);
closedir(dir);
return result;
}
}
closedir(dir);
errno = ENOENT;
return NULL;
}
static const char* SkipSlashes(const char* path)
{
while ( *path == '/' )
path++;
return *path ? path : NULL;
}
extern "C" char* canonicalize_file_name_at(int dirfd, const char* path)
{
if ( path && path[0] == '.' && !path[1] )
path = NULL;
// The below code is able to determine the absolute path to a directory by
// using the .. entry and searching the parent directory. This doesn't work
// for files, as they can be linked in any number of directories and have no
// pointer back to the directory they were opened from. We'll therefore
// follow the path until the last element, and if the path points to a file
// we'll simply append that to the final result.
if ( path )
{
// Open the directory specified by the last slash in the path.
char* last_slash = strrchr(path, '/');
if ( last_slash )
{
size_t subpath_len = (size_t) (last_slash - path + 1);
char* subpath = (char*) malloc((subpath_len + 1) * sizeof(char));
memcpy(subpath, path, subpath_len * sizeof(char));
subpath[subpath_len] = '\0';
int fd = openat(dirfd, subpath, O_RDONLY | O_DIRECTORY);
free(subpath);
if ( fd < 0 )
return NULL;
path = SkipSlashes(last_slash + 1);
char* ret = canonicalize_file_name_at(fd, path);
close(fd);
return ret;
}
// We have reached the final element in the path. It could be:
// 1) A directory.
// 2) A file.
// 3) A symbolic link to a directory.
// 4) A symbolic link to a file.
// The ideal case is if it's a directory (case 1). We follow symbolic
// links to directories as that's also okay (case 3).
int fd = openat(dirfd, path, O_RDONLY | O_DIRECTORY);
if ( fd )
{
char* ret = canonicalize_file_name_at(fd, NULL);
close(fd);
return ret;
}
// Stop if an error happened other that the target wasn't a directory.
if ( errno != ENOTDIR )
return NULL;
// TODO: Symbolic link support here.
// Okay, so now we are dealing with either case 2 or case 4. Since
// Sortix doesn't have current have symbolic links, we'll be lazy and
// just assume we are dealing with a file. Otherwise, we'd have to open
// with O_NOFOLLOW and if that fails, use readlink to figure out where
// the symbolic link is going, open the directory that contains it and
// continue this function from there - or something.
}
// Our task is now to determine the absolute path of the directory opened as
// dirfd and append the path variable to it, if any. We'll find the inode
// information of the directory and search its parent directory for an entry
// that resolves to this directory. That'll give us one part of the path.
// We'll then apply that techinique recursively until we hit a directory
// whose parent is itself (the root directory).
int fd;
int parent;
struct stat fdst;
struct stat parentst;
size_t retlen = 0;
size_t newretlen;
char* ret = NULL;
char* newret;
char* elem;
if ( path )
{
if ( !(ret = (char*) malloc(sizeof(char) * (1 + strlen(path) + 1))) )
return NULL;
stpcpy(stpcpy(ret, "/"), path);
}
if ( (fd = dup_handles_cwd(dirfd)) < 0 )
goto cleanup_done;
if ( fstat(fd, &fdst) )
goto cleanup_fd;
if ( !S_ISDIR(fdst.st_mode) )
{
errno = ENOTDIR;
goto cleanup_fd;
}
next_parent:
parent = openat(fd, "..", O_RDONLY | O_DIRECTORY);
if ( parent < 0 )
goto cleanup_fd;
if ( fstat(parent, &parentst) )
goto cleanup_parent;
if ( fdst.st_ino == parentst.st_ino &&
fdst.st_dev == parentst.st_dev )
{
close(fd);
close(parent);
return ret ? ret : strdup("/");
}
elem = FindDirectoryEntryAt(parent, fdst.st_ino, fdst.st_dev);
if ( !elem )
goto cleanup_parent;
newretlen = 1 + strlen(elem) + retlen;
newret = (char*) malloc(sizeof(char) * (newretlen + 1));
if ( !newret )
goto cleanup_elem;
stpcpy(stpcpy(stpcpy(newret, "/"), elem), ret ? ret : "");
free(elem);
free(ret);
ret = newret;
retlen = newretlen;
close(fd);
fd = parent;
fdst = parentst;
goto next_parent;
cleanup_elem:
free(elem);
cleanup_parent:
close(parent);
cleanup_fd:
close(fd);
cleanup_done:
free(ret);
return NULL;
}

33
libc/stdlib/div.cpp Normal file
View file

@ -0,0 +1,33 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/div.cpp
Compute quotient and remainder of integer division.
*******************************************************************************/
#include <stdlib.h>
extern "C" div_t div(int numer, int denom)
{
div_t ret;
ret.quot = numer / denom;
ret.rem = numer % denom;
return ret;
}

200
libc/stdlib/env.cpp Normal file
View file

@ -0,0 +1,200 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/env.cpp
Environmental variables utilities.
*******************************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
/* Since legacy applications rely on being able to modify the environ variable,
we have to keep track of whether it is what we expect and whether we know the
size of it. If it changed, we need to recount, as well as malloc a copy of it
if we wish to make changes. */
extern "C" { char** environ = NULL; }
static char** environ_malloced = NULL;
static char** environ_counted = NULL;
size_t environlen = 0;
size_t environroom = 0;
static inline bool environismalloced()
{
return environ && environ == environ_malloced;
}
extern "C" const char* const* getenviron(void)
{
return environ;
}
extern "C" size_t envlength(void)
{
if ( !environ ) { return 0; }
if ( environ_counted != environ )
{
size_t count = 0;
while ( environ[count] ) { count++; }
environ_counted = environ;
environlen = count;
}
return environlen;
}
extern "C" const char* getenvindexed(size_t index)
{
if ( envlength() <= index ) { errno = EBOUND; return NULL; }
return environ[index];
}
extern "C" const char* sortix_getenv(const char* name)
{
size_t equalpos = strcspn(name, "=");
if ( name[equalpos] == '=' ) { return NULL; }
size_t namelen = equalpos;
size_t envlen = envlength();
for ( size_t i = 0; i < envlen; i++ )
{
if ( strncmp(name, environ[i], namelen) ) { continue; }
if ( environ[i][namelen] != '=' ) { continue; }
return environ[i] + namelen + 1;
}
return NULL;
}
extern "C" char* getenv(const char* name)
{
return (char*) sortix_getenv(name);
}
static bool makeenvironmalloced()
{
if ( environismalloced() ) { return true; }
size_t envlen = envlength();
size_t newenvlen = envlen;
size_t newenvsize = sizeof(char*) * (newenvlen+1);
char** newenviron = (char**) malloc(newenvsize);
if ( !newenviron ) { return false; }
size_t sofar = 0;
for ( size_t i = 0; i < envlen; i++ )
{
newenviron[i] = strdup(environ[i]);
if ( !newenviron[i] ) { goto cleanup; }
sofar = i;
}
newenviron[envlen] = NULL;
environlen = environroom = newenvlen;
environ = environ_malloced = environ_counted = newenviron;
return true;
cleanup:
for ( size_t i = 0; i < sofar; i++ ) { free(newenviron[i]); }
free(newenviron);
return false;
}
extern "C" int clearenv(void)
{
if ( !environ ) { return 0; }
if ( environismalloced() )
{
for ( char** varp = environ; *varp; varp++ ) { free(*varp); }
free(environ);
}
environ = environ_counted = environ_malloced = NULL;
return 0;
}
static bool doputenv(char* str, char* freeme, bool overwrite)
{
if ( !makeenvironmalloced() ) { free(freeme); return false; }
size_t strvarnamelen = strcspn(str, "=");
for ( size_t i = 0; i < envlength(); i++ )
{
char* var = environ[i];
if ( strncmp(str, var, strvarnamelen) ) { continue; }
if ( !overwrite ) { free(freeme); return true; }
free(var);
environ[i] = str;
return true;
}
if ( environlen == environroom )
{
size_t newenvironroom = environroom ? 2 * environroom : 16;
size_t newenvironsize = sizeof(char*) * (newenvironroom+1);
char** newenviron = (char**) realloc(environ, newenvironsize);
if ( !newenviron ) { free(freeme); return false; }
environ = environ_malloced = environ_counted = newenviron;
environroom = newenvironroom;
}
environ[environlen++] = str;
environ[environlen] = NULL;
return true;
}
extern "C" int setenv(const char* name, const char* value, int overwrite)
{
if ( !name || !name[0] || strchr(name, '=') ) { errno = EINVAL; return -1; }
char* str = (char*) malloc(strlen(name) + 1 + strlen(value) + 1);
if ( !str ) { return -1; }
stpcpy(stpcpy(stpcpy(str, name), "="), value);
if ( !doputenv(str, str, overwrite) ) { return -1; }
return 0;
}
extern "C" int putenv(char* str)
{
if ( !strchr(str, '=') ) { errno = EINVAL; return -1; }
// TODO: HACK: This voilates POSIX as it mandates that callers must be able
// to modify the environment by modifying the string. However, this is bad
// design! It also means we got a memory leak since we can't safely free
// strings from the environment when overriding them. Therefore we create
// a copy of the strings here and use the copy instead. This is a problem
// for some applications that will subtly break.
char* strcopy = strdup(str);
if ( !strcopy )
return -1;
if ( !doputenv(strcopy, strcopy, true) ) { return -1; }
return 0;
}
extern "C" int unsetenv(const char* name)
{
size_t equalpos = strcspn(name, "=");
if ( name[equalpos] == '=' ) { return 0; }
size_t namelen = equalpos;
size_t envlen = envlength();
for ( size_t i = 0; i < envlen; i++ )
{
if ( strncmp(name, environ[i], namelen) ) { continue; }
if ( environ[i][namelen] != '=' ) { continue; }
if ( environismalloced() )
{
char* str = environ[i];
free(str);
}
if ( i < envlen-1 ) { environ[i] = environ[envlen-1]; }
environ[--environlen] = NULL;
return 0;
}
return 0;
}

37
libc/stdlib/exit.cpp Normal file
View file

@ -0,0 +1,37 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/exit.cpp
Terminates the current process.
*******************************************************************************/
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
extern "C" void call_exit_handlers(int status);
extern "C" void exit(int status)
{
call_exit_handlers(status);
dcloseall();
fcloseall();
_Exit(status);
}

722
libc/stdlib/heap.cpp Normal file
View file

@ -0,0 +1,722 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/heap.cpp
Functions that allocate/free memory from a dynamic memory heap.
*******************************************************************************/
#include <sys/mman.h>
#ifdef SORTIX_KERNEL
#define HEAP_GROWS_DOWNWARDS
#endif
#ifndef SORTIX_KERNEL
#include <error.h>
#include <stdio.h>
#include <unistd.h>
#endif
#include <assert.h>
#include <errno.h>
#include <malloc.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define PARANOIA 1
#ifdef SORTIX_KERNEL
#include <sortix/kernel/decl.h>
#include <sortix/kernel/addralloc.h>
#include <sortix/kernel/kthread.h>
#include <sortix/kernel/log.h>
#include <sortix/kernel/memorymanagement.h>
#include <sortix/kernel/panic.h>
#endif
//
// This first section is just magic compiler/platform stuff, you should
// skip ahead to the actual algorithm.
//
#if defined(__x86_64__)
const size_t MAGIC = 0xDEADDEADDEADDEADUL;
const size_t ALIGNMENT = 16UL;
#else
const size_t MAGIC = 0xDEADDEADUL;
const size_t ALIGNMENT = 8UL;
#endif
const size_t PAGESIZE = 4UL * 1024UL; // 4 KiB
const size_t NUMBINS = 8UL * sizeof(size_t);
static uintptr_t wilderness;
#ifdef SORTIX_KERNEL
static uintptr_t GetHeapStart()
{
return Sortix::GetHeapUpper();
}
static void FreeMemory(uintptr_t where, size_t bytes)
{
assert(Sortix::Page::IsAligned(where + bytes));
while ( bytes )
{
addr_t page = Sortix::Memory::Unmap(where);
Sortix::Page::Put(page);
bytes -= PAGESIZE;
where += PAGESIZE;
}
}
static bool AllocateMemory(uintptr_t where, size_t bytes)
{
assert(Sortix::Page::IsAligned(where + bytes));
uintptr_t pos = where;
while ( bytes )
{
addr_t page = Sortix::Page::Get();
if ( !page )
{
FreeMemory(where, pos-where);
return false;
}
if ( !Sortix::Memory::Map(page, pos, PROT_KREAD | PROT_KWRITE) )
{
Sortix::Page::Put(page);
FreeMemory(where, pos-where);
return false;
}
bytes -= PAGESIZE;
pos += PAGESIZE;
}
return true;
}
static bool ExtendHeap(size_t bytesneeded)
{
size_t got_bytes = Sortix::ExpandHeap(bytesneeded);
if ( !got_bytes )
return false;
assert(bytesneeded <= got_bytes);
#ifdef HEAP_GROWS_DOWNWARDS
uintptr_t newwilderness = wilderness - got_bytes;
#else
uintptr_t newwilderness = wilderness + got_bytes;
#endif
if ( !AllocateMemory(newwilderness, got_bytes) )
{
Sortix::ShrinkHeap(got_bytes);
return false;
}
return true;
}
#else
static uintptr_t GetHeapStart()
{
uintptr_t base = (uintptr_t) sbrk(0);
uintptr_t unaligned = base % ALIGNMENT;
if ( unaligned )
{
sbrk(ALIGNMENT-unaligned);
}
uintptr_t result = (uintptr_t) sbrk(0);
return result;
}
static bool ExtendHeap(size_t bytesneeded)
{
void* newheapend = sbrk(bytesneeded);
return newheapend != (void*) -1UL;
}
#endif
// TODO: BitScanForward and BitScanReverse are x86 instructions, but
// directly using them messes with the optimizer. Once possible, use
// the inline assembly instead of the C-version of the functions.
// Returns the index of the most significant set bit.
inline size_t BSR(size_t Value)
{
#if 1
assert(Value > 0);
for ( size_t I = 8*sizeof(size_t); I > 0; I-- )
{
if ( Value & ( 1UL << (I-1) ) ) { return I-1; }
}
return 0;
#else
size_t Result;
asm("bsr %0, %1" : "=r"(Result) : "r"(Value));
return Result;
#endif
}
// Returns the index of the least significant set bit.
inline size_t BSF(size_t Value)
{
#if 1
assert(Value > 0);
for ( size_t I = 0; I < 8*sizeof(size_t); I++ )
{
if ( Value & ( 1UL << I ) ) { return I; }
}
return 0;
#else
size_t Result;
asm("bsf %0, %1" : "=r"(Result) : "r"(Value));
return Result;
#endif
}
//
// Now for some helper functions and structures.
//
struct Chunk;
struct Trailer;
#ifdef SORTIX_KERNEL
Sortix::kthread_mutex_t heaplock;
#endif
// The location where the heap originally grows from.
uintptr_t heapstart;
// If heap grows down: Location of the first mapped page.
// If heap grows up: Location of the first not-mapped page.
#if 0 /* forward declared abvce */
static uintptr_t wilderness;
#endif
// How many bytes remain in the wilderness.
size_t wildernesssize;
// How many bytes are the heap allow to grow to (including wilderness).
size_t heapmaxsize;
// How many bytes are currently used for chunks in the heap, which
// excludes the wilderness.
size_t heapsize;
// bins[N] contain a linked list of chunks that are at least 2^(N+1)
// bytes, but less than 2^(N+2) bytes. By selecting the proper bin in
// constant time, we can allocate chunks in constant time.
Chunk* bins[NUMBINS];
// Bit N is set if bin[N] contains a chunk.
size_t bincontainschunks;
static bool IsGoodHeapPointer(void* ptr, size_t size)
{
uintptr_t ptrlower = (uintptr_t) ptr;
uintptr_t ptrupper = ptrlower + size;
#ifdef HEAP_GROWS_DOWNWARDS
uintptr_t heaplower = wilderness;
uintptr_t heapupper = heapstart;
#else
uintptr_t heaplower = heapstart;
uintptr_t heapupper = wilderness;
#endif
return heaplower <= ptrlower && ptrupper <= heapupper;
}
// A preamble to every chunk providing meta-information.
struct Chunk
{
public:
size_t size; // Includes size of Chunk and Trailer
union
{
size_t magic;
Chunk* nextunused;
};
public:
bool IsUsed() { return magic == MAGIC; }
Trailer* GetTrailer();
Chunk* LeftNeighbor();
Chunk* RightNeighbor();
bool IsSane();
};
// A trailer to every chunk providing meta-information.
struct Trailer
{
public:
union
{
size_t magic;
Chunk* prevunused;
};
size_t size; // Includes size of Chunk and Trailer
public:
bool IsUsed() { return magic == MAGIC; }
Chunk* GetChunk();
};
const size_t OVERHEAD = sizeof(Chunk) + sizeof(Trailer);
// This is how a real chunk actually looks:
//struct RealChunk
//{
// Chunk header;
// byte data[...];
// Trailer footer;
// };
Trailer* Chunk::GetTrailer()
{
return (Trailer*) (((uintptr_t) this) + size - sizeof(Trailer));
}
Chunk* Chunk::LeftNeighbor()
{
Trailer* trailer = (Trailer*) (((uintptr_t) this) - sizeof(Trailer));
return trailer->GetChunk();
}
Chunk* Chunk::RightNeighbor()
{
return (Chunk*) (((uintptr_t) this) + size);
}
Chunk* Trailer::GetChunk()
{
return (Chunk*) (((uintptr_t) this) + sizeof(Trailer) - size);
}
bool Chunk::IsSane()
{
if ( !IsGoodHeapPointer(this, sizeof(*this)) )
return false;
if ( !size ) { return false; }
size_t binindex = BSR(size);
Trailer* trailer = GetTrailer();
if ( !IsGoodHeapPointer(trailer, sizeof(*trailer)) )
return false;
if ( trailer->size != size ) { return false; }
if ( IsUsed() )
{
if ( bins[binindex] == this ) { return false; }
if ( magic != MAGIC || trailer->magic != magic ) { return false; }
}
if ( !IsUsed() )
{
if ( ((uintptr_t) nextunused) & (ALIGNMENT-1UL) ) { return false; }
if ( ((uintptr_t) trailer->prevunused) & (ALIGNMENT-1UL) ) { return false; }
if ( nextunused && !IsGoodHeapPointer(nextunused->GetTrailer(),
sizeof(Trailer)) )
return false;
if ( nextunused && nextunused->GetTrailer()->prevunused != this ) { return false; }
if ( trailer->prevunused )
{
if ( !IsGoodHeapPointer(trailer->prevunused,
sizeof(*trailer->prevunused)) )
return false;
if ( bins[binindex] == this ) { return false; }
if ( trailer->prevunused->nextunused != this ) { return false; }
}
if ( !trailer->prevunused )
{
if ( bins[binindex] != this ) { return false; }
if ( !(bincontainschunks & (1UL << binindex)) ) { return false; }
}
}
return true;
}
static void InsertChunk(Chunk* chunk)
{
// Insert the chunk into the right bin.
size_t binindex = BSR(chunk->size);
chunk->GetTrailer()->prevunused = NULL;
chunk->nextunused = bins[binindex];
if ( chunk->nextunused )
{
assert(chunk->nextunused->IsSane());
chunk->nextunused->GetTrailer()->prevunused = chunk;
}
bins[binindex] = chunk;
bincontainschunks |= (1UL << binindex);
assert(chunk->IsSane());
}
__attribute__((unused))
static bool ValidateHeap()
{
bool foundbin[NUMBINS];
for ( size_t i = 0; i < NUMBINS; i++ ) { foundbin[i] = false; }
#ifdef HEAP_GROWS_DOWNWARDS
Chunk* chunk = (Chunk*) (wilderness + wildernesssize);
while ( (uintptr_t) chunk < heapstart )
#else
Chunk* chunk = (Chunk*) heapstart;
while ( (uintptr_t) chunk < wilderness - wildernesssize )
#endif
{
size_t timesfound = 0;
for ( size_t i = 0; i < NUMBINS; i++ )
{
if ( chunk == bins[i] ) { foundbin[i] = true; timesfound++; }
}
if ( 1 < timesfound ) { return false; }
if ( !chunk->IsSane() ) { return false; }
chunk = chunk->RightNeighbor();
}
for ( size_t i = 0; i < NUMBINS; i++ )
{
if ( !bins[i] )
{
if ( foundbin[i] ) { return false; }
continue;
}
if ( !foundbin[i] ) { return false; }
if ( !bins[i]->IsSane() ) { return false; }
}
return true;
}
//
// This is where the actual memory allocation algorithm starts.
//
extern "C" void _init_heap()
{
heapstart = GetHeapStart();
heapmaxsize = SIZE_MAX;
heapsize = 0;
wilderness = heapstart;
wildernesssize = 0;
for ( size_t i = 0; i < NUMBINS; i++ ) { bins[i] = NULL; }
bincontainschunks = 0;
#ifdef SORTIX_KERNEL
heaplock = Sortix::KTHREAD_MUTEX_INITIALIZER;
#endif
}
// Attempts to expand the wilderness such that it contains at least
// bytesneeded bytes. This is done by mapping new pages onto into the
// virtual address-space.
static bool ExpandWilderness(size_t bytesneeded)
{
if ( bytesneeded <= wildernesssize ) { return true; }
bytesneeded -= wildernesssize;
// Align the increase on page boundaries.
const size_t PAGEMASK = ~(PAGESIZE - 1UL);
bytesneeded = ( bytesneeded + PAGESIZE - 1UL ) & PAGEMASK;
assert(bytesneeded >= PAGESIZE);
// TODO: Overflow MAY happen here!
if ( heapmaxsize <= heapsize + wildernesssize + bytesneeded )
return errno = ENOMEM, true;
#ifdef HEAP_GROWS_DOWNWARDS
uintptr_t newwilderness = wilderness - bytesneeded;
#else
uintptr_t newwilderness = wilderness + bytesneeded;
#endif
// Attempt to map pages so our wilderness grows.
if ( !ExtendHeap(bytesneeded) )
return false;
wildernesssize += bytesneeded;
wilderness = newwilderness;
return true;
}
extern "C" void* malloc(size_t size)
{
#ifdef SORTIX_KERNEL
Sortix::ScopedLock scopedlock(&heaplock);
#endif
#if 2 <= PARANOIA
assert(ValidateHeap());
#endif
// The size field keeps both the allocation and meta information.
size += OVERHEAD;
// Round up to nearest alignment.
size = (size + ALIGNMENT - 1UL) & (~(ALIGNMENT-1UL));
// Find the index of the smallest usable bin.
size_t minbinindex = BSR(size-1UL)+1UL;
// Make a bitmask that filter away all bins that are too small.
size_t minbinmask = ~((1UL << minbinindex) - 1UL);
// Figure out which bins are usable for our chunk.
size_t availablebins = bincontainschunks & minbinmask;
if ( availablebins )
{
// Find the smallest available bin.
size_t binindex = BSF(availablebins);
Chunk* chunk = bins[binindex];
assert(chunk->IsSane());
bins[binindex] = chunk->nextunused;
size_t binsize = 1UL << binindex;
// Mark the bin as empty if we emptied it.
if ( !bins[binindex] )
{
bincontainschunks ^= binsize;
}
else
{
Trailer* trailer = bins[binindex]->GetTrailer();
trailer->prevunused = NULL;
}
assert(!bins[binindex] || bins[binindex]->IsSane());
// If we don't use the entire chunk.
if ( OVERHEAD <= binsize - size )
{
size_t left = binsize - size;
chunk->size -= left;
chunk->GetTrailer()->size = chunk->size;
Chunk* leftchunk = chunk->RightNeighbor();
leftchunk->size = left;
Trailer* lefttrailer = leftchunk->GetTrailer();
lefttrailer->size = left;
InsertChunk(leftchunk);
}
chunk->magic = MAGIC;
chunk->GetTrailer()->magic = MAGIC;
#if 3 <= PARANOIA
assert(ValidateHeap());
#endif
uintptr_t result = ((uintptr_t) chunk) + sizeof(Chunk);
return (void*) result;
}
// If no bins are available, try to allocate from the wilderness.
// Check if the wilderness can meet our requirements.
if ( wildernesssize < size && !ExpandWilderness(size) )
{
errno = ENOMEM;
return NULL;
}
// Carve a new chunk out of the wilderness and initialize it.
#ifdef HEAP_GROWS_DOWNWARDS
Chunk* chunk = (Chunk*) (wilderness + wildernesssize - size);
#else
Chunk* chunk = (Chunk*) (wilderness - wildernesssize);
#endif
assert(size <= wildernesssize);
wildernesssize -= size;
heapsize += size;
assert(IsGoodHeapPointer(chunk, sizeof(*chunk)));
chunk->size = size;
Trailer* trailer = chunk->GetTrailer();
assert(IsGoodHeapPointer(trailer, sizeof(*trailer)));
trailer->size = size;
chunk->magic = MAGIC;
trailer->magic = MAGIC;
#if 3 <= PARANOIA
assert(ValidateHeap());
#endif
uintptr_t result = ((uintptr_t) chunk) + sizeof(Chunk);
return (void*) result;
}
static bool IsLeftmostChunk(Chunk* chunk)
{
#ifdef HEAP_GROWS_DOWNWARDS
return (uintptr_t) chunk <= wilderness + wildernesssize;
#else
return heapstart <= (uintptr_t) chunk;
#endif
}
static bool IsRightmostChunk(Chunk* chunk)
{
#ifdef HEAP_GROWS_DOWNWARDS
return heapstart <= (uintptr_t) chunk + chunk->size;
#else
return heapstart + heapsize <= (uintptr_t) chunk + chunk->size;
#endif
}
// Removes a chunk from its bin.
static void UnlinkChunk(Chunk* chunk)
{
assert(chunk->IsSane());
Trailer* trailer = chunk->GetTrailer();
if ( trailer->prevunused )
{
assert(trailer->prevunused->IsSane());
trailer->prevunused->nextunused = chunk->nextunused;
if ( chunk->nextunused )
{
assert(chunk->nextunused->IsSane());
chunk->nextunused->GetTrailer()->prevunused = trailer->prevunused;
}
}
else
{
if ( chunk->nextunused )
{
assert(chunk->nextunused->IsSane());
chunk->nextunused->GetTrailer()->prevunused = NULL;
}
size_t binindex = BSR(chunk->size);
assert(bins[binindex] == chunk);
bins[binindex] = chunk->nextunused;
if ( !bins[binindex] ) { bincontainschunks ^= 1UL << binindex; }
else { assert(bins[binindex]->IsSane()); }
}
}
// Transforms a chunk and its neighbors into a single chunk if possible.
static void UnifyNeighbors(Chunk** chunk)
{
if ( !IsLeftmostChunk(*chunk) )
{
Chunk* neighbor = (*chunk)->LeftNeighbor();
if ( !neighbor->IsUsed() )
{
size_t size = neighbor->size;
size_t chunksize = (*chunk)->size;
UnlinkChunk(neighbor);
*chunk = neighbor;
(*chunk)->size = size + chunksize;
(*chunk)->GetTrailer()->size = (*chunk)->size;
}
}
if ( !IsRightmostChunk(*chunk) )
{
Chunk* neighbor = (*chunk)->RightNeighbor();
if ( !neighbor->IsUsed() )
{
UnlinkChunk(neighbor);
(*chunk)->size += neighbor->size;
(*chunk)->GetTrailer()->size = (*chunk)->size;
}
}
}
extern "C" void free(void* addr)
{
#ifdef SORTIX_KERNEL
Sortix::ScopedLock scopedlock(&heaplock);
#endif
#if 2 <= PARANOIA
assert(ValidateHeap());
#endif
if ( !addr) { return; }
Chunk* chunk = (Chunk*) ((uintptr_t) addr - sizeof(Chunk));
#ifndef SORTIX_KERNEL
if ( !IsGoodHeapPointer(addr, 1) ||
!IsGoodHeapPointer(chunk, sizeof(*chunk)) )
{
error(0, 0, "attempted to free(3) non-heap pointer: 0x%zx", addr);
abort();
}
if ( !chunk->IsUsed() )
{
error(0, 0, "attempted to free(3) area that doesn't appear to be "
"allocated: 0x%zx + 0x%zx", addr);
abort();
}
#endif
assert(chunk->IsUsed());
assert(chunk->IsSane());
UnifyNeighbors(&chunk);
#ifdef HEAP_GROWS_DOWNWARDS
bool nexttowilderness = IsLeftmostChunk(chunk);
#else
bool nexttowilderness = IsRightmostChunk(chunk);
#endif
// If possible, let the wilderness regain the memory.
if ( nexttowilderness )
{
heapsize -= chunk->size;
wildernesssize += chunk->size;
return;
}
InsertChunk(chunk);
#if 3 <= PARANOIA
assert(ValidateHeap());
#endif
}
// TODO: Implement this function properly.
extern "C" void* realloc(void* ptr, size_t size)
{
if ( !ptr ) { return malloc(size); }
Chunk* chunk = (Chunk*) ((uintptr_t) ptr - sizeof(Chunk));
assert(chunk->IsUsed());
assert(chunk->IsSane());
size_t allocsize = chunk->size - OVERHEAD;
if ( size < allocsize ) { return ptr; }
void* newptr = malloc(size);
if ( !newptr ) { return NULL; }
memcpy(newptr, ptr, allocsize);
free(ptr);
return newptr;
}

90
libc/stdlib/integer.cpp Normal file
View file

@ -0,0 +1,90 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/integer.cpp
Converts integers represented as strings to binary representation.
*******************************************************************************/
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
static int Debase(char c)
{
if ( '0' <= c && c <= '9' ) { return c - '0'; }
if ( 'a' <= c && c <= 'z' ) { return 10 + c - 'a'; }
if ( 'A' <= c && c <= 'Z' ) { return 10 + c - 'A'; }
return -1;
}
template <class INT, bool UNSIGNED> INT ParseInteger(const char* str, char** endptr, int base)
{
const char* origstr = str;
int origbase = base;
while ( isspace(*str) ) { str++; }
if ( base < 0 || 36 < base ) { if ( endptr ) { *endptr = (char*) str; } return 0; }
INT result = 0;
bool negative = false;
char c = *str;
if ( !UNSIGNED && c == '-' ) { str++; negative = true; }
if ( !UNSIGNED && c == '+' ) { str++; negative = false; }
if ( !base && str[0] == '0' )
{
if ( str[1] == 'x' || str[1] == 'X' ) { str += 2; base = 16; }
else if ( 0 <= Debase(str[1]) && Debase(str[1]) < 8 ) { str++; base = 8; }
}
if ( !base ) { base = 10; }
if ( origbase == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) { str += 2; }
size_t numconvertedchars = 0;
while ( (c = *str ) )
{
int val = Debase(c);
if ( val < 0 ) { break; }
if ( base <= val ) { break; }
if ( !UNSIGNED && negative ) { val = -val; }
// TODO: Detect overflow!
result = result * (INT) base + (INT) val;
str++;
numconvertedchars++;
}
if ( !numconvertedchars ) { str = origstr; result = 0; }
if ( endptr ) { *endptr = (char*) str; }
return result;
}
extern "C" long strtol(const char* str, char** endptr, int base)
{
return ParseInteger<long, false>(str, endptr, base);
}
extern "C" long long strtoll(const char* str, char** endptr, int base)
{
return ParseInteger<long long, false>(str, endptr, base);
}
extern "C" unsigned long strtoul(const char* str, char** endptr, int base)
{
return ParseInteger<unsigned long, true>(str, endptr, base);
}
extern "C" unsigned long long strtoull(const char* str, char** endptr, int base)
{
return ParseInteger<unsigned long long, true>(str, endptr, base);
}

33
libc/stdlib/ldiv.cpp Normal file
View file

@ -0,0 +1,33 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/ldiv.cpp
Compute quotient and remainder of integer division.
*******************************************************************************/
#include <stdlib.h>
extern "C" ldiv_t ldiv(long numer, long denom)
{
ldiv_t ret;
ret.quot = numer / denom;
ret.rem = numer % denom;
return ret;
}

33
libc/stdlib/lldiv.cpp Normal file
View file

@ -0,0 +1,33 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/lldiv.cpp
Compute quotient and remainder of integer division.
*******************************************************************************/
#include <stdlib.h>
extern "C" lldiv_t lldiv(long long numer, long long denom)
{
lldiv_t ret;
ret.quot = numer / denom;
ret.rem = numer % denom;
return ret;
}

43
libc/stdlib/mblen.cpp Normal file
View file

@ -0,0 +1,43 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/mblen.cpp
Determine number of bytes in next multibyte character.
*******************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
extern "C" int mblen(const char* s, size_t n)
{
static mbstate_t ps;
if ( !s )
{
memset(&ps, 0, sizeof(ps));
return 0; // TODO: Give the correct return value depending on ps.
}
size_t ret = mbrlen(s, n, &ps);
if ( ret == (size_t) -2 )
return -1;
if ( ret == (size_t) -1 )
return -1;
return (int) ret;
}

38
libc/stdlib/mbstowcs.cpp Normal file
View file

@ -0,0 +1,38 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/mbstowcs.cpp
Convert a multibyte string to a wide-character string.
*******************************************************************************/
#include <stdlib.h>
#include <wchar.h>
extern "C" size_t mbstowcs(wchar_t* dst, const char* src, size_t n)
{
// Reset the secret conversion state variable in mbsrtowcs that is used when
// ps is NULL by successfully converting the empty string. As always, this
// is not multithread secure. For some reason, the standards don't mandate
// that the conversion state is reset when mbsrtowcs is called with ps=NULL,
// which arguably is a feature - but this function is supposed to do it.
const char* empty_string = "";
mbsrtowcs(NULL, &empty_string, 0, NULL);
return mbsrtowcs(dst, &src, n, NULL);
}

33
libc/stdlib/mbtowc.cpp Normal file
View file

@ -0,0 +1,33 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/mbtowc.cpp
Convert a multibyte sequence to a wide character.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
// TODO: This function is unpure and should be removed.
extern "C" int mbtowc(wchar_t* pwd, const char* s, size_t n)
{
return mbrtowc(pwd, s, n, NULL);
}

37
libc/stdlib/mktemp.cpp Normal file
View file

@ -0,0 +1,37 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/mktemp.cpp
Make a unique temporary filename.
*******************************************************************************/
#include <stdlib.h>
#include <string.h>
// TODO: This is a hacky implementation of a stupid function.
extern "C" char* mktemp(char* templ)
{
size_t templlen = strlen(templ);
for ( size_t i = templlen-6UL; i < templlen; i++ )
{
templ[i] = '0' + rand() % 10;
}
return templ;
}

62
libc/stdlib/on_exit.cpp Normal file
View file

@ -0,0 +1,62 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/on_exit.cpp
Hooks that is called upon process exit.
*******************************************************************************/
#include <stdlib.h>
struct exithandler
{
void (*hook)(int, void*);
void* param;
struct exithandler* next;
}* exit_handler_stack = NULL;
extern "C" int on_exit(void (*hook)(int, void*), void* param)
{
struct exithandler* handler = (struct exithandler*) malloc(sizeof(struct exithandler));
if ( !handler ) { return -1; }
handler->hook = hook;
handler->param = param;
handler->next = exit_handler_stack;
exit_handler_stack = handler;
return 0;
}
static void atexit_adapter(int /*status*/, void* user)
{
((void (*)(void)) user)();
}
extern "C" int atexit(void (*hook)(void))
{
return on_exit(atexit_adapter, (void*) hook);
}
extern "C" void call_exit_handlers(int status)
{
while ( exit_handler_stack )
{
exit_handler_stack->hook(status, exit_handler_stack->param);
exit_handler_stack = exit_handler_stack->next;
}
}

61
libc/stdlib/qsort.cpp Normal file
View file

@ -0,0 +1,61 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/qsort.cpp
Utility functions related to sorting and sorted data.
*******************************************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
// TODO: This is an ugly hack!
static void memswap(uint8_t* a, uint8_t* b, size_t size)
{
uint8_t* tmp = (uint8_t*) malloc(size);
if ( !tmp ) { abort(); }
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
free(tmp);
}
// TODO: This is just a quick and dirty insertion sort. It'd be nice to have a
// good old quick sort here soon. Combined with the slow memswap above, this
// results in a very slow sorting algorithm.
extern "C" void qsort(void* base, size_t nmemb, size_t size,
int (* compare)(const void*, const void*))
{
uint8_t* buf = (uint8_t*) base;
for ( size_t i = 0; i < nmemb; i++ )
{
for ( size_t c = i; c; c-- )
{
size_t currentoff = c * size;
uint8_t* current = buf + currentoff;
size_t p = c-1;
size_t prevoff = p * size;
uint8_t* prev = buf + prevoff;
int cmp = compare(prev, current);
if ( cmp <= 0 ) { break; }
memswap(prev, current, size);
}
}
}

65
libc/stdlib/rand.cpp Normal file
View file

@ -0,0 +1,65 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/rand.cpp
Returns a random value.
*******************************************************************************/
#include <stdlib.h>
#if 1
static unsigned int m_w = 1337;
static unsigned int m_z = 37;
static unsigned int RandomUnsignedInt()
{
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w; /* 32-bit result */
}
extern "C" int rand()
{
return RandomUnsignedInt() % 32768;
}
extern "C" void srand(unsigned int seed)
{
m_w = seed >> 16 & 0xFFFF;
m_z = seed >> 0 & 0xFFFF;
}
#else
static unsigned random_seed = 1337;
extern "C" int rand()
{
random_seed = random_seed + 37 * 1103515245 + 12345;
return random_seed >> 16;
}
extern "C" void srand(unsigned int seed)
{
random_seed = seed;
}
#endif

57
libc/stdlib/realpath.cpp Normal file
View file

@ -0,0 +1,57 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/realpath.cpp
Return the canonicalized filename.
*******************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char* realpath(const char* restrict path, char* restrict resolved_path)
{
char* ret_path = canonicalize_file_name(path);
if ( !ret_path )
return NULL;
if ( !resolved_path )
return ret_path;
#ifdef PATH_MAX
if ( PATH_MAX < strlen(ret_path) + 1 )
return errno = ENAMETOOLONG, (char*) NULL;
strcpy(resolved_path, ret_path);
free(ret_path);
return resolved_path;
#else
if ( !isatty(2) )
dup2(open("/dev/tty", O_WRONLY), 2);
fprintf(stderr, "%s:%u: %s(\"%s\", %p) = \"%s\": "
"This platform doesn't have PATH_MAX and the second argument "
"wasn't NULL - You cannot reliably allocate a sufficiently large "
"buffer and the POSIX standard specifies this as undefined "
"behavior, aborting.\n", __FILE__, __LINE__, __func__, path,
resolved_path, ret_path);
abort();
#endif
}

28
libc/stdlib/strtod.cpp Normal file
View file

@ -0,0 +1,28 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/strtod.cpp
Converts floating numbers represented as strings to binary representation.
*******************************************************************************/
#define FLOAT double
#define STRTOF strtod
#include "strtof.cpp"

94
libc/stdlib/strtof.cpp Normal file
View file

@ -0,0 +1,94 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/strtof.cpp
Converts floating numbers represented as strings to binary representation.
*******************************************************************************/
#ifndef FLOAT
#define FLOAT float
#define STRTOF strtof
#endif
#include <stdlib.h>
#include <stdio.h>
// TODO: This horribly hacky code is taken from sdlquake's common.c, which is
// licensed under the GPL. Since most Sortix software is GPL-compatible
// this will do for now. It's a temporary measure until I get around to
// writing a real strtod function - most of them are true horrors.
extern "C" FLOAT STRTOF(const char* str, char** nptr)
{
int sign = *str == '-' ? (str++, -1) : 1;
FLOAT val = 0.0;
if ( false )
{
out:
if ( nptr )
*nptr = (char*) str;
return val * sign;
}
if ( str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
{
str += 2;
while ( true )
{
char c = *str++;
if ( '0' <= c && c <= '9' )
val = val * 16 + c - '0';
else if ( 'a' <= c && c <= 'f' )
val = val * 16 + c - 'a' + 10;
else if ( 'A' <= c && c <= 'F' )
val = val * 16 + c - 'A' + 10;
else
goto out;
}
}
int decimal = -1;
int total = 0;
while ( true )
{
char c = *str++;
if (c == '.')
{
decimal = total;
continue;
}
if ( c < '0' || c > '9' )
break;
val = val * 10 + c - '0';
total++;
}
if ( decimal == -1 )
goto out;
while ( decimal < total )
{
val /= 10;
total--;
}
goto out;
}

28
libc/stdlib/strtold.cpp Normal file
View file

@ -0,0 +1,28 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/strtold.cpp
Converts floating numbers represented as strings to binary representation.
*******************************************************************************/
#define FLOAT long double
#define STRTOF strtold
#include "strtof.cpp"

49
libc/stdlib/system.cpp Normal file
View file

@ -0,0 +1,49 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/system.cpp
Execute a shell command.
*******************************************************************************/
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
extern "C" int system(const char* command)
{
const int ret_error = command ? -1 : 0;
const int exit_error = command ? 127 : 0;
if ( !command )
command = "exit 1";
// TODO: Block SIGHCHLD, SIGINT, anda SIGQUIT while waiting.
pid_t childpid = fork();
if ( childpid < 0 )
return ret_error;
if ( childpid )
{
int status;
if ( waitpid(childpid, &status, 0) < 0 )
return ret_error;
return status;
}
execlp("sh", "sh", "-c", command, NULL);
_exit(exit_error);
}

38
libc/stdlib/wcstombs.cpp Normal file
View file

@ -0,0 +1,38 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/wcstombs.cpp
Convert a wide-character string to multibyte string.
*******************************************************************************/
#include <stdlib.h>
#include <wchar.h>
extern "C" size_t wcstombs(char* dst, const wchar_t* src, size_t n)
{
// Reset the secret conversion state variable in wcsrtombs that is used when
// ps is NULL by successfully converting the empty string. As always, this
// is not multithread secure. For some reason, the standards don't mandate
// that the conversion state is reset when wcsrtombs is called with ps=NULL,
// which arguably is a feature - but this function is supposed to do it.
const wchar_t* empty_string = L"";
wcsrtombs(NULL, &empty_string, 0, NULL);
return wcsrtombs(dst, &src, n, NULL);
}

32
libc/stdlib/wctomb.cpp Normal file
View file

@ -0,0 +1,32 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
The Sortix C Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
stdlib/wctomb.cpp
Convert a wide character to a multibyte sequence.
*******************************************************************************/
#include <stdlib.h>
#include <wchar.h>
// TODO: This function is unpure and should be removed.
extern "C" int wctomb(char* s, wchar_t wc)
{
return wcrtomb(s, wc, NULL);
}