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:
parent
ab0177113f
commit
18356edb69
34 changed files with 65 additions and 65 deletions
31
libc/stdlib/_Exit.cpp
Normal file
31
libc/stdlib/_Exit.cpp
Normal 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
53
libc/stdlib/abort.cpp
Normal 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
37
libc/stdlib/abs.cpp
Normal 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
30
libc/stdlib/atof.cpp
Normal 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
30
libc/stdlib/atoi.cpp
Normal 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
30
libc/stdlib/atol.cpp
Normal 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
30
libc/stdlib/atoll.cpp
Normal 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
40
libc/stdlib/bsearch.cpp
Normal 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
36
libc/stdlib/calloc.cpp
Normal 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;
|
||||
}
|
||||
31
libc/stdlib/canonicalize_file_name.cpp
Normal file
31
libc/stdlib/canonicalize_file_name.cpp
Normal 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);
|
||||
}
|
||||
206
libc/stdlib/canonicalize_file_name_at.cpp
Normal file
206
libc/stdlib/canonicalize_file_name_at.cpp
Normal 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
33
libc/stdlib/div.cpp
Normal 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
200
libc/stdlib/env.cpp
Normal 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
37
libc/stdlib/exit.cpp
Normal 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
722
libc/stdlib/heap.cpp
Normal 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
90
libc/stdlib/integer.cpp
Normal 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
33
libc/stdlib/ldiv.cpp
Normal 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
33
libc/stdlib/lldiv.cpp
Normal 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
43
libc/stdlib/mblen.cpp
Normal 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
38
libc/stdlib/mbstowcs.cpp
Normal 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
33
libc/stdlib/mbtowc.cpp
Normal 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
37
libc/stdlib/mktemp.cpp
Normal 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
62
libc/stdlib/on_exit.cpp
Normal 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
61
libc/stdlib/qsort.cpp
Normal 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
65
libc/stdlib/rand.cpp
Normal 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
57
libc/stdlib/realpath.cpp
Normal 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
28
libc/stdlib/strtod.cpp
Normal 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
94
libc/stdlib/strtof.cpp
Normal 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
28
libc/stdlib/strtold.cpp
Normal 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
49
libc/stdlib/system.cpp
Normal 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
38
libc/stdlib/wcstombs.cpp
Normal 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
32
libc/stdlib/wctomb.cpp
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue