Squash commits for public release
This commit is contained in:
6
libs/libapi/BUILD.gn
Normal file
6
libs/libapi/BUILD.gn
Normal file
@@ -0,0 +1,6 @@
|
||||
import("//build/libs/TEMPLATE.gni")
|
||||
|
||||
xOS_static_library("libapi") {
|
||||
sources = []
|
||||
configs = [ "//build/libs:lib_flags" ]
|
||||
}
|
||||
1407
libs/libapi/include/libapi/window_server/Connections/WSConnection.h
Normal file
1407
libs/libapi/include/libapi/window_server/Connections/WSConnection.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
# .ipc files should be regenerated with connection compiler "PROJECT_ROOT/utils/compilers/ConnectionCompiler/connc {input} {output}"
|
||||
# or run "PROJECT_ROOT/utils/codeassistant/recompile_connections.py"
|
||||
#
|
||||
# After regeneration you have to recompile the whole project to apply changes.
|
||||
|
||||
{
|
||||
KEYPROTECTED
|
||||
NAME: BaseWindowServerDecoder
|
||||
MAGIC: 320
|
||||
GreetMessage() => GreetMessageReply(uint32_t connection_id)
|
||||
CreateWindowMessage(int type, uint32_t width, uint32_t height, int buffer_id, LIPC::StringEncoder title, LIPC::StringEncoder icon_path, LIPC::StringEncoder bundle_id, uint32_t color, uint32_t menubar_style) => CreateWindowMessageReply(uint32_t window_id)
|
||||
DestroyWindowMessage(uint32_t window_id) => DestroyWindowMessageReply(uint32_t status)
|
||||
SetBufferMessage(uint32_t window_id, int buffer_id, int format, LG::Rect bounds)
|
||||
SetBarStyleMessage(uint32_t window_id, uint32_t color, uint32_t menubar_style)
|
||||
SetTitleMessage(uint32_t window_id, LIPC::StringEncoder title)
|
||||
InvalidateMessage(uint32_t window_id, LG::Rect rect)
|
||||
AskBringToFrontMessage(uint32_t window_id, uint32_t target_window_id)
|
||||
|
||||
# MenuBar
|
||||
MenuBarCreateMenuMessage(uint32_t window_id, LIPC::StringEncoder title) => MenuBarCreateMenuMessageReply(int status, int menu_id)
|
||||
MenuBarCreateItemMessage(uint32_t window_id, int menu_id, int item_id, LIPC::StringEncoder title) => MenuBarCreateItemMessageReply(int status)
|
||||
|
||||
# Popup
|
||||
PopupShowMenuMessage(uint32_t window_id, LG::Point<int> point, LIPC::VectorEncoder<LIPC::StringEncoder> data) => PopupShowMenuMessageReply(int status, int menu_id)
|
||||
}
|
||||
{
|
||||
KEYPROTECTED
|
||||
NAME: BaseWindowClientDecoder
|
||||
MAGIC: 737
|
||||
MouseMoveMessage(int win_id, uint32_t x, uint32_t y)
|
||||
MouseActionMessage(int win_id, int type, uint32_t x, uint32_t y)
|
||||
MouseLeaveMessage(int win_id, uint32_t x, uint32_t y)
|
||||
MouseWheelMessage(int win_id, int wheel_data, uint32_t x, uint32_t y)
|
||||
KeyboardMessage(int win_id, uint32_t kbd_key)
|
||||
|
||||
# Service Messages
|
||||
DisplayMessage(LG::Rect rect)
|
||||
WindowCloseRequestMessage(int win_id)
|
||||
ResizeMessage(int win_id, LG::Rect rect)
|
||||
DisconnectMessage(int reason)
|
||||
|
||||
# MenuBar
|
||||
MenuBarActionMessage(int win_id, int menu_id, int item_id)
|
||||
|
||||
# Popup
|
||||
PopupActionMessage(int win_id, int menu_id, int item_id)
|
||||
|
||||
# Notifications
|
||||
NotifyWindowCreateMessage(int win_id, LIPC::StringEncoder bundle_id, LIPC::StringEncoder icon_path, int changed_window_id, int changed_window_type)
|
||||
NotifyWindowStatusChangedMessage(int win_id, int changed_window_id, int type)
|
||||
NotifyWindowTitleChangedMessage(int win_id, int changed_window_id, LIPC::StringEncoder title)
|
||||
NotifyWindowIconChangedMessage(int win_id, int changed_window_id, LIPC::StringEncoder icon_path)
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <libg/Color.h>
|
||||
|
||||
struct StatusBarStyle {
|
||||
public:
|
||||
enum Mode : uint32_t {
|
||||
LightText = (1 << 0),
|
||||
HideText = (1 << 1),
|
||||
};
|
||||
|
||||
StatusBarStyle()
|
||||
: m_flags(0)
|
||||
, m_color(LG::Color::LightSystemBackground)
|
||||
{
|
||||
}
|
||||
|
||||
StatusBarStyle(uint32_t attr)
|
||||
: m_flags(attr)
|
||||
{
|
||||
}
|
||||
|
||||
StatusBarStyle(Mode attr)
|
||||
: m_flags(uint32_t(attr))
|
||||
{
|
||||
}
|
||||
|
||||
StatusBarStyle(uint32_t attr, const LG::Color& clr)
|
||||
: m_flags(attr)
|
||||
, m_color(clr)
|
||||
{
|
||||
}
|
||||
|
||||
StatusBarStyle(Mode attr, const LG::Color& clr)
|
||||
: m_flags(uint32_t(attr))
|
||||
, m_color(clr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit StatusBarStyle(const LG::Color& clr)
|
||||
: m_flags(0)
|
||||
, m_color(clr)
|
||||
{
|
||||
}
|
||||
|
||||
struct StandardLightType {
|
||||
};
|
||||
static const StandardLightType StandardLight;
|
||||
StatusBarStyle(StandardLightType)
|
||||
: m_flags(0)
|
||||
, m_color(LG::Color::LightSystemBackground)
|
||||
{
|
||||
}
|
||||
|
||||
struct StandardOpaqueType {
|
||||
};
|
||||
static const StandardOpaqueType StandardOpaque;
|
||||
StatusBarStyle(StandardOpaqueType)
|
||||
: m_flags(0)
|
||||
, m_color(LG::Color::Opaque)
|
||||
{
|
||||
}
|
||||
|
||||
~StatusBarStyle() = default;
|
||||
|
||||
inline bool hide_text() const { return has_attr(Mode::HideText); }
|
||||
inline bool show_text() const { return !hide_text(); }
|
||||
|
||||
inline bool light_text() const { return has_attr(Mode::LightText); }
|
||||
inline bool dark_text() const { return !light_text(); }
|
||||
|
||||
inline StatusBarStyle& set_light_text()
|
||||
{
|
||||
set_attr(Mode::LightText);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline StatusBarStyle& set_dark_text()
|
||||
{
|
||||
rem_attr(Mode::LightText);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline StatusBarStyle& set_hide_text()
|
||||
{
|
||||
set_attr(Mode::HideText);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline StatusBarStyle& set_show_text()
|
||||
{
|
||||
rem_attr(Mode::HideText);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uint32_t flags() const { return m_flags; }
|
||||
inline void set_flags(uint32_t attr) { m_flags = attr; }
|
||||
|
||||
inline StatusBarStyle& set_mode(Mode attr)
|
||||
{
|
||||
m_flags = (uint32_t)attr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const LG::Color& color() const { return m_color; }
|
||||
inline void set_color(const LG::Color& clr) { m_color = clr; }
|
||||
|
||||
private:
|
||||
inline bool has_attr(Mode mode) const { return ((m_flags & (uint32_t)mode) == (uint32_t)mode); }
|
||||
inline void set_attr(Mode mode) { m_flags |= (uint32_t)mode; }
|
||||
inline void rem_attr(Mode mode) { m_flags = m_flags & (~(uint32_t)mode); }
|
||||
|
||||
uint32_t m_flags { 0 };
|
||||
LG::Color m_color { LG::Color::LightSystemBackground };
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
enum MouseActionType {
|
||||
LeftMouseButtonPressed,
|
||||
LeftMouseButtonReleased,
|
||||
RightMouseButtonPressed,
|
||||
RightMouseButtonReleased,
|
||||
};
|
||||
|
||||
class MouseActionState {
|
||||
public:
|
||||
MouseActionState() = default;
|
||||
~MouseActionState() = default;
|
||||
|
||||
inline int state() const { return m_state; }
|
||||
inline void set(MouseActionType state) { m_state |= (int)state; }
|
||||
|
||||
private:
|
||||
int m_state { 0 };
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
enum WindowType : int {
|
||||
Standard = 0,
|
||||
Homescreen = 1,
|
||||
AppList = 2,
|
||||
};
|
||||
|
||||
enum WindowStatusUpdateType : int {
|
||||
Changed,
|
||||
Minimized,
|
||||
Removed,
|
||||
};
|
||||
24
libs/libc/BUILD.gn
Normal file
24
libs/libc/BUILD.gn
Normal file
@@ -0,0 +1,24 @@
|
||||
import("//build/libs/TEMPLATE.gni")
|
||||
import("//libs/libc/LIBC_SOURCES.gni")
|
||||
|
||||
xOS_static_library("libc") {
|
||||
sources = libc_sources
|
||||
|
||||
# Private LibC sources.
|
||||
sources += [ "init/_init.c" ]
|
||||
|
||||
if (target_arch == "arm32") {
|
||||
sources += [ "string/routines/arm32/memset.S" ]
|
||||
}
|
||||
|
||||
include_dirs = [
|
||||
"include/",
|
||||
"//libs/",
|
||||
]
|
||||
|
||||
configs = [ "//build/libs:lib_flags" ]
|
||||
|
||||
if (host == "llvm") {
|
||||
cflags = [ "-flto" ]
|
||||
}
|
||||
}
|
||||
47
libs/libc/LIBC_SOURCES.gni
Normal file
47
libs/libc/LIBC_SOURCES.gni
Normal file
@@ -0,0 +1,47 @@
|
||||
import("//build/libs/TEMPLATE.gni")
|
||||
|
||||
# LibC and LibCxx are built seperatly while LibCxx uses all LibC base.
|
||||
# This list contains a shared files which will be used to compile both of libs.
|
||||
libc_sources = [
|
||||
"ctype/ctype.c",
|
||||
"dirent/dirent.c",
|
||||
"init/_lib.c",
|
||||
"malloc/malloc.c",
|
||||
"malloc/slab.c",
|
||||
"posix/fs.c",
|
||||
"posix/identity.c",
|
||||
"posix/sched.c",
|
||||
"posix/signal.c",
|
||||
"posix/system.c",
|
||||
"posix/tasking.c",
|
||||
"posix/time.c",
|
||||
"pthread/pthread.c",
|
||||
"ptrace/ptrace.c",
|
||||
"pwd/pwd.c",
|
||||
"pwd/shadow.c",
|
||||
"setjmp/$target_arch/setjmp.S",
|
||||
"socket/socket.c",
|
||||
"stdio/printf.c",
|
||||
"stdio/scanf.c",
|
||||
"stdio/stdio.c",
|
||||
"stdlib/env.c",
|
||||
"stdlib/exit.c",
|
||||
"stdlib/pts.c",
|
||||
"stdlib/tools.c",
|
||||
"string/string.c",
|
||||
"sysdeps/xos/generic/shared_buffer.c",
|
||||
"sysdeps/unix/$target_arch/crt0.S",
|
||||
"sysdeps/unix/generic/ioctl.c",
|
||||
"termios/termios.c",
|
||||
"time/strftime.c",
|
||||
"time/time.c",
|
||||
]
|
||||
|
||||
libc_sources_for_libcxx = []
|
||||
foreach(i, libc_sources) {
|
||||
libc_sources_for_libcxx += [ string_join("",
|
||||
[
|
||||
"../libc/",
|
||||
i,
|
||||
]) ]
|
||||
}
|
||||
20
libs/libc/ctype/ctype.c
Normal file
20
libs/libc/ctype/ctype.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <ctype.h>
|
||||
|
||||
const char __ctypes[256] = {
|
||||
_C, _C, _C, _C, _C, _C, _C, _C,
|
||||
_C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C,
|
||||
_C, _C, _C, _C, _C, _C, _C, _C,
|
||||
_C, _C, _C, _C, _C, _C, _C, _C,
|
||||
(char)(_S | _B), _P, _P, _P, _P, _P, _P, _P,
|
||||
_P, _P, _P, _P, _P, _P, _P, _P,
|
||||
_N, _N, _N, _N, _N, _N, _N, _N,
|
||||
_N, _N, _P, _P, _P, _P, _P, _P,
|
||||
_P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U,
|
||||
_U, _U, _U, _U, _U, _U, _U, _U,
|
||||
_U, _U, _U, _U, _U, _U, _U, _U,
|
||||
_U, _U, _U, _P, _P, _P, _P, _P,
|
||||
_P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L,
|
||||
_L, _L, _L, _L, _L, _L, _L, _L,
|
||||
_L, _L, _L, _L, _L, _L, _L, _L,
|
||||
_L, _L, _L, _P, _P, _P, _P, _C
|
||||
};
|
||||
41
libs/libc/dirent/dirent.c
Normal file
41
libs/libc/dirent/dirent.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sysdep.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* TODO: Will be replaced with malloc */
|
||||
DIR dirarr[8];
|
||||
int nxt = 0;
|
||||
|
||||
DIR* opendir(char* name)
|
||||
{
|
||||
int fd = open(name, O_RDONLY | O_DIRECTORY);
|
||||
if (fd < 0) {
|
||||
errno = -fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Replace with malloc */
|
||||
dirarr[nxt].fd = fd;
|
||||
dirarr[nxt].size = 128;
|
||||
dirarr[nxt].allocated = 128;
|
||||
dirarr[nxt].offset = 0;
|
||||
return &dirarr[nxt++];
|
||||
}
|
||||
|
||||
int closedir(DIR* dir)
|
||||
{
|
||||
if (dir->fd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(dir->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t getdents(int fd, char* buf, size_t len)
|
||||
{
|
||||
return (ssize_t)DO_SYSCALL_3(SYS_GETDENTS, fd, buf, len);
|
||||
}
|
||||
23
libs/libc/include/assert.h
Normal file
23
libs/libc/include/assert.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _LIBC_ASSERT_H
|
||||
#define _LIBC_ASSERT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifndef assert
|
||||
#define assert(x) \
|
||||
if (!(x)) { \
|
||||
printf("Assertion failed: %s, function %s, file %s:%d\n", #x, __func__, __FILE__, __LINE__); \
|
||||
fflush(stdout); \
|
||||
abort(); \
|
||||
}
|
||||
#endif // assert
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_ASSERT_H
|
||||
135
libs/libc/include/bits/errno.h
Normal file
135
libs/libc/include/bits/errno.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#ifndef _LIBC_BITS_ERRNO_H
|
||||
#define _LIBC_BITS_ERRNO_H
|
||||
|
||||
// clang-format off
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Arg list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
#define EBADARCH 125 /* Bad arch */
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBC_BITS_ERRNO_H
|
||||
19
libs/libc/include/bits/fcntl.h
Normal file
19
libs/libc/include/bits/fcntl.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _LIBC_BITS_FCNTL_H
|
||||
#define _LIBC_BITS_FCNTL_H
|
||||
|
||||
#define SEEK_SET 0x1
|
||||
#define SEEK_CUR 0x2
|
||||
#define SEEK_END 0x3
|
||||
|
||||
/* OPEN */
|
||||
#define O_RDONLY 0x1
|
||||
#define O_WRONLY 0x2
|
||||
#define O_RDWR (O_RDONLY | O_WRONLY)
|
||||
#define O_DIRECTORY 0x4
|
||||
#define O_CREAT 0x8
|
||||
#define O_TRUNC 0x10
|
||||
#define O_APPEND 0x20
|
||||
#define O_EXCL 0x40
|
||||
#define O_EXEC 0x80
|
||||
|
||||
#endif // _LIBC_BITS_FCNTL_H
|
||||
44
libs/libc/include/bits/signal.h
Normal file
44
libs/libc/include/bits/signal.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef _LIBC_BITS_SIGNAL_H
|
||||
#define _LIBC_BITS_SIGNAL_H
|
||||
|
||||
#define SIGHUP 1
|
||||
#define SIGINT 2
|
||||
#define SIGQUIT 3
|
||||
#define SIGILL 4
|
||||
#define SIGTRAP 5
|
||||
#define SIGABRT 6
|
||||
#define SIGIOT 6
|
||||
#define SIGBUS 7
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGUSR1 10
|
||||
#define SIGSEGV 11
|
||||
#define SIGUSR2 12
|
||||
#define SIGPIPE 13
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
#define SIGSTKFLT 16
|
||||
#define SIGCHLD 17
|
||||
#define SIGCONT 18
|
||||
#define SIGSTOP 19
|
||||
#define SIGTSTP 20
|
||||
#define SIGTTIN 21
|
||||
#define SIGTTOU 22
|
||||
#define SIGURG 23
|
||||
#define SIGXCPU 24
|
||||
#define SIGXFSZ 25
|
||||
#define SIGVTALRM 26
|
||||
#define SIGPROF 27
|
||||
#define SIGWINCH 28
|
||||
#define SIGIO 29
|
||||
#define SIGPOLL SIGIO
|
||||
#define SIGPWR 30
|
||||
#define SIGSYS 31
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
|
||||
#define SIG_DFL ((sighandler_t)0)
|
||||
#define SIG_ERR ((sighandler_t)-1)
|
||||
#define SIG_IGN ((sighandler_t)1)
|
||||
|
||||
#endif // _LIBC_BITS_SIGNAL_H
|
||||
18
libs/libc/include/bits/sys/ioctls.h
Normal file
18
libs/libc/include/bits/sys/ioctls.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _LIBC_BITS_SYS_IOCTLS_H
|
||||
#define _LIBC_BITS_SYS_IOCTLS_H
|
||||
|
||||
/* TTY */
|
||||
#define TIOCGPGRP 0x0101
|
||||
#define TIOCSPGRP 0x0102
|
||||
#define TCGETS 0x0103
|
||||
#define TCSETS 0x0104
|
||||
#define TCSETSW 0x0105
|
||||
#define TCSETSF 0x0106
|
||||
|
||||
/* BGA */
|
||||
#define BGA_SWAP_BUFFERS 0x0101
|
||||
#define BGA_GET_HEIGHT 0x0102
|
||||
#define BGA_GET_WIDTH 0x0103
|
||||
#define BGA_GET_SCALE 0x0104
|
||||
|
||||
#endif // _LIBC_BITS_SYS_IOCTLS_H
|
||||
28
libs/libc/include/bits/sys/mman.h
Normal file
28
libs/libc/include/bits/sys/mman.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _LIBC_BITS_SYS_MMAN_H
|
||||
#define _LIBC_BITS_SYS_MMAN_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_STACK 0x40
|
||||
|
||||
#define PROT_READ 0x1
|
||||
#define PROT_WRITE 0x2
|
||||
#define PROT_EXEC 0x4
|
||||
#define PROT_NONE 0x0
|
||||
|
||||
struct mmap_params {
|
||||
void* addr;
|
||||
size_t size;
|
||||
int prot;
|
||||
int flags;
|
||||
int fd;
|
||||
off_t offset;
|
||||
};
|
||||
typedef struct mmap_params mmap_params_t;
|
||||
|
||||
#endif // _LIBC_BITS_SYS_MMAN_H
|
||||
13
libs/libc/include/bits/sys/ptrace.h
Normal file
13
libs/libc/include/bits/sys/ptrace.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _LIBC_BITS_SYS_PTRACE_H
|
||||
#define _LIBC_BITS_SYS_PTRACE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef int ptrace_request_t;
|
||||
#define PTRACE_TRACEME (0x1)
|
||||
#define PTRACE_CONT (0x2)
|
||||
#define PTRACE_PEEKTEXT (0x3)
|
||||
#define PTRACE_PEEKDATA (0x4)
|
||||
|
||||
#endif // _LIBC_BITS_SYS_PTRACE_H
|
||||
18
libs/libc/include/bits/sys/select.h
Normal file
18
libs/libc/include/bits/sys/select.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _LIBC_BITS_SYS_SELECT_H
|
||||
#define _LIBC_BITS_SYS_SELECT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define FD_SETSIZE 32
|
||||
|
||||
struct fd_set {
|
||||
uint8_t fds[FD_SETSIZE / 8];
|
||||
};
|
||||
typedef struct fd_set fd_set_t;
|
||||
|
||||
#define FD_SET(fd, fd_set_ptr) ((fd_set_ptr)->fds[fd / 8] |= (1 << (fd % 8)))
|
||||
#define FD_CLR(fd, fd_set_ptr) ((fd_set_ptr)->fds[fd / 8] &= ~(1 << (fd % 8)))
|
||||
#define FD_ZERO(fd_set_ptr) (memset((uint8_t*)(fd_set_ptr), 0, sizeof(fd_set_t)))
|
||||
#define FD_ISSET(fd, fd_set_ptr) ((fd_set_ptr)->fds[fd / 8] & (1 << (fd % 8)))
|
||||
|
||||
#endif // _LIBC_BITS_SYS_SELECT_H
|
||||
26
libs/libc/include/bits/sys/socket.h
Normal file
26
libs/libc/include/bits/sys/socket.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _LIBC_BITS_SYS_SOCKET_H
|
||||
#define _LIBC_BITS_SYS_SOCKET_H
|
||||
|
||||
enum SOCK_DOMAINS {
|
||||
PF_LOCAL,
|
||||
PF_INET,
|
||||
PF_INET6,
|
||||
PF_IPX,
|
||||
PF_NETLINK,
|
||||
PF_X25,
|
||||
PF_AX25,
|
||||
PF_ATMPVC,
|
||||
PF_APPLETALK,
|
||||
PF_PACKET,
|
||||
};
|
||||
|
||||
enum SOCK_TYPES {
|
||||
SOCK_STREAM,
|
||||
SOCK_DGRAM,
|
||||
SOCK_SEQPACKET,
|
||||
SOCK_RAW,
|
||||
SOCK_RDM,
|
||||
SOCK_PACKET,
|
||||
};
|
||||
|
||||
#endif // _LIBC_BITS_SYS_SOCKET_H
|
||||
64
libs/libc/include/bits/sys/stat.h
Normal file
64
libs/libc/include/bits/sys/stat.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef _LIBC_BITS_SYS_STAT_H
|
||||
#define _LIBC_BITS_SYS_STAT_H
|
||||
|
||||
#include <bits/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define S_IFMT 0xF000
|
||||
|
||||
/* MODES */
|
||||
#define S_IFSOCK 0xC000 /* [XSI] socket */
|
||||
#define S_IFLNK 0xA000 /* [XSI] symbolic link */
|
||||
#define S_IFREG 0x8000 /* [XSI] regular */
|
||||
#define S_IFBLK 0x6000 /* [XSI] block special */
|
||||
#define S_IFDIR 0x4000 /* [XSI] directory */
|
||||
#define S_IFCHR 0x2000 /* [XSI] character special */
|
||||
#define S_IFIFO 0x1000 /* [XSI] named pipe (fifo) */
|
||||
|
||||
#define S_ISUID 0x0800
|
||||
#define S_ISGID 0x0400
|
||||
#define S_ISVTX 0x0200
|
||||
|
||||
/* Read, write, execute/search by owner */
|
||||
#define S_IRWXU 0x01c0
|
||||
#define S_IRUSR 0x0100
|
||||
#define S_IWUSR 0x0080
|
||||
#define S_IXUSR 0x0040
|
||||
/* Read, write, execute/search by group */
|
||||
#define S_IRWXG 0x0038
|
||||
#define S_IRGRP 0x0020
|
||||
#define S_IWGRP 0x0010
|
||||
#define S_IXGRP 0x0008
|
||||
/* Read, write, execute/search by others */
|
||||
#define S_IRWXO 0x0007
|
||||
#define S_IROTH 0x0004
|
||||
#define S_IWOTH 0x0002
|
||||
#define S_IXOTH 0x0001
|
||||
|
||||
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
|
||||
#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
|
||||
#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK)
|
||||
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
|
||||
#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO)
|
||||
#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK)
|
||||
|
||||
struct stat {
|
||||
dev_t st_dev; /* ID of device containing file */
|
||||
ino_t st_ino; /* Inode number */
|
||||
mode_t st_mode; /* File type and mode */
|
||||
nlink_t st_nlink; /* Number of hard links */
|
||||
uid_t st_uid; /* User ID of owner */
|
||||
gid_t st_gid; /* Group ID of owner */
|
||||
dev_t st_rdev; /* Device ID (if special file) */
|
||||
off_t st_size; /* Total size, in bytes */
|
||||
uint32_t st_blksize; /* Block size for filesystem I/O */
|
||||
uint32_t st_blocks; /* Number of 512B blocks allocated */
|
||||
|
||||
struct timespec st_atim; /* Time of last access */
|
||||
struct timespec st_mtim; /* Time of last modification */
|
||||
struct timespec st_ctim; /* Time of last status change */
|
||||
};
|
||||
typedef struct stat stat_t;
|
||||
|
||||
#endif // _LIBC_BITS_SYS_STAT_H
|
||||
15
libs/libc/include/bits/sys/utsname.h
Normal file
15
libs/libc/include/bits/sys/utsname.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _LIBC_BITS_SYS_UTSNAME_H
|
||||
#define _LIBC_BITS_SYS_UTSNAME_H
|
||||
|
||||
#define UTSNAME_ENTRY_LEN 65
|
||||
|
||||
struct utsname {
|
||||
char sysname[UTSNAME_ENTRY_LEN];
|
||||
char nodename[UTSNAME_ENTRY_LEN];
|
||||
char release[UTSNAME_ENTRY_LEN];
|
||||
char version[UTSNAME_ENTRY_LEN];
|
||||
char machine[UTSNAME_ENTRY_LEN];
|
||||
};
|
||||
typedef struct utsname utsname_t;
|
||||
|
||||
#endif // _LIBC_BITS_SYS_UTSNAME_H
|
||||
7
libs/libc/include/bits/sys/wait.h
Normal file
7
libs/libc/include/bits/sys/wait.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef _LIBC_BITS_SYS_WAIT_H
|
||||
#define _LIBC_BITS_SYS_WAIT_H
|
||||
|
||||
#define WNOHANG 0x1
|
||||
#define WUNTRACED 0x2
|
||||
|
||||
#endif // _LIBC_BITS_SYS_WAIT_H
|
||||
1129
libs/libc/include/bits/syscalls.h
Normal file
1129
libs/libc/include/bits/syscalls.h
Normal file
File diff suppressed because it is too large
Load Diff
13
libs/libc/include/bits/thread.h
Normal file
13
libs/libc/include/bits/thread.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _LIBC_BITS_THREAD_H
|
||||
#define _LIBC_BITS_THREAD_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct thread_create_params {
|
||||
uint32_t entry_point;
|
||||
uint32_t stack_start;
|
||||
uint32_t stack_size;
|
||||
};
|
||||
typedef struct thread_create_params thread_create_params_t;
|
||||
|
||||
#endif // _LIBC_BITS_THREAD_H
|
||||
56
libs/libc/include/bits/time.h
Normal file
56
libs/libc/include/bits/time.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef _LIBC_BITS_TIME_H
|
||||
#define _LIBC_BITS_TIME_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct timeval {
|
||||
time_t tv_sec;
|
||||
uint32_t tv_usec;
|
||||
};
|
||||
typedef struct timeval timeval_t;
|
||||
|
||||
#define DST_NONE 0 /* not on dst */
|
||||
#define DST_USA 1 /* USA style dst */
|
||||
#define DST_AUST 2 /* Australian style dst */
|
||||
#define DST_WET 3 /* Western European dst */
|
||||
#define DST_MET 4 /* Middle European dst */
|
||||
#define DST_EET 5 /* Eastern European dst */
|
||||
#define DST_CAN 6 /* Canada */
|
||||
struct timezone {
|
||||
int tz_minuteswest; /* minutes west of Greenwich */
|
||||
int tz_dsttime; /* type of dst correction */
|
||||
};
|
||||
typedef struct timezone timezone_t;
|
||||
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
uint32_t tv_nsec;
|
||||
};
|
||||
typedef struct timespec timespec_t;
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
typedef struct tm tm_t;
|
||||
|
||||
typedef enum {
|
||||
CLOCK_REALTIME,
|
||||
CLOCK_MONOTONIC,
|
||||
CLOCK_PROCESS_CPUTIME_ID,
|
||||
CLOCK_THREAD_CPUTIME_ID,
|
||||
} clockid_t;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_BITS_TIME_H
|
||||
43
libs/libc/include/bits/types.h
Normal file
43
libs/libc/include/bits/types.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _LIBC_BITS_TYPES_H
|
||||
#define _LIBC_BITS_TYPES_H
|
||||
|
||||
typedef char __int8_t;
|
||||
typedef short __int16_t;
|
||||
typedef int __int32_t;
|
||||
typedef long long __int64_t;
|
||||
typedef unsigned char __uint8_t;
|
||||
typedef unsigned short __uint16_t;
|
||||
typedef unsigned int __uint32_t;
|
||||
typedef unsigned long long __uint64_t;
|
||||
|
||||
typedef __uint32_t __dev_t; /* Type of device numbers. */
|
||||
typedef __uint32_t __uid_t; /* Type of user identifications. */
|
||||
typedef __uint32_t __gid_t; /* Type of group identifications. */
|
||||
typedef __uint32_t __ino_t; /* Type of file serial numbers. */
|
||||
typedef __uint64_t __ino64_t; /* Type of file serial numbers (LFS).*/
|
||||
typedef __uint16_t __mode_t; /* Type of file attribute bitmasks. */
|
||||
typedef __uint32_t __nlink_t; /* Type of file link counts. */
|
||||
typedef __int64_t __off64_t; /* Type of file sizes and offsets (LFS). */
|
||||
typedef __uint32_t __pid_t; /* Type of process identifications. */
|
||||
typedef __uint32_t __fsid_t; /* Type of file system IDs. */
|
||||
typedef __uint32_t __time_t; /* Seconds since the Epoch. */
|
||||
|
||||
#if defined(__x86_64__) || defined(__aarch64__) || (defined(__riscv) && (__riscv_xlen == 64))
|
||||
#define BITS64
|
||||
typedef __int64_t __off_t; /* Type of file sizes and offsets. */
|
||||
|
||||
#ifndef LONG_TYPE_SIZE
|
||||
#define LONG_TYPE_SIZE (8)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define BITS32
|
||||
typedef __int32_t __off_t; /* Type of file sizes and offsets. */
|
||||
|
||||
#ifndef LONG_TYPE_SIZE
|
||||
#define LONG_TYPE_SIZE (4)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _LIBC_BITS_TYPES_H
|
||||
38
libs/libc/include/ctype.h
Normal file
38
libs/libc/include/ctype.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef _LIBC_CTYPE_H
|
||||
#define _LIBC_CTYPE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define _U 01
|
||||
#define _L 02
|
||||
#define _N 04
|
||||
#define _S 010
|
||||
#define _P 020
|
||||
#define _C 040
|
||||
#define _X 0100
|
||||
#define _B 0200
|
||||
|
||||
extern const char __ctypes[256];
|
||||
|
||||
static inline int isalnum(int c) { return __ctypes[(unsigned char)(c)] & (_U | _L | _N); }
|
||||
static inline int isalpha(int c) { return __ctypes[(unsigned char)(c)] & (_U | _L); }
|
||||
static inline int iscntrl(int c) { return __ctypes[(unsigned char)(c)] & (_C); }
|
||||
static inline int isdigit(int c) { return __ctypes[(unsigned char)(c)] & (_N); }
|
||||
static inline int isxdigit(int c) { return __ctypes[(unsigned char)(c)] & (_N | _X); }
|
||||
static inline int isspace(int c) { return __ctypes[(unsigned char)(c)] & (_S); }
|
||||
static inline int ispunct(int c) { return __ctypes[(unsigned char)(c)] & (_P); }
|
||||
static inline int isprint(int c) { return __ctypes[(unsigned char)(c)] & (_P | _U | _L | _N | _B); }
|
||||
static inline int isgraph(int c) { return __ctypes[(unsigned char)(c)] & (_P | _U | _L | _N); }
|
||||
static inline int islower(int c) { return (__ctypes[(unsigned char)(c)] & (_U | _L)) == _L; }
|
||||
static inline int isupper(int c) { return (__ctypes[(unsigned char)(c)] & (_U | _L)) == _U; }
|
||||
static inline int tolower(int c) { return isupper(c) ? (c) - 'a' + 'A' : c; }
|
||||
static inline int toupper(int c) { return islower(c) ? (c) - 'A' + 'a' : c; }
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _LIBC_CTYPE_H */
|
||||
31
libs/libc/include/dirent.h
Normal file
31
libs/libc/include/dirent.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _LIBC_DIRENT_H
|
||||
#define _LIBC_DIRENT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct __dirstream {
|
||||
int fd;
|
||||
size_t size; /* size of dir data */
|
||||
size_t allocated; /* size of data holder block */
|
||||
size_t offset;
|
||||
};
|
||||
typedef struct __dirstream DIR;
|
||||
|
||||
struct __dirent {
|
||||
uint32_t d_ino; /* Inode number */
|
||||
uint32_t d_off; /* Offset to next linux_dirent */
|
||||
uint16_t d_reclen; /* Length of this linux_dirent */
|
||||
char d_name[]; /* Filename (null-terminated) */
|
||||
};
|
||||
typedef struct __dirent dirent_t;
|
||||
|
||||
ssize_t getdents(int fd, char* buf, size_t len);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _LIBC_DIRENT_H */
|
||||
10
libs/libc/include/errno.h
Normal file
10
libs/libc/include/errno.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _LIBC_ERRNO_H
|
||||
#define _LIBC_ERRNO_H
|
||||
|
||||
#include <bits/errno.h>
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define set_errno(x) (errno = x)
|
||||
|
||||
#endif
|
||||
15
libs/libc/include/fcntl.h
Normal file
15
libs/libc/include/fcntl.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _LIBC_FCNTL_H
|
||||
#define _LIBC_FCNTL_H
|
||||
|
||||
#include <bits/fcntl.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int open(const char* pathname, int flags, ...);
|
||||
int creat(const char* path, mode_t mode);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_FCNTL_H
|
||||
98
libs/libc/include/limits.h
Normal file
98
libs/libc/include/limits.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#ifndef _LIBC_LIMITS_H
|
||||
#define _LIBC_LIMITS_H
|
||||
|
||||
#include <bits/types.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
|
||||
#define HOST_NAME_MAX 64
|
||||
|
||||
#define PATH_MAX 4096
|
||||
#if !defined MAXPATHLEN && defined PATH_MAX
|
||||
#define MAXPATHLEN PATH_MAX
|
||||
#endif
|
||||
|
||||
#define NAME_MAX 255
|
||||
|
||||
#define TTY_NAME_MAX 32
|
||||
|
||||
#define PIPE_BUF 4096
|
||||
|
||||
#define INT_MAX INT32_MAX
|
||||
#define INT_MIN INT32_MIN
|
||||
|
||||
#define UINT_MAX UINT32_MAX
|
||||
|
||||
#define CHAR_BIT 8
|
||||
#define SCHAR_MIN (-128)
|
||||
#define SCHAR_MAX 127
|
||||
#define UCHAR_MAX 255
|
||||
|
||||
#define SHRT_MAX 32768
|
||||
#define SHRT_MIN (-SHRT_MAX - 1)
|
||||
|
||||
#define USHRT_MAX 65535
|
||||
|
||||
#if LONG_TYPE_SIZE == 4
|
||||
#define LONG_MAX 2147483647L
|
||||
#define LONG_MIN (-LONG_MAX - 1L)
|
||||
#define ULONG_MAX 4294967295UL
|
||||
#elif LONG_TYPE_SIZE == 8
|
||||
#define LONG_MAX 9223372036854775807L
|
||||
#define LONG_MIN (-LONG_MAX - 1L)
|
||||
#define ULONG_MAX 18446744073709551615UL
|
||||
#endif
|
||||
|
||||
#define LONG_LONG_MAX 9223372036854775807LL
|
||||
#define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL)
|
||||
|
||||
#define LLONG_MAX LONG_LONG_MAX
|
||||
#define LLONG_MIN LONG_LONG_MIN
|
||||
|
||||
#define ULONG_LONG_MAX 18446744073709551615ULL
|
||||
#define ULLONG_MAX ULONG_LONG_MAX
|
||||
|
||||
#define CHAR_MIN SCHAR_MIN
|
||||
#define CHAR_MAX SCHAR_MAX
|
||||
|
||||
#define CHAR_WIDTH 8
|
||||
#define SCHAR_WIDTH 8
|
||||
#define UCHAR_WIDTH 8
|
||||
|
||||
#define SHRT_WIDTH 16
|
||||
#define USHRT_WIDTH 16
|
||||
|
||||
#define INT_WIDTH 32
|
||||
#define UINT_WIDTH 32
|
||||
|
||||
#if LONG_TYPE_SIZE == 4
|
||||
#define LONG_WIDTH 32
|
||||
#define ULONG_WIDTH 32
|
||||
#else
|
||||
#define LONG_WIDTH 64
|
||||
#define ULONG_WIDTH 64
|
||||
#endif
|
||||
|
||||
#define LLONG_WIDTH 64
|
||||
#define ULLONG_WIDTH 64
|
||||
|
||||
#define ARG_MAX 65536
|
||||
|
||||
#define PTHREAD_STACK_MIN 65536
|
||||
|
||||
#define SSIZE_MAX 2147483647
|
||||
|
||||
#define LINK_MAX 4096
|
||||
|
||||
#define TZNAME_MAX 64
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_LIMITS_H
|
||||
15
libs/libc/include/pthread.h
Normal file
15
libs/libc/include/pthread.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _LIBC_PTHREAD_H
|
||||
#define _LIBC_PTHREAD_H
|
||||
|
||||
#include <bits/thread.h>
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int pthread_create(void* func);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _LIBC_PTHREAD_H */
|
||||
28
libs/libc/include/pwd.h
Normal file
28
libs/libc/include/pwd.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _LIBC_PWD_H
|
||||
#define _LIBC_PWD_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct passwd {
|
||||
char* pw_name;
|
||||
char* pw_passwd;
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
char* pw_gecos;
|
||||
char* pw_dir;
|
||||
char* pw_shell;
|
||||
};
|
||||
typedef struct passwd passwd_t;
|
||||
|
||||
void setpwent();
|
||||
void endpwent();
|
||||
passwd_t* getpwent();
|
||||
passwd_t* getpwuid(uid_t uid);
|
||||
passwd_t* getpwnam(const char* name);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_PWD_H
|
||||
13
libs/libc/include/sched.h
Normal file
13
libs/libc/include/sched.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _LIBC_SCHED_H
|
||||
#define _LIBC_SCHED_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
void sched_yield();
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SCHED_H
|
||||
60
libs/libc/include/setjmp.h
Normal file
60
libs/libc/include/setjmp.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef _LIBC_SETJMP_H
|
||||
#define _LIBC_SETJMP_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifdef __i386__
|
||||
/**
|
||||
* x86_32 (6 * 4):
|
||||
* - ebx
|
||||
* - esp
|
||||
* - ebp
|
||||
* - esi
|
||||
* - edi
|
||||
* - return address
|
||||
*/
|
||||
#define _jblen (6 * 4)
|
||||
#elif defined(__x86_64__)
|
||||
/**
|
||||
* x86_64 (8 * 8):
|
||||
* - rip, rbp, rsp, rbx, r12, r13, r14, r15
|
||||
*/
|
||||
#define _jblen (8 * 8)
|
||||
#elif defined(__arm__)
|
||||
/**
|
||||
* ARMv7 (11 * 4 + 8 * 8):
|
||||
* - r4 - r12, sp, lr
|
||||
* - d8-d15
|
||||
*/
|
||||
#define _jblen (11 * 4 + 8 * 8)
|
||||
#elif defined(__aarch64__)
|
||||
/**
|
||||
* ARMv8 (22 * 8):
|
||||
* - x19-x28, x29(fp), x30(lr), x31(sp), x4(alignment)
|
||||
* - d8-d15
|
||||
*/
|
||||
#define _jblen (22 * 8)
|
||||
#elif (defined(__riscv) && (__riscv_xlen == 64))
|
||||
/**
|
||||
* RISC-V 64bit (14 * 8):
|
||||
* - s0-s11, ra, sp
|
||||
*/
|
||||
#define _jblen (14 * 8)
|
||||
#endif
|
||||
|
||||
struct __jmp_buf {
|
||||
char regs[_jblen];
|
||||
};
|
||||
|
||||
typedef struct __jmp_buf jmp_buf[1];
|
||||
typedef struct __jmp_buf sigjmp_buf[1];
|
||||
|
||||
extern int setjmp(jmp_buf);
|
||||
extern void longjmp(jmp_buf, int val);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
30
libs/libc/include/shadow.h
Normal file
30
libs/libc/include/shadow.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef _LIBC_SHADOW_H
|
||||
#define _LIBC_SHADOW_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct spwd {
|
||||
char* sp_namp;
|
||||
char* sp_pwdp;
|
||||
int sp_lstchg;
|
||||
int sp_min;
|
||||
int sp_max;
|
||||
int sp_warn;
|
||||
int sp_inact;
|
||||
int sp_expire;
|
||||
uint32_t sp_flag;
|
||||
};
|
||||
|
||||
typedef struct spwd spwd_t;
|
||||
|
||||
void setspent();
|
||||
void endspent();
|
||||
spwd_t* getspent();
|
||||
spwd_t* getspnam(const char* name);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SHADOW_H
|
||||
17
libs/libc/include/signal.h
Normal file
17
libs/libc/include/signal.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _LIBC_SIGNAL_H
|
||||
#define _LIBC_SIGNAL_H
|
||||
|
||||
#include <bits/signal.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int kill(pid_t pid, int sig);
|
||||
int sigaction(int signo, sighandler_t callback);
|
||||
sighandler_t signal(int signo, sighandler_t callback);
|
||||
int raise(int sig);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SIGNAL_H
|
||||
15
libs/libc/include/stdarg.h
Normal file
15
libs/libc/include/stdarg.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _LIBC_STDARG_H
|
||||
#define _LIBC_STDARG_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define va_start(v, l) __builtin_va_start(v, l)
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v, l) __builtin_va_arg(v, l)
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_STDARG_H
|
||||
41
libs/libc/include/stdatomic.h
Normal file
41
libs/libc/include/stdatomic.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef _LIBC_STDATOMIC_H
|
||||
#define _LIBC_STDATOMIC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||
memory_order_consume = __ATOMIC_CONSUME,
|
||||
memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||
memory_order_release = __ATOMIC_RELEASE,
|
||||
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||
memory_order_seq_cst = __ATOMIC_SEQ_CST
|
||||
} memory_order;
|
||||
|
||||
typedef _Atomic bool atomic_bool;
|
||||
typedef _Atomic char atomic_char;
|
||||
typedef _Atomic signed char atomic_schar;
|
||||
typedef _Atomic unsigned char atomic_uchar;
|
||||
typedef _Atomic short atomic_short;
|
||||
typedef _Atomic unsigned short atomic_ushort;
|
||||
typedef _Atomic int atomic_int;
|
||||
typedef _Atomic unsigned int atomic_uint;
|
||||
typedef _Atomic long atomic_long;
|
||||
typedef _Atomic unsigned long atomic_ulong;
|
||||
typedef _Atomic long long atomic_llong;
|
||||
typedef _Atomic unsigned long long atomic_ullong;
|
||||
|
||||
#define atomic_add_explicit(x, val, ord) (__atomic_add_fetch(x, val, ord))
|
||||
#define atomic_store_explicit(x, val, ord) (__atomic_store_n(x, val, ord))
|
||||
#define atomic_load_explicit(x, ord) (__atomic_load_n(x, ord))
|
||||
|
||||
#define atomic_add(x, val) (atomic_add_explicit(x, val, __ATOMIC_SEQ_CST))
|
||||
#define atomic_store(x, val) (atomic_store_explicit(x, val, __ATOMIC_SEQ_CST))
|
||||
#define atomic_load(x) (atomic_load_explicit(x, __ATOMIC_SEQ_CST))
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif //_LIBC_STDATOMIC_H
|
||||
17
libs/libc/include/stdbool.h
Normal file
17
libs/libc/include/stdbool.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _LIBC_STDBOOL_H
|
||||
#define _LIBC_STDBOOL_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifndef __bool_true_false_are_defined
|
||||
#define bool _Bool
|
||||
#define true (1)
|
||||
#define false (0)
|
||||
#define __bool_true_false_are_defined 1
|
||||
#endif // __bool_true_false_are_defined
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif //_LIBC_STDBOOL_H
|
||||
43
libs/libc/include/stddef.h
Normal file
43
libs/libc/include/stddef.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _LIBC_STDDEF_H
|
||||
#define _LIBC_STDDEF_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifdef __i386__
|
||||
#if defined(__clang__)
|
||||
typedef unsigned int size_t;
|
||||
typedef int ssize_t;
|
||||
typedef int ptrdiff_t;
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
typedef unsigned long size_t;
|
||||
typedef long ssize_t;
|
||||
typedef long ptrdiff_t;
|
||||
#endif
|
||||
#elif __x86_64__
|
||||
typedef unsigned long size_t;
|
||||
typedef long long ssize_t;
|
||||
typedef long long ptrdiff_t;
|
||||
#elif __arm__
|
||||
typedef unsigned int size_t;
|
||||
typedef int ssize_t;
|
||||
typedef int ptrdiff_t;
|
||||
#elif __aarch64__
|
||||
typedef unsigned long size_t;
|
||||
typedef long long ssize_t;
|
||||
typedef long long ptrdiff_t;
|
||||
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||
typedef unsigned long size_t;
|
||||
typedef long long ssize_t;
|
||||
typedef long long ptrdiff_t;
|
||||
#endif
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_STDDEF_H
|
||||
110
libs/libc/include/stdint.h
Normal file
110
libs/libc/include/stdint.h
Normal file
@@ -0,0 +1,110 @@
|
||||
#ifndef _LIBC_STDINT_H
|
||||
#define _LIBC_STDINT_H
|
||||
|
||||
#include <bits/types.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifndef __stdints_defined
|
||||
#define __stdints_defined
|
||||
typedef __int8_t int8_t;
|
||||
typedef __int16_t int16_t;
|
||||
typedef __int32_t int32_t;
|
||||
typedef __int64_t int64_t;
|
||||
typedef __uint8_t uint8_t;
|
||||
typedef __uint16_t uint16_t;
|
||||
typedef __uint32_t uint32_t;
|
||||
typedef __uint64_t uint64_t;
|
||||
#endif // __stdints_defined
|
||||
|
||||
#ifndef __stdleastints_defined
|
||||
#define __stdleastints_defined
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
#endif // __stdleastints_defined
|
||||
|
||||
#ifndef __stdfastints_defined
|
||||
#define __stdfastints_defined
|
||||
typedef int32_t int_fast8_t;
|
||||
typedef int32_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint32_t uint_fast8_t;
|
||||
typedef uint32_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
#endif // __stdfastints_defined
|
||||
|
||||
#ifndef __stdptrints_defined
|
||||
#define __stdptrints_defined
|
||||
#ifdef BITS64
|
||||
typedef int64_t intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
#elif defined(BITS32)
|
||||
typedef int32_t intptr_t;
|
||||
typedef uint32_t uintptr_t;
|
||||
#else
|
||||
#error Unknown BITSx?
|
||||
#endif
|
||||
#endif // __stdptrints_defined
|
||||
|
||||
#ifndef __stdmaxints_defined
|
||||
#define __stdmaxints_defined
|
||||
typedef int64_t intmax_t;
|
||||
#endif // __stdmaxints_defined
|
||||
|
||||
#ifndef __stdintmacroses_defined
|
||||
#define __stdintmacroses_defined
|
||||
#define INT8_MAX 0x7f
|
||||
#define INT8_MIN (-INT8_MAX - 1)
|
||||
#define UINT8_MAX (INT8_MAX * 2 + 1)
|
||||
|
||||
#define INT16_MAX 0x7fff
|
||||
#define INT16_MIN (-INT16_MAX - 1)
|
||||
#define UINT16_MAX (INT16_MAX * 2U + 1U)
|
||||
|
||||
#define INT32_MAX 0x7fffffffL
|
||||
#define INT32_MIN (-INT32_MAX - 1L)
|
||||
#define UINT32_MAX (INT32_MAX * 2UL + 1UL)
|
||||
|
||||
#define INT64_MAX 0x7fffffffffffffffLL
|
||||
#define INT64_MIN (-INT64_MAX - 1LL)
|
||||
#define UINT64_MAX (INT64_MAX * 2ULL + 1ULL)
|
||||
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
#endif // __stdintmacroses_defined
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif //_LIBC_STDINT_H
|
||||
112
libs/libc/include/stdio.h
Normal file
112
libs/libc/include/stdio.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef _LIBC_STDIO_H
|
||||
#define _LIBC_STDIO_H
|
||||
|
||||
#include <bits/fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define _IOFBF 0 /* setvbuf should set fully buffered */
|
||||
#define _IOLBF 1 /* setvbuf should set line buffered */
|
||||
#define _IONBF 2 /* setvbuf should set unbuffered */
|
||||
#define BUFSIZ 1024 /* size of buffer used by setbuf */
|
||||
#define EOF (-1)
|
||||
#define UNGOTC_EMPTY (-0x400)
|
||||
|
||||
/* Define stdin, stdout and stderr macros for better readability. */
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
#define STDERR 2
|
||||
|
||||
typedef struct __fbuf __fbuf_t;
|
||||
typedef struct __rwbuf __rwbuf_t;
|
||||
typedef struct __file FILE;
|
||||
|
||||
extern FILE* stdin;
|
||||
extern FILE* stdout;
|
||||
extern FILE* stderr;
|
||||
|
||||
/* Open a file. Returns a struct representing an open file allocated on the
|
||||
heap. The possible mode combinations are: r, w, a, r+ and w+. Returns NULL
|
||||
if anything goes wrong. */
|
||||
FILE* fopen(const char* filename, const char* mode);
|
||||
|
||||
/* Deallocate the file and close it. Any remaining data is flushed. Returns 0
|
||||
on success, or EOF on failure. */
|
||||
int fclose(FILE* stream);
|
||||
|
||||
/* Read up to 'count' objects, each of 'size' size into 'buf' from 'stream' */
|
||||
size_t fread(void* buf, size_t size, size_t count, FILE* stream);
|
||||
|
||||
/* Write up to 'count' objects, each of 'size' size into 'stream' from 'buf'. */
|
||||
size_t fwrite(const void* buf, size_t size, size_t count, FILE* stream);
|
||||
|
||||
/* Set the file indicator to 'offset', starting from 'origin'. */
|
||||
int fseek(FILE* stream, uint32_t offset, int origin);
|
||||
|
||||
/* Flush all buffers, writing all stored data into the stored device/file. */
|
||||
int fflush(FILE* stream);
|
||||
|
||||
/* Put a single character to the given stream. 'putchar' will write the char
|
||||
to stdout. */
|
||||
int fputc(int c, FILE* stream);
|
||||
int putc(int c, FILE* stream) __use_instead("fputc");
|
||||
int putchar(int c);
|
||||
|
||||
/* Put a string to the given stream with a newline at the end, 'puts' writes
|
||||
to stdout by default. */
|
||||
int fputs(const char* s, FILE* stream);
|
||||
int puts(const char* s);
|
||||
|
||||
/* Read/place back a char from the given stream. 'getchar' will get a single
|
||||
char from stdin. */
|
||||
int fgetc(FILE* stream);
|
||||
int getc(FILE* stream) __use_instead("fgets");
|
||||
int getchar();
|
||||
int ungetc(int c, FILE* stream);
|
||||
|
||||
/* Get a string from the given stream, of max 'size'. */
|
||||
char* fgets(char* str, int size, FILE* stream);
|
||||
char* gets(char* str);
|
||||
|
||||
/* Checks whether the end-of-File indicator associated with stream is set,
|
||||
returning a value different from zero if it is. */
|
||||
int feof(FILE* stream);
|
||||
|
||||
/* Set the buffering mode of the stream. 'mode' can either be _IOFBF, _IOLBF
|
||||
or _IONBF. If 'buf' is NULL, resize the internal buffer to 'size'. If 'buf'
|
||||
is instead not NULL, it changes the internal buffer to the user provided
|
||||
one of size 'size'. Return -1 if something goes wrong. */
|
||||
int setvbuf(FILE* stream, char* buf, int mode, size_t size);
|
||||
|
||||
/* Set the buffering mode to full buffering if 'buf' is provided. The minimum
|
||||
size of the buffer should be BUFSIZ, or it could lead to a buffer overflow.
|
||||
If 'buf' is NULL, buffering it turned off. */
|
||||
void setbuf(FILE* stream, char* buf);
|
||||
|
||||
/* Set the buffering mode of the given stream to _IOLBF. */
|
||||
void setlinebuf(FILE* stream);
|
||||
|
||||
/* Works the same as the C standard says, check there. */
|
||||
int vsnprintf(char* buf, size_t n, const char* fmt, va_list arg);
|
||||
int vsprintf(char* buf, const char* fmt, va_list arg);
|
||||
int snprintf(char* buf, size_t n, const char* fmt, ...);
|
||||
int sprintf(char* buf, const char* fmt, ...);
|
||||
int fprintf(FILE* stream, const char* fmt, ...);
|
||||
int printf(const char* fmt, ...);
|
||||
|
||||
/* Scan a buffer for the provided values. Works similarly to printf, but it
|
||||
reads instead of writes. 'scanf' reads from stdin instead of a buffer. Note
|
||||
that using these functions may be unsafe. Never trust the user! */
|
||||
int vsscanf(const char* buf, const char* fmt, va_list arg);
|
||||
int sscanf(const char* buf, const char* fmt, ...);
|
||||
int scanf(const char* fmt, ...);
|
||||
|
||||
/* Dump information about the stream to stdout. */
|
||||
int __stream_info(FILE* stream);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_STDIO_H
|
||||
64
libs/libc/include/stdlib.h
Normal file
64
libs/libc/include/stdlib.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef _LIBC_STDLIB_H
|
||||
#define _LIBC_STDLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/environ.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define EXIT_FAILURE 1
|
||||
#define EXIT_SUCCESS 0
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#ifndef max
|
||||
#define max(a, b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
#endif /* max */
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
#endif /* min */
|
||||
#endif /* NOMINMAX */
|
||||
|
||||
static inline int abs(int i)
|
||||
{
|
||||
return i < 0 ? -i : i;
|
||||
}
|
||||
|
||||
/* malloc */
|
||||
extern void* malloc(size_t);
|
||||
extern void free(void*);
|
||||
extern void* calloc(size_t, size_t);
|
||||
extern void* realloc(void*, size_t);
|
||||
|
||||
/* tools */
|
||||
int atoi(const char* s);
|
||||
|
||||
/* exit */
|
||||
void abort() __attribute__((noreturn));
|
||||
void exit(int status) __attribute__((noreturn));
|
||||
|
||||
/* pts */
|
||||
int posix_openpt(int flags);
|
||||
int ptsname_r(int fd, char* buf, size_t buflen);
|
||||
char* ptsname(int fd);
|
||||
|
||||
/* env */
|
||||
int putenv(char* string);
|
||||
char* getenv(const char* name);
|
||||
int setenv(const char* name, const char* value, int overwrite);
|
||||
int unsetenv(const char* name);
|
||||
|
||||
long strtol(const char* nptr, char** endptr, int base);
|
||||
void qsort(void* base, size_t nitems, size_t size, int (*compar)(const void*, const void*));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_STDLIB_H
|
||||
57
libs/libc/include/string.h
Normal file
57
libs/libc/include/string.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef _LIBC_STRING_H
|
||||
#define _LIBC_STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Set 'nbytes' to 'fill' starting from 'dest'. */
|
||||
void* memset(void* dest, int fill, size_t nbytes);
|
||||
|
||||
/* Move 'nbytes' from 'src' to 'dest' */
|
||||
void* memmove(void* dest, const void* __restrict src, size_t nbytes);
|
||||
|
||||
/* Copy 'nbytes' from 'src' to 'dest'. See the comment in the source file
|
||||
about optimization and restricting pointers. */
|
||||
void* memcpy(void* __restrict dest, const void* __restrict src, size_t nbytes);
|
||||
|
||||
/* Copy 'nbytes' from 'src' to 'dest', stopping if the current byte matches
|
||||
'stop'. Note that the stop byte also gets copied over. */
|
||||
void* memccpy(void* dest, const void* __restrict src, int stop, size_t nbytes);
|
||||
|
||||
/* Compare 'nbytes' from 'src1' and 'src2'. Return 0 if all the bytes match,
|
||||
otherwise return the difference. */
|
||||
int memcmp(const void* src1, const void* src2, size_t nbytes);
|
||||
void* memchr(const void* ptr, int c, size_t size);
|
||||
|
||||
/* Calculate the string length starting from 'str'. */
|
||||
size_t strlen(const char* str);
|
||||
|
||||
/* Copy 'src' into 'dest' until it finds a null byte in the source string.
|
||||
Note that this is dangerous because it writes memory no matter the size
|
||||
the 'dest' buffer is. */
|
||||
char* strcpy(char* dest, const char* src);
|
||||
int strcmp(const char* a, const char* b);
|
||||
int strncmp(const char* a, const char* b, size_t nbytes);
|
||||
|
||||
/* Copy 'src' into 'dest' until it finds a null byte or reaches the 'nbytes'
|
||||
limit provided by the user. This is the recommended way of copying strings,
|
||||
instead of using regular strcpy. Note that this will fill the 'dest' buffer
|
||||
with null bytes if the amount of copied bytes is lower than 'nbytes'. */
|
||||
char* strncpy(char* dest, const char* src, size_t nbytes);
|
||||
|
||||
/* Returns a pointer to the first occurrence of character in the C string str. */
|
||||
char* strchr(const char* s, int c);
|
||||
|
||||
char* strtok_r(char* str, const char* delim, char** saveptr);
|
||||
char* strtok(char* str, const char* delim);
|
||||
|
||||
char* strstr(const char* haystack, const char* needle);
|
||||
char* strcat(char* dest, const char* src);
|
||||
char* strrchr(const char* str, int ch);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_STRING_H
|
||||
4
libs/libc/include/sys/_structs.h
Normal file
4
libs/libc/include/sys/_structs.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#ifndef _LIBC_SYS__STRUCTS_H
|
||||
#define _LIBC_SYS__STRUCTS_H
|
||||
|
||||
#endif
|
||||
10
libs/libc/include/sys/_types/_devs.h
Normal file
10
libs/libc/include/sys/_types/_devs.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _LIBC_SYS__TYPES__DEVS_H
|
||||
#define _LIBC_SYS__TYPES__DEVS_H
|
||||
|
||||
#define MINORBITS 20
|
||||
#define MINORMASK ((1U << MINORBITS) - 1)
|
||||
#define major(dev) ((unsigned int)((dev) >> MINORBITS))
|
||||
#define minor(dev) ((unsigned int)((dev)&MINORMASK))
|
||||
#define makedev(ma, mi) (((ma) << MINORBITS) | (mi))
|
||||
|
||||
#endif // _LIBC_SYS__TYPES__DEVS_H
|
||||
77
libs/libc/include/sys/_types/_ints.h
Normal file
77
libs/libc/include/sys/_types/_ints.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef _LIBC_SYS__TYPES__INTS_H
|
||||
#define _LIBC_SYS__TYPES__INTS_H
|
||||
|
||||
#include <bits/types.h>
|
||||
|
||||
#ifndef __stdints_defined
|
||||
#define __stdints_defined
|
||||
typedef __int8_t int8_t;
|
||||
typedef __int16_t int16_t;
|
||||
typedef __int32_t int32_t;
|
||||
typedef __int64_t int64_t;
|
||||
typedef __uint8_t uint8_t;
|
||||
typedef __uint16_t uint16_t;
|
||||
typedef __uint32_t uint32_t;
|
||||
typedef __uint64_t uint64_t;
|
||||
#endif // __stdints_defined
|
||||
|
||||
#ifndef __dev_t_defined
|
||||
#define __dev_t_defined
|
||||
typedef __dev_t dev_t;
|
||||
#endif // __dev_t_defined
|
||||
|
||||
#ifndef __uid_t_defined
|
||||
#define __uid_t_defined
|
||||
typedef __uid_t uid_t;
|
||||
#endif // __uid_t_defined
|
||||
|
||||
#ifndef __gid_t_defined
|
||||
#define __gid_t_defined
|
||||
typedef __gid_t gid_t;
|
||||
#endif // __gid_t_defined
|
||||
|
||||
#ifndef __ino_t_defined
|
||||
#define __ino_t_defined
|
||||
typedef __ino_t ino_t;
|
||||
#endif // __ino_t_defined
|
||||
|
||||
#ifndef __ino64_t_defined
|
||||
#define __ino64_t_defined
|
||||
typedef __ino64_t ino64_t;
|
||||
#endif // __ino64_t_defined
|
||||
|
||||
#ifndef __mode_t_defined
|
||||
#define __mode_t_defined
|
||||
typedef __mode_t mode_t;
|
||||
#endif // __mode_t_defined
|
||||
|
||||
#ifndef __nlink_t_defined
|
||||
#define __nlink_t_defined
|
||||
typedef __nlink_t nlink_t;
|
||||
#endif // __nlink_t_defined
|
||||
|
||||
#ifndef __off_t_defined
|
||||
#define __off_t_defined
|
||||
typedef __off_t off_t;
|
||||
#endif // __off_t_defined
|
||||
|
||||
#ifndef __off64_t_defined
|
||||
#define __off64_t_defined
|
||||
typedef __off64_t off64_t;
|
||||
#endif // __off64_t_defined
|
||||
|
||||
#ifndef __pid_t_defined
|
||||
#define __pid_t_defined
|
||||
typedef __pid_t pid_t;
|
||||
#endif // __pid_t_defined
|
||||
|
||||
#ifndef __fsid_t_defined
|
||||
#define __fsid_t_defined
|
||||
typedef __fsid_t fsid_t;
|
||||
#endif // __fsid_t_defined
|
||||
|
||||
#ifndef __time_t_defined
|
||||
#define __time_t_defined
|
||||
typedef __time_t time_t;
|
||||
#endif // __time_t_defined
|
||||
#endif // _LIBC_SYS__TYPES__INTS_H
|
||||
6
libs/libc/include/sys/_types/_va_list.h
Normal file
6
libs/libc/include/sys/_types/_va_list.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _LIBC_SYS__TYPES__VA_LIST_H
|
||||
#define _LIBC_SYS__TYPES__VA_LIST_H
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
#endif // _LIBC_SYS__TYPES__VA_LIST_H
|
||||
23
libs/libc/include/sys/cdefs.h
Normal file
23
libs/libc/include/sys/cdefs.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _LIBC_SYS_CDEFS_H
|
||||
#define _LIBC_SYS_CDEFS_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#define __BEGIN_DECLS extern "C" {
|
||||
#define __END_DECLS }
|
||||
#else
|
||||
#define __BEGIN_DECLS
|
||||
#define __END_DECLS
|
||||
#endif
|
||||
|
||||
/* Define __use_instead macro for some functions so the user can be warned
|
||||
about better/faster functions. */
|
||||
#ifndef __use_instead
|
||||
#ifdef __clang__
|
||||
#define __use_instead(F) __attribute__((diagnose_if(1, "use " F " instead", \
|
||||
"warning")))
|
||||
#elif defined(__GNUC__)
|
||||
#define __use_instead(F) __attribute__((warning("use " F " instead")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // _LIBC_SYS_CDEFS_H
|
||||
12
libs/libc/include/sys/environ.h
Normal file
12
libs/libc/include/sys/environ.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _LIBC_SYS_ENVIRON_H
|
||||
#define _LIBC_SYS_ENVIRON_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
extern char** environ;
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_ENVIRON_H
|
||||
16
libs/libc/include/sys/ioctl.h
Normal file
16
libs/libc/include/sys/ioctl.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _LIBC_SYS_IOCTL_H
|
||||
#define _LIBC_SYS_IOCTL_H
|
||||
|
||||
#include <bits/sys/ioctls.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int ioctl(int fd, uintptr_t cmd, uintptr_t arg);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_IOCTL_H
|
||||
16
libs/libc/include/sys/mman.h
Normal file
16
libs/libc/include/sys/mman.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _LIBC_SYS_MMAN_H
|
||||
#define _LIBC_SYS_MMAN_H
|
||||
|
||||
#include <bits/sys/mman.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
|
||||
int munmap(void* addr, size_t length);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_MMAN_H
|
||||
15
libs/libc/include/sys/ptrace.h
Normal file
15
libs/libc/include/sys/ptrace.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _LIBC_SYS_PTRACE_H
|
||||
#define _LIBC_SYS_PTRACE_H
|
||||
|
||||
#include <bits/sys/ptrace.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int ptrace(ptrace_request_t request, pid_t pid, void* addr, void* data);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_PTRACE_H
|
||||
16
libs/libc/include/sys/select.h
Normal file
16
libs/libc/include/sys/select.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _LIBC_SYS_SELECT_H
|
||||
#define _LIBC_SYS_SELECT_H
|
||||
|
||||
#include <bits/sys/select.h>
|
||||
#include <bits/time.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int select(int nfds, fd_set_t* readfds, fd_set_t* writefds, fd_set_t* exceptfds, timeval_t* timeout);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_SELECT_H
|
||||
17
libs/libc/include/sys/socket.h
Normal file
17
libs/libc/include/sys/socket.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _LIBC_SYS_SOCKET_H
|
||||
#define _LIBC_SYS_SOCKET_H
|
||||
|
||||
#include <bits/sys/socket.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int socket(int domain, int type, int protocol);
|
||||
int bind(int sockfd, const char* name, int len);
|
||||
int connect(int sockfd, const char* name, int len);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_SOCKET_H
|
||||
15
libs/libc/include/sys/stat.h
Normal file
15
libs/libc/include/sys/stat.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _LIBC_SYS_STAT_H
|
||||
#define _LIBC_SYS_STAT_H
|
||||
|
||||
#include <bits/sys/stat.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int mkdir(const char* path);
|
||||
int fstat(int nfds, stat_t* stat);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
14
libs/libc/include/sys/time.h
Normal file
14
libs/libc/include/sys/time.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _LIBC_SYS_TIME_H
|
||||
#define _LIBC_SYS_TIME_H
|
||||
|
||||
#include <bits/time.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int gettimeofday(timeval_t* tv, timezone_t* tz);
|
||||
int settimeofday(const timeval_t* tv, const timezone_t* tz);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
8
libs/libc/include/sys/types.h
Normal file
8
libs/libc/include/sys/types.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _LIBC_SYS_TYPES_H
|
||||
#define _LIBC_SYS_TYPES_H
|
||||
|
||||
#include <sys/_types/_devs.h>
|
||||
#include <sys/_types/_ints.h>
|
||||
#include <sys/_types/_va_list.h>
|
||||
|
||||
#endif /* _LIBC_SYS_TYPES_H */
|
||||
13
libs/libc/include/sys/utsname.h
Normal file
13
libs/libc/include/sys/utsname.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef _LIBC_SYS_UTSNAME_H
|
||||
#define _LIBC_SYS_UTSNAME_H
|
||||
|
||||
#include <bits/sys/utsname.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int uname(utsname_t* buf);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_UTSNAME_H
|
||||
17
libs/libc/include/sys/wait.h
Normal file
17
libs/libc/include/sys/wait.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _LIBC_SYS_WAIT_H
|
||||
#define _LIBC_SYS_WAIT_H
|
||||
|
||||
#include <bits/sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int wait(int pid);
|
||||
int waitpid(int pid, int* status, int options);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_WAIT_H
|
||||
94
libs/libc/include/sysdep.h
Normal file
94
libs/libc/include/sysdep.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef _LIBC_SYSDEP_H
|
||||
#define _LIBC_SYSDEP_H
|
||||
|
||||
#include <bits/syscalls.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
static inline intptr_t _syscall_impl(sysid_t sysid, intptr_t p1, intptr_t p2, intptr_t p3, intptr_t p4, intptr_t p5)
|
||||
{
|
||||
intptr_t ret;
|
||||
#ifdef __i386__
|
||||
asm volatile("push %%ebx;movl %2,%%ebx;int $0x80;pop %%ebx"
|
||||
: "=a"(ret)
|
||||
: "0"(sysid), "r"((intptr_t)(p1)), "c"((intptr_t)(p2)), "d"((intptr_t)(p3)), "S"((intptr_t)(p4)), "D"((intptr_t)(p5))
|
||||
: "memory");
|
||||
#elif __x86_64__
|
||||
asm volatile(
|
||||
"movq %1, %%rax;\
|
||||
movq %2, %%rdi;\
|
||||
movq %3, %%rsi;\
|
||||
movq %4, %%rdx;\
|
||||
movq %5, %%r10;\
|
||||
movq %6, %%r8;\
|
||||
int $0x80;\
|
||||
movq %%rax, %0;"
|
||||
: "=r"(ret)
|
||||
: "r"(sysid), "r"((intptr_t)(p1)), "r"((intptr_t)(p2)), "r"((intptr_t)(p3)), "r"((intptr_t)(p4)), "r"((intptr_t)(p5))
|
||||
: "memory", "rax", "rdi", "rsi", "rdx", "r10", "r8");
|
||||
#elif __arm__
|
||||
asm volatile(
|
||||
"mov r7, %1;\
|
||||
mov r0, %2;\
|
||||
mov r1, %3;\
|
||||
mov r2, %4;\
|
||||
mov r3, %5;\
|
||||
mov r4, %6;\
|
||||
swi 1;\
|
||||
mov %0, r0;"
|
||||
: "=r"(ret)
|
||||
: "r"(sysid), "r"((intptr_t)(p1)), "r"((intptr_t)(p2)), "r"((intptr_t)(p3)), "r"((intptr_t)(p4)), "r"((intptr_t)(p5))
|
||||
: "memory", "r0", "r1", "r2", "r3", "r4", "r7");
|
||||
#elif __aarch64__
|
||||
asm volatile(
|
||||
"mov x8, %x1;\
|
||||
mov x0, %x2;\
|
||||
mov x1, %x3;\
|
||||
mov x2, %x4;\
|
||||
mov x3, %x5;\
|
||||
mov x4, %x6;\
|
||||
svc 1;\
|
||||
mov %x0, x0;"
|
||||
: "=r"(ret)
|
||||
: "r"(sysid), "r"((intptr_t)(p1)), "r"((intptr_t)(p2)), "r"((intptr_t)(p3)), "r"((intptr_t)(p4)), "r"((intptr_t)(p5))
|
||||
: "memory", "x0", "x1", "x2", "x3", "x4", "x8");
|
||||
#elif defined(__riscv) && (__riscv_xlen == 64)
|
||||
// TODO: Check copatability with Linux.
|
||||
asm volatile(
|
||||
"mv a7, %1;\
|
||||
mv a0, %2;\
|
||||
mv a1, %3;\
|
||||
mv a2, %4;\
|
||||
mv a3, %5;\
|
||||
mv a4, %6;\
|
||||
ecall;\
|
||||
mv %0, a0;"
|
||||
: "=r"(ret)
|
||||
: "r"(sysid), "r"((intptr_t)(p1)), "r"((intptr_t)(p2)), "r"((intptr_t)(p3)), "r"((intptr_t)(p4)), "r"((intptr_t)(p5))
|
||||
: "memory", "a0", "a1", "a2", "a3", "a4", "a7");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define DO_SYSCALL_0(type) _syscall_impl(type, 0, 0, 0, 0, 0)
|
||||
#define DO_SYSCALL_1(type, a) _syscall_impl(type, (intptr_t)a, 0, 0, 0, 0)
|
||||
#define DO_SYSCALL_2(type, a, b) _syscall_impl(type, (intptr_t)a, (intptr_t)b, 0, 0, 0)
|
||||
#define DO_SYSCALL_3(type, a, b, c) _syscall_impl(type, (intptr_t)a, (intptr_t)b, (intptr_t)c, 0, 0)
|
||||
#define DO_SYSCALL_4(type, a, b, c, d) _syscall_impl(type, (intptr_t)a, (intptr_t)b, (intptr_t)c, (intptr_t)d, 0)
|
||||
#define DO_SYSCALL_5(type, a, b, c, d, e) _syscall_impl(type, (intptr_t)a, (intptr_t)b, (intptr_t)c, (intptr_t)d, (intptr_t)e);
|
||||
#define RETURN_WITH_ERRNO(res, on_suc, on_fail) \
|
||||
do { \
|
||||
if ((intptr_t)res < 0) { \
|
||||
set_errno(res); \
|
||||
return (on_fail); \
|
||||
} \
|
||||
set_errno(0); \
|
||||
return on_suc; \
|
||||
} while (0);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYSDEP_H
|
||||
75
libs/libc/include/termios.h
Normal file
75
libs/libc/include/termios.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef _LIBC_TERMIOS_H
|
||||
#define _LIBC_TERMIOS_H
|
||||
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
#define NCCS 32
|
||||
struct termios {
|
||||
tcflag_t c_iflag; /* input mode flags */
|
||||
tcflag_t c_oflag; /* output mode flags */
|
||||
tcflag_t c_cflag; /* control mode flags */
|
||||
tcflag_t c_lflag; /* local mode flags */
|
||||
cc_t c_cc[NCCS]; /* control characters */
|
||||
};
|
||||
typedef struct termios termios_t;
|
||||
|
||||
/* c_cc characters */
|
||||
#define VINTR 0
|
||||
#define VQUIT 1
|
||||
#define VERASE 2
|
||||
#define VKILL 3
|
||||
#define VEOF 4
|
||||
#define VTIME 5
|
||||
#define VMIN 6
|
||||
#define VSWTC 7
|
||||
#define VSTART 8
|
||||
#define VSTOP 9
|
||||
#define VSUSP 10
|
||||
#define VEOL 11
|
||||
#define VREPRINT 12
|
||||
#define VDISCARD 13
|
||||
#define VWERASE 14
|
||||
#define VLNEXT 15
|
||||
#define VEOL2 16
|
||||
|
||||
/* c_lflag bits */
|
||||
#define ISIG 0000001
|
||||
#define ICANON 0000002
|
||||
#define ECHO 0000010
|
||||
#define ECHOE 0000020
|
||||
#define ECHOK 0000040
|
||||
#define ECHONL 0000100
|
||||
#define NOFLSH 0000200
|
||||
#define TOSTOP 0000400
|
||||
#define IEXTEN 0100000
|
||||
|
||||
/* tcflow() and TCXONC use these */
|
||||
#define TCOOFF 0
|
||||
#define TCOON 1
|
||||
#define TCIOFF 2
|
||||
#define TCION 3
|
||||
|
||||
/* tcflush() and TCFLSH use these */
|
||||
#define TCIFLUSH 0
|
||||
#define TCOFLUSH 1
|
||||
#define TCIOFLUSH 2
|
||||
|
||||
/* tcsetattr uses these */
|
||||
#define TCSANOW 0
|
||||
#define TCSADRAIN 1
|
||||
#define TCSAFLUSH 2
|
||||
|
||||
int tcgetattr(int fd, termios_t* termios_p);
|
||||
int tcsetattr(int fd, int optional_actions, const termios_t* termios_p);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _LIBC_TERMIOS_H */
|
||||
36
libs/libc/include/time.h
Normal file
36
libs/libc/include/time.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _LIBC_TIME_H
|
||||
#define _LIBC_TIME_H
|
||||
|
||||
#include <bits/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
time_t time(time_t* timep);
|
||||
char* asctime(const tm_t* tm);
|
||||
char* asctime_r(const tm_t* tm, char* buf);
|
||||
|
||||
char* ctime(const time_t* timep);
|
||||
char* ctime_r(const time_t* timep, char* buf);
|
||||
tm_t* gmtime(const time_t* timep);
|
||||
tm_t* gmtime_r(const time_t* timep, tm_t* result);
|
||||
|
||||
tm_t* localtime(const time_t* timep);
|
||||
tm_t* localtime_r(const time_t* timep, tm_t* result);
|
||||
|
||||
size_t strftime(char* s, size_t max, const char* format, const tm_t* tm);
|
||||
|
||||
time_t mktime(tm_t* tm);
|
||||
|
||||
int clock_getres(clockid_t clk_id, timespec_t* res);
|
||||
int clock_gettime(clockid_t clk_id, timespec_t* tp);
|
||||
int clock_settime(clockid_t clk_id, const timespec_t* tp);
|
||||
|
||||
int nanosleep(const timespec_t* req, timespec_t* rem);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_TIME_H
|
||||
58
libs/libc/include/unistd.h
Normal file
58
libs/libc/include/unistd.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef _LIBC_UNISTD_H
|
||||
#define _LIBC_UNISTD_H
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define STDIN_FILENO 0 // Standard input file descriptor
|
||||
#define STDOUT_FILENO 1 // Standard output file descriptor
|
||||
#define STDERR_FILENO 2 // Standard error file descriptor
|
||||
|
||||
/* tasking */
|
||||
int fork();
|
||||
int execve(const char* path, char* const argv[], char* const envp[]);
|
||||
int execvpe(const char* path, char* const argv[], char* const envp[]);
|
||||
int execvp(const char* path, char* const argv[]);
|
||||
int execlp(const char* path, const char* arg0, ...);
|
||||
pid_t getpid();
|
||||
int setpgid(pid_t cmd, pid_t arg);
|
||||
pid_t getpgid(pid_t arg);
|
||||
uint32_t sleep(uint32_t seconds);
|
||||
uint32_t usleep(uint32_t usec);
|
||||
|
||||
/* fs */
|
||||
int close(int fd);
|
||||
ssize_t read(int fd, char* buf, size_t count);
|
||||
ssize_t write(int fd, const void* buf, size_t count);
|
||||
int dup(int oldfd);
|
||||
int dup2(int oldfd, int newfd);
|
||||
int rmdir(const char* path);
|
||||
int chdir(const char* path);
|
||||
char* getcwd(char* buf, size_t size);
|
||||
int unlink(const char* path);
|
||||
off_t lseek(int fd, off_t off, int whence);
|
||||
|
||||
/* identity */
|
||||
uid_t getuid();
|
||||
int setuid(uid_t uid);
|
||||
int setgid(gid_t gid);
|
||||
int setreuid(uid_t ruid, uid_t euid);
|
||||
int setregid(gid_t rgid, gid_t egid);
|
||||
char* getlogin();
|
||||
|
||||
/* sched */
|
||||
int nice(int inc);
|
||||
|
||||
/* conf */
|
||||
#define _CS_GNU_LIBC_VERSION 1
|
||||
#define _CS_GNU_LIBPTHREAD_VERSION 2
|
||||
#define _CS_PATH 3
|
||||
size_t confstr(int name, char* buf, size_t len);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_UNISTD_H
|
||||
18
libs/libc/include/x/shared_buffer.h
Normal file
18
libs/libc/include/x/shared_buffer.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _LIBC_SYS_SHARED_BUFFER_H
|
||||
#define _LIBC_SYS_SHARED_BUFFER_H
|
||||
|
||||
#include <bits/sys/select.h>
|
||||
#include <bits/time.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int shared_buffer_create(uint8_t** buffer, size_t size);
|
||||
int shared_buffer_get(int id, uint8_t** buffer);
|
||||
int shared_buffer_free(int id);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_SYS_SHARED_BUFFER_H
|
||||
12
libs/libc/init/_init.c
Normal file
12
libs/libc/init/_init.c
Normal file
@@ -0,0 +1,12 @@
|
||||
extern void _libc_init(int argc, char* argv[], char* envp[]);
|
||||
extern void _libc_deinit();
|
||||
|
||||
void _init(int argc, char* argv[], char* envp[])
|
||||
{
|
||||
_libc_init(argc, argv, envp);
|
||||
}
|
||||
|
||||
void _deinit()
|
||||
{
|
||||
_libc_deinit();
|
||||
}
|
||||
26
libs/libc/init/_lib.c
Normal file
26
libs/libc/init/_lib.c
Normal file
@@ -0,0 +1,26 @@
|
||||
int errno;
|
||||
char** environ;
|
||||
int __environ_malloced = 0;
|
||||
|
||||
extern int _stdio_init();
|
||||
extern int _stdio_deinit();
|
||||
extern int _malloc_init();
|
||||
|
||||
void _libc_init(int argc, char* argv[], char* envp[])
|
||||
{
|
||||
environ = envp;
|
||||
_malloc_init();
|
||||
_stdio_init();
|
||||
extern void (*__init_array_start[])(int, char**, char**) __attribute__((visibility("hidden")));
|
||||
extern void (*__init_array_end[])(int, char**, char**) __attribute__((visibility("hidden")));
|
||||
|
||||
const unsigned int size = __init_array_end - __init_array_start;
|
||||
for (unsigned int i = 0; i < size; i++) {
|
||||
(*__init_array_start[i])(argc, argv, envp);
|
||||
}
|
||||
}
|
||||
|
||||
void _libc_deinit()
|
||||
{
|
||||
_stdio_deinit();
|
||||
}
|
||||
172
libs/libc/malloc/malloc.c
Normal file
172
libs/libc/malloc/malloc.c
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "malloc.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define ALIGNMENT (4)
|
||||
#define DEVIDE_SPACE_BOUNDARY (32)
|
||||
|
||||
static malloc_header_t* memory[MALLOC_MAX_ALLOCATED_BLOCKS];
|
||||
static size_t allocated_blocks = 0;
|
||||
|
||||
static int _alloc_new_block(size_t sz);
|
||||
|
||||
static int _alloc_new_block(size_t sz)
|
||||
{
|
||||
// TODO: This should be expendable.
|
||||
assert(allocated_blocks < MALLOC_MAX_ALLOCATED_BLOCKS);
|
||||
|
||||
sz += sizeof(malloc_header_t);
|
||||
|
||||
// This reduces system calls for the small memory allocations.
|
||||
size_t allocated_sz = sz > MALLOC_DEFAULT_BLOCK_SIZE ? sz : MALLOC_DEFAULT_BLOCK_SIZE;
|
||||
|
||||
intptr_t ret = (intptr_t)mmap(NULL, allocated_sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
memory[allocated_blocks] = (void*)ret;
|
||||
memory[allocated_blocks]->flags = 0;
|
||||
memory[allocated_blocks]->next = 0;
|
||||
memory[allocated_blocks]->prev = 0;
|
||||
memory[allocated_blocks]->size = allocated_sz - sizeof(malloc_header_t);
|
||||
|
||||
allocated_blocks++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char _malloc_need_to_divide_space(malloc_header_t* space, size_t alloc_size)
|
||||
{
|
||||
return alloc_size + DEVIDE_SPACE_BOUNDARY <= space->size;
|
||||
}
|
||||
|
||||
static inline char _malloc_can_fit_allocation(malloc_header_t* space, size_t alloc_size)
|
||||
{
|
||||
uint32_t add[] = { 0, sizeof(malloc_header_t) };
|
||||
return space->size >= (alloc_size + add[_malloc_need_to_divide_space(space, alloc_size)]);
|
||||
}
|
||||
|
||||
void* malloc(size_t sz)
|
||||
{
|
||||
if (!sz) {
|
||||
return NULL;
|
||||
}
|
||||
sz += (ALIGNMENT - 1);
|
||||
sz &= ~(uint32_t)(ALIGNMENT - 1);
|
||||
|
||||
void* res = slab_alloc(sz);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// Iterating over allocated by mmap blocks to find a first fit memory chunk.
|
||||
malloc_header_t* first_fit = NULL;
|
||||
for (size_t i = 0; i < allocated_blocks; i++) {
|
||||
malloc_header_t* cur_block = memory[i];
|
||||
while (cur_block->next && !(block_is_free(cur_block) && _malloc_can_fit_allocation(cur_block, sz))) {
|
||||
cur_block = cur_block->next;
|
||||
}
|
||||
if (block_is_free(cur_block) && _malloc_can_fit_allocation(cur_block, sz)) {
|
||||
first_fit = cur_block;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!first_fit) {
|
||||
int err = _alloc_new_block(sz);
|
||||
if (err) {
|
||||
return NULL;
|
||||
}
|
||||
first_fit = memory[allocated_blocks - 1];
|
||||
}
|
||||
|
||||
malloc_header_t* copy_next = first_fit->next;
|
||||
size_t copy_size = first_fit->size;
|
||||
|
||||
first_fit->flags |= FLAG_ALLOCATED;
|
||||
if (_malloc_need_to_divide_space(first_fit, sz)) {
|
||||
first_fit->size = sz;
|
||||
first_fit->next = (malloc_header_t*)((uintptr_t)first_fit + sz + sizeof(malloc_header_t));
|
||||
|
||||
// Adjust the firstfit chunk.
|
||||
first_fit->next->flags = 0;
|
||||
first_fit->next->size = copy_size - sz - sizeof(malloc_header_t);
|
||||
first_fit->next->next = copy_next;
|
||||
first_fit->next->prev = first_fit;
|
||||
|
||||
if (first_fit->next->next) {
|
||||
first_fit->next->next->prev = first_fit->next;
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)&((malloc_header_t*)first_fit)[1];
|
||||
}
|
||||
|
||||
void free(void* mem)
|
||||
{
|
||||
if (!mem) {
|
||||
return;
|
||||
}
|
||||
|
||||
malloc_header_t* mem_header = &((malloc_header_t*)mem)[-1];
|
||||
|
||||
if (block_is_slab(mem_header)) {
|
||||
return slab_free(mem_header);
|
||||
}
|
||||
|
||||
block_rem_flags(mem_header, FLAG_ALLOCATED);
|
||||
while (mem_header->prev && block_is_free(mem_header->prev)) {
|
||||
mem_header = mem_header->prev;
|
||||
}
|
||||
|
||||
// Trying to glue the freed chunk with its neighbours.
|
||||
while (mem_header->next && block_is_free(mem_header->next)) {
|
||||
mem_header->size += mem_header->next->size + sizeof(malloc_header_t);
|
||||
|
||||
if (mem_header->next->next) {
|
||||
mem_header->next->next->prev = mem_header;
|
||||
}
|
||||
mem_header->next = mem_header->next->next;
|
||||
}
|
||||
}
|
||||
|
||||
void* calloc(size_t num, size_t size)
|
||||
{
|
||||
void* mem = malloc(num * size);
|
||||
if (!mem) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(mem, 0, num * size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void* realloc(void* ptr, size_t new_size)
|
||||
{
|
||||
if (!ptr) {
|
||||
return malloc(new_size);
|
||||
}
|
||||
|
||||
size_t old_size = ((malloc_header_t*)ptr)[-1].size;
|
||||
if (old_size == new_size) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t* new_area = malloc(new_size);
|
||||
if (!new_area) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(new_area, ptr, new_size < old_size ? new_size : old_size);
|
||||
free(ptr);
|
||||
|
||||
return new_area;
|
||||
}
|
||||
|
||||
void _malloc_init()
|
||||
{
|
||||
_slab_init();
|
||||
}
|
||||
68
libs/libc/malloc/malloc.h
Normal file
68
libs/libc/malloc/malloc.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef _LIBC_MALLOC_MALLOC_H
|
||||
#define _LIBC_MALLOC_MALLOC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define MALLOC_DEFAULT_BLOCK_SIZE 4096
|
||||
#define MALLOC_MAX_ALLOCATED_BLOCKS 256
|
||||
|
||||
#define FLAG_ALLOCATED (0x1)
|
||||
#define FLAG_SLAB (0x2)
|
||||
struct __malloc_header {
|
||||
size_t size;
|
||||
uint32_t flags;
|
||||
struct __malloc_header* next;
|
||||
struct __malloc_header* prev;
|
||||
};
|
||||
typedef struct __malloc_header malloc_header_t;
|
||||
|
||||
static inline bool block_has_flags(malloc_header_t* block, uint32_t flags)
|
||||
{
|
||||
return ((block->flags & flags) == flags);
|
||||
}
|
||||
|
||||
static inline void block_set_flags(malloc_header_t* block, uint32_t flags)
|
||||
{
|
||||
block->flags |= flags;
|
||||
}
|
||||
|
||||
static inline void block_rem_flags(malloc_header_t* block, uint32_t flags)
|
||||
{
|
||||
block->flags &= (~flags);
|
||||
}
|
||||
|
||||
static inline bool block_is_allocated(malloc_header_t* block)
|
||||
{
|
||||
return block_has_flags(block, FLAG_ALLOCATED);
|
||||
}
|
||||
|
||||
static inline bool block_is_free(malloc_header_t* block)
|
||||
{
|
||||
return !block_has_flags(block, FLAG_ALLOCATED);
|
||||
}
|
||||
|
||||
static inline bool block_is_slab(malloc_header_t* block)
|
||||
{
|
||||
return block_has_flags(block, FLAG_SLAB);
|
||||
}
|
||||
|
||||
void _malloc_init();
|
||||
void _slab_init();
|
||||
|
||||
void* malloc(size_t);
|
||||
void free(void*);
|
||||
void* calloc(size_t, size_t);
|
||||
void* realloc(void*, size_t);
|
||||
|
||||
void* slab_alloc(size_t);
|
||||
void slab_free(malloc_header_t* mem_header);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_MALLOC_MALLOC_H
|
||||
79
libs/libc/malloc/slab.c
Normal file
79
libs/libc/malloc/slab.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "malloc.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// Fast allocator for sizes 16, 32, 48, 64 bytes
|
||||
|
||||
malloc_header_t* free_blocks[5];
|
||||
|
||||
void prepare_free_blocks(size_t size)
|
||||
{
|
||||
int block_id = size >> 4;
|
||||
const size_t alloc_size = MALLOC_DEFAULT_BLOCK_SIZE;
|
||||
intptr_t ret = (intptr_t)mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
|
||||
if (ret < 0) {
|
||||
free_blocks[block_id] = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void* raw_area = (void*)ret;
|
||||
const size_t sizeof_block_with_header = size + sizeof(malloc_header_t);
|
||||
size_t passed = 0;
|
||||
|
||||
free_blocks[block_id] = (malloc_header_t*)raw_area;
|
||||
malloc_header_t* prev_header = NULL;
|
||||
|
||||
while (passed + sizeof_block_with_header <= alloc_size) {
|
||||
malloc_header_t* current = (malloc_header_t*)raw_area;
|
||||
|
||||
current->flags = FLAG_SLAB | FLAG_ALLOCATED;
|
||||
current->next = NULL;
|
||||
current->prev = prev_header;
|
||||
current->size = size;
|
||||
|
||||
prev_header = current;
|
||||
raw_area += sizeof_block_with_header;
|
||||
passed += sizeof_block_with_header;
|
||||
}
|
||||
|
||||
malloc_header_t* next_header = NULL;
|
||||
while (prev_header) {
|
||||
prev_header->next = next_header;
|
||||
prev_header = prev_header->prev;
|
||||
}
|
||||
}
|
||||
|
||||
void _slab_init()
|
||||
{
|
||||
prepare_free_blocks(16);
|
||||
prepare_free_blocks(32);
|
||||
prepare_free_blocks(48);
|
||||
prepare_free_blocks(64);
|
||||
}
|
||||
|
||||
void* slab_alloc(size_t size)
|
||||
{
|
||||
if (size > 64) {
|
||||
return NULL;
|
||||
}
|
||||
int block_id = ((size + 15) >> 4);
|
||||
malloc_header_t* zone = free_blocks[block_id];
|
||||
if (!zone) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free_blocks[block_id] = zone->next;
|
||||
return (void*)&((malloc_header_t*)zone)[1];
|
||||
}
|
||||
|
||||
void slab_free(malloc_header_t* mem_header)
|
||||
{
|
||||
malloc_header_t* next = free_blocks[((mem_header->size) >> 4)];
|
||||
free_blocks[((mem_header->size) >> 4)] = mem_header;
|
||||
mem_header->next = next;
|
||||
mem_header->prev = NULL;
|
||||
if (next) {
|
||||
next->prev = mem_header;
|
||||
}
|
||||
}
|
||||
119
libs/libc/posix/fs.c
Normal file
119
libs/libc/posix/fs.c
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sysdep.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int open(const char* pathname, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if ((flags & O_CREAT) != 0) {
|
||||
va_list va;
|
||||
va_start(va, flags);
|
||||
mode = (mode_t)va_arg(va, unsigned);
|
||||
va_end(va);
|
||||
}
|
||||
int res = DO_SYSCALL_3(SYS_OPEN, pathname, flags, mode);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
int creat(const char* path, mode_t mode)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_CREAT, path, mode);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_CLOSE, fd);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
ssize_t read(int fd, char* buf, size_t count)
|
||||
{
|
||||
return (ssize_t)DO_SYSCALL_3(SYS_READ, fd, buf, count);
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void* buf, size_t count)
|
||||
{
|
||||
return (ssize_t)DO_SYSCALL_3(SYS_WRITE, fd, buf, count);
|
||||
}
|
||||
|
||||
int dup(int oldfd)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_DUP, oldfd);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
int dup2(int oldfd, int newfd)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_DUP2, oldfd, newfd);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
off_t lseek(int fd, off_t off, int whence)
|
||||
{
|
||||
return (off_t)DO_SYSCALL_3(SYS_LSEEK, fd, off, whence);
|
||||
}
|
||||
|
||||
int mkdir(const char* path)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_MKDIR, path);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
int rmdir(const char* path)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_RMDIR, path);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
int chdir(const char* path)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_CHDIR, path);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
char* getcwd(char* buf, size_t size)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_GETCWD, buf, size);
|
||||
RETURN_WITH_ERRNO(res, buf, NULL);
|
||||
}
|
||||
|
||||
int unlink(const char* path)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_UNLINK, path);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
int fstat(int nfds, stat_t* stat)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_FSTAT, nfds, stat);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
int select(int nfds, fd_set_t* readfds, fd_set_t* writefds, fd_set_t* exceptfds, timeval_t* timeout)
|
||||
{
|
||||
int res = DO_SYSCALL_5(SYS_SELECT, nfds, readfds, writefds, exceptfds, timeout);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
mmap_params_t mmap_params = { 0 };
|
||||
mmap_params.addr = addr;
|
||||
mmap_params.size = length;
|
||||
mmap_params.prot = prot;
|
||||
mmap_params.flags = flags;
|
||||
mmap_params.fd = fd;
|
||||
mmap_params.offset = offset;
|
||||
return (void*)DO_SYSCALL_1(SYS_MMAP, &mmap_params);
|
||||
}
|
||||
|
||||
int munmap(void* addr, size_t length)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_MUNMAP, addr, length);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
44
libs/libc/posix/identity.c
Normal file
44
libs/libc/posix/identity.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <assert.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <sysdep.h>
|
||||
#include <unistd.h>
|
||||
|
||||
uid_t getuid()
|
||||
{
|
||||
return (uid_t)DO_SYSCALL_0(SYS_GETUID);
|
||||
}
|
||||
|
||||
uid_t geteuid()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setuid(uid_t uid)
|
||||
{
|
||||
return DO_SYSCALL_1(SYS_SETUID, uid);
|
||||
}
|
||||
|
||||
int setgid(gid_t gid)
|
||||
{
|
||||
return DO_SYSCALL_1(SYS_SETGID, gid);
|
||||
}
|
||||
|
||||
int setreuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
return DO_SYSCALL_2(SYS_SETREUID, ruid, euid);
|
||||
}
|
||||
|
||||
int setregid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
return DO_SYSCALL_2(SYS_SETREGID, rgid, egid);
|
||||
}
|
||||
|
||||
static char loginbuf[128];
|
||||
char* getlogin()
|
||||
{
|
||||
passwd_t* passwd = getpwuid(getuid());
|
||||
strncpy(loginbuf, passwd->pw_name, 128);
|
||||
endpwent();
|
||||
return loginbuf;
|
||||
}
|
||||
14
libs/libc/posix/sched.c
Normal file
14
libs/libc/posix/sched.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <sched.h>
|
||||
#include <sysdep.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void sched_yield()
|
||||
{
|
||||
DO_SYSCALL_0(SYS_SCHED_YIELD);
|
||||
}
|
||||
|
||||
int nice(int inc)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_NICE, inc);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
26
libs/libc/posix/signal.c
Normal file
26
libs/libc/posix/signal.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <signal.h>
|
||||
#include <sysdep.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int sigaction(int signo, sighandler_t callback)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_SIGACTION, signo, callback);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
sighandler_t signal(int signo, sighandler_t callback)
|
||||
{
|
||||
sigaction(signo, callback);
|
||||
return SIG_DFL;
|
||||
}
|
||||
|
||||
int raise(int signo)
|
||||
{
|
||||
return kill(getpid(), signo);
|
||||
}
|
||||
|
||||
int kill(pid_t pid, int signo)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_KILL, pid, signo);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
34
libs/libc/posix/system.c
Normal file
34
libs/libc/posix/system.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sysdep.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int uname(utsname_t* buf)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_UNAME, buf);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
#define PATH_CONSTANT "/bin:/usr/bin"
|
||||
#define PATH_CONSTANT_LEN sizeof(PATH_CONSTANT)
|
||||
size_t confstr(int name, char* buf, size_t len)
|
||||
{
|
||||
switch (name) {
|
||||
case _CS_PATH:
|
||||
if (!buf || !len) {
|
||||
return PATH_CONSTANT_LEN;
|
||||
} else {
|
||||
// Return path only if enough space.
|
||||
if (len < PATH_CONSTANT_LEN) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf, PATH_CONSTANT, PATH_CONSTANT_LEN);
|
||||
return PATH_CONSTANT_LEN;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
133
libs/libc/posix/tasking.c
Normal file
133
libs/libc/posix/tasking.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysdep.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int fork()
|
||||
{
|
||||
int res = DO_SYSCALL_0(SYS_FORK);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
int execve(const char* path, char* const argv[], char* const envp[])
|
||||
{
|
||||
int res = DO_SYSCALL_3(SYS_EXECVE, path, argv, envp);
|
||||
RETURN_WITH_ERRNO(res, -1, -1);
|
||||
}
|
||||
|
||||
int execvpe(const char* path, char* const argv[], char* const envp[])
|
||||
{
|
||||
if (strchr(path, '/')) {
|
||||
return execve(path, argv, envp);
|
||||
}
|
||||
|
||||
char* full_path = malloc(256);
|
||||
size_t namelen = strlen(path);
|
||||
char* env_path = getenv("PATH");
|
||||
if (!env_path) {
|
||||
// Get it from confstr
|
||||
env_path = "/bin:/usr/bin";
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
int cnt = 0;
|
||||
for (int i = 0; env_path[i]; i += len) {
|
||||
len = 0;
|
||||
while (env_path[i + len] && env_path[i + len] != ':') {
|
||||
len++;
|
||||
}
|
||||
|
||||
memcpy(full_path, &env_path[i], len);
|
||||
full_path[len] = '/';
|
||||
memcpy(&full_path[len + 1], path, namelen + 1);
|
||||
|
||||
int err = execve(full_path, argv, envp);
|
||||
if (env_path[i + len] == ':') {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
free(full_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int execvp(const char* path, char* const argv[])
|
||||
{
|
||||
return execvpe(path, argv, environ);
|
||||
}
|
||||
|
||||
int execlp(const char* path, const char* arg0, ...)
|
||||
{
|
||||
const char* args[16];
|
||||
int nxt = 0;
|
||||
args[nxt++] = arg0;
|
||||
|
||||
va_list va;
|
||||
va_start(va, arg0);
|
||||
for (;;) {
|
||||
const char* arg = va_arg(va, const char*);
|
||||
if (!arg) {
|
||||
break;
|
||||
}
|
||||
args[nxt++] = arg;
|
||||
}
|
||||
va_end(va);
|
||||
args[nxt++] = NULL;
|
||||
return execvpe(path, (char* const*)args, environ);
|
||||
}
|
||||
|
||||
int wait(int pid)
|
||||
{
|
||||
int res = DO_SYSCALL_3(SYS_WAITPID, pid, NULL, 0);
|
||||
RETURN_WITH_ERRNO(res, pid, -1);
|
||||
}
|
||||
|
||||
int waitpid(int pid, int* status, int options)
|
||||
{
|
||||
int res = DO_SYSCALL_3(SYS_WAITPID, pid, status, options);
|
||||
RETURN_WITH_ERRNO(res, pid, -1);
|
||||
}
|
||||
|
||||
pid_t getpid()
|
||||
{
|
||||
int res = DO_SYSCALL_0(SYS_GETPID);
|
||||
RETURN_WITH_ERRNO(res, (pid_t)res, -1);
|
||||
}
|
||||
|
||||
int setpgid(pid_t pid, pid_t pgid)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_SETPGID, pid, pgid);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
pid_t getpgid(pid_t pid)
|
||||
{
|
||||
int res = DO_SYSCALL_1(SYS_GETPGID, pid);
|
||||
RETURN_WITH_ERRNO(res, (pid_t)res, -1);
|
||||
}
|
||||
|
||||
uint32_t usleep(uint32_t usec)
|
||||
{
|
||||
timespec_t ts = { 0 };
|
||||
ts.tv_sec = usec / 1000000;
|
||||
ts.tv_nsec = (usec % 1000000) * 1000;
|
||||
int err = nanosleep(&ts, NULL);
|
||||
if (err) {
|
||||
return 0;
|
||||
}
|
||||
return usec;
|
||||
}
|
||||
|
||||
uint32_t sleep(uint32_t seconds)
|
||||
{
|
||||
timespec_t ts = { 0 };
|
||||
ts.tv_sec = seconds;
|
||||
int err = nanosleep(&ts, NULL);
|
||||
if (err) {
|
||||
return 0;
|
||||
}
|
||||
return seconds;
|
||||
}
|
||||
19
libs/libc/posix/time.c
Normal file
19
libs/libc/posix/time.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <sys/time.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
int nanosleep(const timespec_t* req, timespec_t* rem)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_NANOSLEEP, req, rem);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
int gettimeofday(timeval_t* tv, timezone_t* tz)
|
||||
{
|
||||
int res = DO_SYSCALL_2(SYS_GETTIMEOFDAY, tv, tz);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
int settimeofday(const timeval_t* tv, const timezone_t* tz)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
5
libs/libc/private/_init.c
Normal file
5
libs/libc/private/_init.c
Normal file
@@ -0,0 +1,5 @@
|
||||
int errno;
|
||||
|
||||
void _init()
|
||||
{
|
||||
}
|
||||
15
libs/libc/pthread/pthread.c
Normal file
15
libs/libc/pthread/pthread.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
int pthread_create(void* func)
|
||||
{
|
||||
intptr_t start = (intptr_t)mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_STACK | MAP_PRIVATE, 0, 0);
|
||||
thread_create_params_t params;
|
||||
params.stack_start = start;
|
||||
params.stack_size = 4096;
|
||||
params.entry_point = (intptr_t)func;
|
||||
int res = DO_SYSCALL_1(SYS_PTHREAD_CREATE, ¶ms);
|
||||
RETURN_WITH_ERRNO(res, 0, res);
|
||||
}
|
||||
8
libs/libc/ptrace/ptrace.c
Normal file
8
libs/libc/ptrace/ptrace.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <sys/ptrace.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
int ptrace(ptrace_request_t request, pid_t pid, void* addr, void* data)
|
||||
{
|
||||
int res = DO_SYSCALL_4(SYS_PTRACE, request, pid, addr, data);
|
||||
RETURN_WITH_ERRNO(res, 0, res);
|
||||
}
|
||||
118
libs/libc/pwd/pwd.c
Normal file
118
libs/libc/pwd/pwd.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <assert.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static FILE* pwdfile = NULL;
|
||||
static char tmp_buf[512];
|
||||
|
||||
// Passwd struct contains pointers to data which is
|
||||
// stored in passwd_buf
|
||||
static char passwd_buf[512];
|
||||
static passwd_t passwd_entry;
|
||||
|
||||
static passwd_t* parse_passwd_entry(char* res)
|
||||
{
|
||||
int len = strlen(res);
|
||||
int nxt_part = 0;
|
||||
char* parts[8];
|
||||
|
||||
memcpy(passwd_buf, res, len);
|
||||
|
||||
parts[nxt_part++] = &passwd_buf[0];
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (passwd_buf[i] == ':') {
|
||||
parts[nxt_part++] = &passwd_buf[i + 1];
|
||||
passwd_buf[i] = '\0';
|
||||
if (nxt_part > 7) {
|
||||
// More than 7 block.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
passwd_buf[len] = '\0';
|
||||
|
||||
if (nxt_part != 7) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
sscanf(parts[2], "%u", &uid);
|
||||
sscanf(parts[3], "%u", &gid);
|
||||
|
||||
passwd_entry.pw_name = parts[0];
|
||||
passwd_entry.pw_passwd = parts[1];
|
||||
passwd_entry.pw_uid = uid;
|
||||
passwd_entry.pw_gid = gid;
|
||||
passwd_entry.pw_gecos = parts[4];
|
||||
passwd_entry.pw_dir = parts[5];
|
||||
passwd_entry.pw_shell = parts[6];
|
||||
|
||||
return &passwd_entry;
|
||||
}
|
||||
|
||||
void setpwent()
|
||||
{
|
||||
pwdfile = fopen("/etc/passwd", "r");
|
||||
if (pwdfile == NULL) {
|
||||
// Raise an error
|
||||
}
|
||||
}
|
||||
|
||||
void endpwent()
|
||||
{
|
||||
if (pwdfile) {
|
||||
fclose(pwdfile);
|
||||
pwdfile = NULL;
|
||||
}
|
||||
memset(&passwd_entry, 0, sizeof(passwd_entry));
|
||||
}
|
||||
|
||||
passwd_t* getpwent()
|
||||
{
|
||||
if (!pwdfile) {
|
||||
setpwent();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (feof(pwdfile)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* res = fgets(passwd_buf, 512, pwdfile);
|
||||
if (!res || !res[0]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (parse_passwd_entry(res)) {
|
||||
return &passwd_entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
passwd_t* getpwuid(uid_t uid)
|
||||
{
|
||||
passwd_t* passwd;
|
||||
setpwent();
|
||||
while ((passwd = getpwent())) {
|
||||
if (passwd->pw_uid == uid) {
|
||||
return passwd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
passwd_t* getpwnam(const char* name)
|
||||
{
|
||||
passwd_t* passwd;
|
||||
setpwent();
|
||||
while ((passwd = getpwent())) {
|
||||
if (!strcmp(passwd->pw_name, name)) {
|
||||
return passwd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
116
libs/libc/pwd/shadow.c
Normal file
116
libs/libc/pwd/shadow.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <assert.h>
|
||||
#include <shadow.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static FILE* spwdfile = NULL;
|
||||
static char tmp_buf[512];
|
||||
|
||||
// spwd struct contains pointers to data which is
|
||||
// stored in spwd_buf
|
||||
static char spwd_buf[512];
|
||||
static spwd_t spwd_entry;
|
||||
|
||||
static inline int spwd_part_to_int(char* part)
|
||||
{
|
||||
int res = 0;
|
||||
sscanf(part, "%d", &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline uint32_t spwd_part_to_uint(char* part)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
sscanf(part, "%u", &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static spwd_t* parse_spwd_entry(char* res)
|
||||
{
|
||||
int len = strlen(res);
|
||||
int nxt_part = 0;
|
||||
char* parts[10];
|
||||
|
||||
memcpy(spwd_buf, res, len);
|
||||
|
||||
parts[nxt_part++] = &spwd_buf[0];
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (spwd_buf[i] == ':') {
|
||||
parts[nxt_part++] = &spwd_buf[i + 1];
|
||||
spwd_buf[i] = '\0';
|
||||
if (nxt_part > 9) {
|
||||
// More than 9 block.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
spwd_buf[len] = '\0';
|
||||
|
||||
if (nxt_part != 9) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spwd_entry.sp_namp = parts[0];
|
||||
spwd_entry.sp_pwdp = parts[1];
|
||||
spwd_entry.sp_lstchg = spwd_part_to_int(parts[2]);
|
||||
spwd_entry.sp_min = spwd_part_to_int(parts[3]);
|
||||
spwd_entry.sp_max = spwd_part_to_int(parts[4]);
|
||||
spwd_entry.sp_warn = spwd_part_to_int(parts[5]);
|
||||
spwd_entry.sp_inact = spwd_part_to_int(parts[6]);
|
||||
spwd_entry.sp_expire = spwd_part_to_int(parts[7]);
|
||||
spwd_entry.sp_flag = spwd_part_to_uint(parts[8]);
|
||||
return &spwd_entry;
|
||||
}
|
||||
|
||||
void setspent()
|
||||
{
|
||||
spwdfile = fopen("/etc/shadow", "r");
|
||||
if (spwdfile == NULL) {
|
||||
// Raise an error
|
||||
}
|
||||
}
|
||||
|
||||
void endspent()
|
||||
{
|
||||
if (spwdfile) {
|
||||
fclose(spwdfile);
|
||||
spwdfile = NULL;
|
||||
}
|
||||
memset(&spwd_entry, 0, sizeof(spwd_entry));
|
||||
}
|
||||
|
||||
spwd_t* getspent()
|
||||
{
|
||||
if (!spwdfile) {
|
||||
setspent();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (feof(spwdfile)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* res = fgets(spwd_buf, 512, spwdfile);
|
||||
if (!res || !res[0]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (parse_spwd_entry(res)) {
|
||||
return &spwd_entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spwd_t* getspnam(const char* name)
|
||||
{
|
||||
spwd_t* spwd;
|
||||
setspent();
|
||||
while ((spwd = getspent())) {
|
||||
if (!strcmp(spwd->sp_namp, name)) {
|
||||
return spwd;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
25
libs/libc/setjmp/arm32/setjmp.S
Normal file
25
libs/libc/setjmp/arm32/setjmp.S
Normal file
@@ -0,0 +1,25 @@
|
||||
.global setjmp
|
||||
setjmp:
|
||||
stm r0!, {r4-r12,lr}
|
||||
mov r1, sp
|
||||
ldm r0!, {r1}
|
||||
#ifdef __ARM_NEON__
|
||||
vstm r0!, {d8-d15}
|
||||
#endif // __ARM_NEON__
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
.global longjmp
|
||||
longjmp:
|
||||
ldm r0!, {r4-r12,lr}
|
||||
ldm r0!, {r1}
|
||||
mov sp, r1
|
||||
#ifdef __ARM_NEON__
|
||||
vldm r0!, {d8-d15}
|
||||
#endif // __ARM_NEON__
|
||||
mov r0, r1
|
||||
cmp r0, #0
|
||||
bne 1f
|
||||
mov r0, #1
|
||||
1:
|
||||
bx lr
|
||||
39
libs/libc/setjmp/arm64/setjmp.S
Normal file
39
libs/libc/setjmp/arm64/setjmp.S
Normal file
@@ -0,0 +1,39 @@
|
||||
.global setjmp
|
||||
setjmp:
|
||||
stp x19, x20, [x0,#0x0]
|
||||
stp x21, x22, [x0,#0x10]
|
||||
stp x23, x24, [x0,#0x20]
|
||||
stp x25, x26, [x0,#0x30]
|
||||
stp x27, x28, [x0,#0x40]
|
||||
stp x29, x4, [x0,#0x50]
|
||||
mov x2, lr
|
||||
mov x3, sp
|
||||
stp x2, x3, [x0,#0x60]
|
||||
stp d8, d9, [x0,#0x70]
|
||||
stp d10, d11, [x0,#0x80]
|
||||
stp d12, d13, [x0,#0x90]
|
||||
stp d14, d15, [x0,#0xa0]
|
||||
mov x0, #0
|
||||
ret
|
||||
|
||||
.global longjmp
|
||||
longjmp:
|
||||
ldp x19, x20, [x0,#0x0]
|
||||
ldp x21, x22, [x0,#0x10]
|
||||
ldp x23, x24, [x0,#0x20]
|
||||
ldp x25, x26, [x0,#0x30]
|
||||
ldp x27, x28, [x0,#0x40]
|
||||
ldp x29, x4, [x0,#0x50]
|
||||
ldp x2, x3, [x0,#0x60]
|
||||
ldp d8, d9, [x0,#0x70]
|
||||
ldp d10, d11, [x0,#0x80]
|
||||
ldp d12, d13, [x0,#0x90]
|
||||
ldp d14, d15, [x0,#0xa0]
|
||||
mov lr, x2
|
||||
mov sp, x3
|
||||
mov x0, x1
|
||||
cmp x0, #0
|
||||
bne 1f
|
||||
mov x0, #1
|
||||
1:
|
||||
ret
|
||||
55
libs/libc/setjmp/riscv64/setjmp.S
Normal file
55
libs/libc/setjmp/riscv64/setjmp.S
Normal file
@@ -0,0 +1,55 @@
|
||||
.global setjmp
|
||||
setjmp:
|
||||
sd s0, 0(a0)
|
||||
sd s1, 8(a0)
|
||||
sd s2, 16(a0)
|
||||
sd s3, 24(a0)
|
||||
sd s4, 32(a0)
|
||||
sd s5, 40(a0)
|
||||
sd s6, 48(a0)
|
||||
sd s7, 56(a0)
|
||||
sd s8, 64(a0)
|
||||
sd s9, 72(a0)
|
||||
sd s10, 80(a0)
|
||||
sd s11, 88(a0)
|
||||
sd ra, 96(a0)
|
||||
sd sp, 104(a0)
|
||||
|
||||
mv a0, zero
|
||||
ret
|
||||
// stp x19, x20, [x0,#0x0]
|
||||
// stp x21, x22, [x0,#0x10]
|
||||
// stp x23, x24, [x0,#0x20]
|
||||
// stp x25, x26, [x0,#0x30]
|
||||
// stp x27, x28, [x0,#0x40]
|
||||
// stp x29, x4, [x0,#0x50]
|
||||
// mov x2, lr
|
||||
// mov x3, sp
|
||||
// stp x2, x3, [x0,#0x60]
|
||||
// stp d8, d9, [x0,#0x70]
|
||||
// stp d10, d11, [x0,#0x80]
|
||||
// stp d12, d13, [x0,#0x90]
|
||||
// stp d14, d15, [x0,#0xa0]
|
||||
// mov x0, #0
|
||||
ret
|
||||
|
||||
.global longjmp
|
||||
longjmp:
|
||||
ld s0, 0(a0)
|
||||
ld s1, 8(a0)
|
||||
ld s2, 16(a0)
|
||||
ld s3, 24(a0)
|
||||
ld s4, 32(a0)
|
||||
ld s5, 40(a0)
|
||||
ld s6, 48(a0)
|
||||
ld s7, 56(a0)
|
||||
ld s8, 64(a0)
|
||||
ld s9, 72(a0)
|
||||
ld s10, 80(a0)
|
||||
ld s11, 88(a0)
|
||||
ld ra, 96(a0)
|
||||
ld sp, 104(a0)
|
||||
bne a0, zero, 1f
|
||||
li a0, 1
|
||||
1:
|
||||
ret
|
||||
29
libs/libc/setjmp/x86/setjmp.S
Normal file
29
libs/libc/setjmp/x86/setjmp.S
Normal file
@@ -0,0 +1,29 @@
|
||||
global setjmp
|
||||
setjmp:
|
||||
mov eax, [esp+4]
|
||||
mov [eax], ebx
|
||||
mov [eax+4], esi
|
||||
mov [eax+8], edi
|
||||
mov [eax+12], ebp
|
||||
lea ecx, [esp+4]
|
||||
mov [eax+16], ecx
|
||||
mov ecx, [esp]
|
||||
mov [eax+20], ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
global longjmp
|
||||
longjmp:
|
||||
mov edx, [esp+4]
|
||||
mov eax, [esp+8]
|
||||
mov ebx, [edx]
|
||||
mov esi, [edx+4]
|
||||
mov edi, [edx+8]
|
||||
mov ebp, [edx+12]
|
||||
mov esp, [edx+16]
|
||||
mov ecx, [edx+20]
|
||||
test eax, eax
|
||||
jnz success
|
||||
mov eax, 1
|
||||
success:
|
||||
jmp ecx
|
||||
35
libs/libc/setjmp/x86_64/setjmp.S
Normal file
35
libs/libc/setjmp/x86_64/setjmp.S
Normal file
@@ -0,0 +1,35 @@
|
||||
[bits 64]
|
||||
|
||||
global setjmp
|
||||
setjmp:
|
||||
mov [rdi], rbx
|
||||
mov [rdi+8], r12
|
||||
mov [rdi+16], r13
|
||||
mov [rdi+24], r14
|
||||
mov [rdi+32], r15
|
||||
mov [rdi+40], rbp
|
||||
mov [rdi+48], rsp
|
||||
|
||||
mov rax, [rsp]
|
||||
mov [rdi+56], rax
|
||||
|
||||
xor rax, rax
|
||||
ret
|
||||
|
||||
global longjmp
|
||||
longjmp:
|
||||
mov rbx, [rdi]
|
||||
mov r12, [rdi+8]
|
||||
mov r13, [rdi+16]
|
||||
mov r14, [rdi+24]
|
||||
mov r15, [rdi+32]
|
||||
mov rbp, [rdi+40]
|
||||
mov rsp, [rdi+48]
|
||||
mov rcx, [rdi+56]
|
||||
|
||||
mov rax, rsi
|
||||
test rax, rax
|
||||
jnz success
|
||||
mov rax, 1
|
||||
success:
|
||||
jmp rcx
|
||||
20
libs/libc/socket/socket.c
Normal file
20
libs/libc/socket/socket.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
int res = DO_SYSCALL_3(SYS_SOCKET, domain, type, protocol);
|
||||
RETURN_WITH_ERRNO(res, res, -1);
|
||||
}
|
||||
|
||||
int bind(int sockfd, const char* name, int len)
|
||||
{
|
||||
int res = DO_SYSCALL_3(SYS_BIND, sockfd, name, len);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
|
||||
int connect(int sockfd, const char* name, int len)
|
||||
{
|
||||
int res = DO_SYSCALL_3(SYS_CONNECT, sockfd, name, len);
|
||||
RETURN_WITH_ERRNO(res, 0, -1);
|
||||
}
|
||||
17
libs/libc/stdio/_internal.h
Normal file
17
libs/libc/stdio/_internal.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _LIBC_STDIO__INTERNAL_H
|
||||
#define _LIBC_STDIO__INTERNAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef int (*_lookupch_callback)(void* callback_params);
|
||||
typedef int (*_getch_callback)(void* callback_params);
|
||||
typedef int (*_putch_callback)(char ch, char* buf_base, size_t* written, void* callback_params);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // _LIBC_STDIO__INTERNAL_H
|
||||
349
libs/libc/stdio/printf.c
Normal file
349
libs/libc/stdio/printf.c
Normal file
@@ -0,0 +1,349 @@
|
||||
#include "_internal.h"
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char* HEX_alphabet = "0123456789ABCDEF";
|
||||
static const char* hex_alphabet = "0123456789abcdef";
|
||||
|
||||
static int _printf_hex32_impl(unsigned int value, const char* alph, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[16];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = alph[(value % 16)];
|
||||
value /= 16;
|
||||
}
|
||||
|
||||
callback('0', base_buf, written, callback_params);
|
||||
callback('x', base_buf, written, callback_params);
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_hex64_impl(unsigned long value, const char* alph, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[32];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = alph[(value % 16)];
|
||||
value /= 16;
|
||||
}
|
||||
|
||||
callback('0', base_buf, written, callback_params);
|
||||
callback('x', base_buf, written, callback_params);
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_hex32(unsigned int value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex32_impl(value, hex_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_HEX32(unsigned int value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex32_impl(value, HEX_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_hex64(unsigned long value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex64_impl(value, hex_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_HEX64(unsigned long value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
return _printf_hex64_impl(value, HEX_alphabet, base_buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_u32(unsigned int value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[16];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = (value % 10) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_u64(unsigned long value, char* base_buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
int nxt = 0;
|
||||
char tmp_buf[32];
|
||||
|
||||
while (value > 0) {
|
||||
tmp_buf[nxt++] = (value % 10) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
if (nxt == 0) {
|
||||
callback('0', base_buf, written, callback_params);
|
||||
}
|
||||
|
||||
while (nxt) {
|
||||
callback(tmp_buf[--nxt], base_buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _printf_i32(int value, char* buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
if (value < 0) {
|
||||
callback('-', buf, written, callback_params);
|
||||
value = -value;
|
||||
}
|
||||
return _printf_u32(value, buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_i64(long value, char* buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
if (value < 0) {
|
||||
callback('-', buf, written, callback_params);
|
||||
value = -value;
|
||||
}
|
||||
return _printf_u64(value, buf, written, callback, callback_params);
|
||||
}
|
||||
|
||||
static int _printf_string(const char* value, char* buf, size_t* written, _putch_callback callback, void* callback_params)
|
||||
{
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len = strlen(value);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
callback(value[i], buf, written, callback_params);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t _printf_internal(char* buf, const char* format, _putch_callback callback, void* callback_params, va_list arg)
|
||||
{
|
||||
const char* p = format;
|
||||
size_t written = 0;
|
||||
while (*p) {
|
||||
int l_arg = 0;
|
||||
int h_arg = 0;
|
||||
if (*p == '%' && *(p + 1)) {
|
||||
// Reading arguments
|
||||
parse_args:
|
||||
p++;
|
||||
switch (*p) {
|
||||
case 'l':
|
||||
l_arg++;
|
||||
if (*(p + 1)) {
|
||||
goto parse_args;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
h_arg++;
|
||||
if (*(p + 1)) {
|
||||
goto parse_args;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Reading conversion specifiers
|
||||
switch (*p) {
|
||||
case 'i':
|
||||
case 'd':
|
||||
if (l_arg) {
|
||||
long value = va_arg(arg, long);
|
||||
_printf_i64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
int value = va_arg(arg, int);
|
||||
_printf_i32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (l_arg) {
|
||||
uint64_t value = va_arg(arg, uint64_t);
|
||||
_printf_u64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
uint32_t value = va_arg(arg, uint32_t);
|
||||
_printf_u32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
if (l_arg) {
|
||||
uint64_t value = va_arg(arg, uint64_t);
|
||||
_printf_hex64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
uint32_t value = va_arg(arg, uint32_t);
|
||||
_printf_hex32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
if (l_arg) {
|
||||
uint64_t value = va_arg(arg, uint64_t);
|
||||
_printf_HEX64(value, buf, &written, callback, callback_params);
|
||||
} else {
|
||||
uint32_t value = va_arg(arg, uint32_t);
|
||||
_printf_HEX32(value, buf, &written, callback, callback_params);
|
||||
}
|
||||
break;
|
||||
case 'c': {
|
||||
char value = (char)va_arg(arg, int);
|
||||
callback(value, buf, &written, callback_params);
|
||||
} break;
|
||||
case 's': {
|
||||
const char* value = va_arg(arg, const char*);
|
||||
_printf_string(value, buf, &written, callback, callback_params);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
callback(*p, buf, &written, callback_params);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
static int putch_callback_sized_buf(char ch, char* buf_base, size_t* written, void* callback_params)
|
||||
{
|
||||
if (!callback_params) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!written) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t n = *(size_t*)callback_params;
|
||||
size_t vw = *written;
|
||||
if (vw >= n) {
|
||||
return -1;
|
||||
}
|
||||
buf_base[vw++] = ch;
|
||||
*written = vw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vsnprintf(char* s, size_t n, const char* format, va_list arg)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t wr = _printf_internal(s, format, putch_callback_sized_buf, &n, arg);
|
||||
if (wr == n) {
|
||||
s[n - 1] = '\0';
|
||||
} else {
|
||||
s[wr] = '\0';
|
||||
}
|
||||
return (int)wr;
|
||||
}
|
||||
|
||||
int snprintf(char* s, size_t n, const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int res = vsnprintf(s, n, format, arg);
|
||||
va_end(arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int putch_callback_buf(char ch, char* buf_base, size_t* written, void* callback_params)
|
||||
{
|
||||
if (!written) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t vw = *written;
|
||||
buf_base[vw++] = ch;
|
||||
*written = vw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vsprintf(char* s, const char* format, va_list arg)
|
||||
{
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
ssize_t wr = _printf_internal(s, format, putch_callback_buf, NULL, arg);
|
||||
s[wr] = '\0';
|
||||
return (int)wr;
|
||||
}
|
||||
|
||||
int sprintf(char* s, const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int res = vsprintf(s, format, arg);
|
||||
va_end(arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int putch_callback_stream(char c, char* buf_base, size_t* written, void* callback_params)
|
||||
{
|
||||
FILE* stream = (FILE*)callback_params;
|
||||
if (!stream) {
|
||||
return -1;
|
||||
}
|
||||
return fputc(c, stream);
|
||||
}
|
||||
|
||||
static int vfprintf(FILE* stream, const char* format, va_list arg)
|
||||
{
|
||||
return _printf_internal(NULL, format, putch_callback_stream, stream, arg);
|
||||
}
|
||||
|
||||
int fprintf(FILE* stream, const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int res = vfprintf(stream, format, arg);
|
||||
va_end(arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int vprintf(const char* format, va_list arg)
|
||||
{
|
||||
return vfprintf(stdout, format, arg);
|
||||
}
|
||||
|
||||
int printf(const char* format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
int ret = vprintf(format, arg);
|
||||
va_end(arg);
|
||||
return ret;
|
||||
}
|
||||
202
libs/libc/stdio/scanf.c
Normal file
202
libs/libc/stdio/scanf.c
Normal file
@@ -0,0 +1,202 @@
|
||||
#include "_internal.h"
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/_structs.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int _scanf_u32(_lookupch_callback lookupch, _getch_callback getch, void* callback_params, uint32_t* val)
|
||||
{
|
||||
int read = 0;
|
||||
uint32_t res = 0;
|
||||
while (isdigit(lookupch(callback_params))) {
|
||||
res *= 10;
|
||||
char ch = getch(callback_params);
|
||||
res += (ch - '0');
|
||||
read++;
|
||||
}
|
||||
*val = res;
|
||||
return read;
|
||||
}
|
||||
|
||||
static int _scanf_i32(_lookupch_callback lookupch, _getch_callback getch, void* callback_params, int* val)
|
||||
{
|
||||
int read = 0;
|
||||
bool negative = 0;
|
||||
if (lookupch(callback_params) == '-') {
|
||||
negative = true;
|
||||
getch(callback_params);
|
||||
read++;
|
||||
}
|
||||
|
||||
uint32_t tmp_u32;
|
||||
int read_imm = _scanf_u32(lookupch, getch, callback_params, &tmp_u32);
|
||||
if (!read_imm) {
|
||||
return 0;
|
||||
}
|
||||
read += read_imm;
|
||||
|
||||
int tmp_i32 = (int)tmp_u32;
|
||||
if (negative) {
|
||||
tmp_i32 = -tmp_i32;
|
||||
}
|
||||
*val = tmp_i32;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
static int _scanf_internal(const char* format, _lookupch_callback lookupch, _getch_callback getch, void* callback_params, va_list arg)
|
||||
{
|
||||
const char* p = format;
|
||||
int passed = 0;
|
||||
|
||||
while (*p) {
|
||||
int l_arg = 0;
|
||||
int h_arg = 0;
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
if (*p == '%' && *(p + 1)) {
|
||||
// Reading arguments
|
||||
parse_args:
|
||||
p++;
|
||||
switch (*p) {
|
||||
case 'l':
|
||||
l_arg++;
|
||||
if (*(p + 1)) {
|
||||
goto parse_args;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
h_arg++;
|
||||
if (*(p + 1)) {
|
||||
goto parse_args;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while (isspace(lookupch(callback_params))) {
|
||||
getch(callback_params);
|
||||
passed++;
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
case 'i':
|
||||
case 'd':
|
||||
if (!l_arg) {
|
||||
int* value = va_arg(arg, int*);
|
||||
int read = _scanf_i32(lookupch, getch, callback_params, value);
|
||||
passed += read;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (!l_arg) {
|
||||
uint32_t* value = va_arg(arg, uint32_t*);
|
||||
int read = _scanf_u32(lookupch, getch, callback_params, value);
|
||||
passed += read;
|
||||
}
|
||||
break;
|
||||
case 's': {
|
||||
int rv = 0;
|
||||
char* value = va_arg(arg, char*);
|
||||
while (!isspace(lookupch(callback_params))) {
|
||||
char ch = getch(callback_params);
|
||||
value[rv++] = ch;
|
||||
passed++;
|
||||
}
|
||||
value[rv] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
} else {
|
||||
while (isspace(lookupch(callback_params))) {
|
||||
getch(callback_params);
|
||||
passed++;
|
||||
}
|
||||
if (lookupch(callback_params) != *p) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
getch(callback_params);
|
||||
passed++;
|
||||
}
|
||||
}
|
||||
return passed;
|
||||
}
|
||||
|
||||
struct buffer_params {
|
||||
const char* buf;
|
||||
};
|
||||
typedef struct buffer_params buffer_params_t;
|
||||
|
||||
static int lookup_callback_buffer(void* callback_params)
|
||||
{
|
||||
buffer_params_t* bp = (buffer_params_t*)callback_params;
|
||||
if (!bp->buf) {
|
||||
return EOF;
|
||||
}
|
||||
return *bp->buf;
|
||||
}
|
||||
|
||||
static int getch_callback_buffer(void* callback_params)
|
||||
{
|
||||
buffer_params_t* bp = (buffer_params_t*)callback_params;
|
||||
if (!bp->buf) {
|
||||
return EOF;
|
||||
}
|
||||
char res = *bp->buf;
|
||||
bp->buf++;
|
||||
return res;
|
||||
}
|
||||
|
||||
int vsscanf(const char* buf, const char* format, va_list arg)
|
||||
{
|
||||
buffer_params_t bp = { .buf = buf };
|
||||
return _scanf_internal(format, lookup_callback_buffer, getch_callback_buffer, (void*)&bp, arg);
|
||||
}
|
||||
|
||||
static int lookup_callback_stream(void* callback_params)
|
||||
{
|
||||
FILE* file = (FILE*)callback_params;
|
||||
int res = fgetc(file);
|
||||
ungetc(res, file);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int getch_callback_stream(void* callback_params)
|
||||
{
|
||||
FILE* file = (FILE*)callback_params;
|
||||
int res = fgetc(file);
|
||||
return res;
|
||||
}
|
||||
|
||||
int vfscanf(FILE* stream, const char* format, va_list arg)
|
||||
{
|
||||
return _scanf_internal(format, lookup_callback_stream, getch_callback_stream, (void*)stream, arg);
|
||||
}
|
||||
|
||||
int sscanf(const char* buf, const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int count = vsscanf(buf, format, ap);
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
||||
|
||||
int scanf(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int count = vfscanf(stdin, format, ap);
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
||||
668
libs/libc/stdio/stdio.c
Normal file
668
libs/libc/stdio/stdio.c
Normal file
@@ -0,0 +1,668 @@
|
||||
#include <bits/errno.h>
|
||||
#include <bits/fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define _IO_MAGIC 0xFBAD0000 /* Magic number */
|
||||
#define _IO_MAGIC_MASK 0xFFFF0000
|
||||
#define _IO_USER_BUF 0x0001 /* Don't deallocate buffer on close. */
|
||||
#define _IO_UNBUFFERED 0x0002
|
||||
#define _IO_NO_READS 0x0004 /* Reading not allowed. */
|
||||
#define _IO_NO_WRITES 0x0008 /* Writing not allowed. */
|
||||
#define _IO_EOF_SEEN 0x0010
|
||||
#define _IO_ERR_SEEN 0x0020
|
||||
#define _IO_DELETE_DONT_CLOSE 0x0040 /* Don't call close(_fileno) on close. */
|
||||
#define _IO_LINKED 0x0080 /* In the list of all open files. */
|
||||
#define _IO_IN_BACKUP 0x0100
|
||||
#define _IO_LINE_BUF 0x0200
|
||||
#define _IO_TIED_PUT_GET 0x0400 /* Put and get pointer move in unison. */
|
||||
#define _IO_CURRENTLY_PUTTING 0x0800
|
||||
#define _IO_IS_APPENDING 0x1000
|
||||
#define _IO_IS_FILEBUF 0x2000
|
||||
/* 0x4000 No longer used, reserved for compat. */
|
||||
#define _IO_USER_LOCK 0x8000
|
||||
|
||||
struct __fbuf {
|
||||
char* base;
|
||||
char* ptr; /* current pointer */
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct __rwbuf {
|
||||
__fbuf_t rbuf;
|
||||
__fbuf_t wbuf;
|
||||
char* base;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct __file {
|
||||
int _flags; /* flags, below; this FILE is free if 0 */
|
||||
int _file; /* fileno, if Unix descriptor, else -1 */
|
||||
size_t _r; /* read space left */
|
||||
size_t _w; /* write space left */
|
||||
__rwbuf_t _bf; /* rw buffer */
|
||||
int _ungotc; /* ungot char. If spot is empty, it equals to UNGOTC_EMPTY */
|
||||
};
|
||||
|
||||
static FILE _stdstreams[3];
|
||||
FILE* stdin = &_stdstreams[0];
|
||||
FILE* stdout = &_stdstreams[1];
|
||||
FILE* stderr = &_stdstreams[2];
|
||||
|
||||
/* Static functions */
|
||||
static inline int _can_read(FILE* file);
|
||||
static inline int _can_write(FILE* file);
|
||||
static inline int _can_use_buffer(FILE* file);
|
||||
static int _parse_mode(const char* mode, mode_t* flags);
|
||||
|
||||
/* Buffer */
|
||||
static inline int _free_buf(FILE* stream);
|
||||
static size_t _do_system_write(const void* ptr, size_t size, FILE* stream);
|
||||
static int _resize_buf(FILE* stream, size_t size);
|
||||
static ssize_t _flush_wbuf(FILE* stream);
|
||||
static void _split_rwbuf(FILE* stream);
|
||||
static int _resize_buf(FILE* stream, size_t size);
|
||||
|
||||
/* Stream */
|
||||
static int _init_stream(FILE* file);
|
||||
static int _init_file_with_fd(FILE* file, int fd);
|
||||
static int _open_file(FILE* file, const char* path, const char* mode);
|
||||
static FILE* _fopen_internal(const char* path, const char* mode);
|
||||
|
||||
/* Read/write */
|
||||
static size_t _do_system_read(char* ptr, size_t size, FILE* stream);
|
||||
static size_t _do_system_write(const void* ptr, size_t size, FILE* stream);
|
||||
static size_t _fread_internal(char* ptr, size_t size, FILE* stream);
|
||||
static size_t _fwrite_internal(const void* ptr, size_t size, FILE* stream);
|
||||
|
||||
/* Public functions */
|
||||
|
||||
FILE* fopen(const char* path, const char* mode)
|
||||
{
|
||||
if (!path || !mode)
|
||||
return NULL;
|
||||
|
||||
return _fopen_internal(path, mode);
|
||||
}
|
||||
|
||||
int fclose(FILE* stream)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Flush & close the stream, and then free any allocated memory. */
|
||||
fflush(stream);
|
||||
res = close(stream->_file);
|
||||
|
||||
if (res == -EBADF || res == -EFAULT)
|
||||
return EOF;
|
||||
|
||||
_free_buf(stream);
|
||||
free(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t fread(void* ptr, size_t size, size_t count, FILE* stream)
|
||||
{
|
||||
if (!ptr || !stream)
|
||||
return 0;
|
||||
|
||||
return _fread_internal(ptr, size * count, stream);
|
||||
}
|
||||
|
||||
size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream)
|
||||
{
|
||||
if (!ptr) {
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!stream) {
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _fwrite_internal(ptr, size * count, stream);
|
||||
}
|
||||
|
||||
static void _drop_rbuf(FILE* stream)
|
||||
{
|
||||
stream->_r = 0;
|
||||
stream->_ungotc = UNGOTC_EMPTY;
|
||||
}
|
||||
|
||||
int fseek(FILE* stream, uint32_t offset, int origin)
|
||||
{
|
||||
if (!stream) {
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
fflush(stream);
|
||||
_drop_rbuf(stream);
|
||||
|
||||
return lseek(stream->_file, offset, origin);
|
||||
}
|
||||
|
||||
int fputc(int c, FILE* stream)
|
||||
{
|
||||
int res = fwrite(&c, 1, 1, stream);
|
||||
if (!res)
|
||||
return -errno;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int putc(int c, FILE* stream)
|
||||
{
|
||||
return fputc(c, stream);
|
||||
}
|
||||
|
||||
int putchar(int c)
|
||||
{
|
||||
return fputc(c, stdout);
|
||||
}
|
||||
|
||||
long ftell(FILE* stream)
|
||||
{
|
||||
if (!stream) {
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fflush(stream);
|
||||
_drop_rbuf(stream);
|
||||
|
||||
return lseek(stream->_file, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
int fputs(const char* s, FILE* stream)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
int res = fwrite(s, len, 1, stream);
|
||||
|
||||
if (!res)
|
||||
return -errno;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int puts(const char* s)
|
||||
{
|
||||
return fputs(s, stdout);
|
||||
}
|
||||
|
||||
int fgetc(FILE* stream)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (fread(&c, 1, 1, stream) != 1)
|
||||
return EOF;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int getc(FILE* stream)
|
||||
{
|
||||
return fgetc(stream);
|
||||
}
|
||||
|
||||
int getchar()
|
||||
{
|
||||
return fgetc(stdin);
|
||||
}
|
||||
|
||||
int ungetc(int c, FILE* stream)
|
||||
{
|
||||
if (c == EOF)
|
||||
return EOF;
|
||||
|
||||
if (!stream) {
|
||||
set_errno(EINVAL);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (stream->_ungotc != UNGOTC_EMPTY) {
|
||||
set_errno(EBUSY);
|
||||
return EOF;
|
||||
}
|
||||
|
||||
stream->_flags &= ~_IO_EOF_SEEN;
|
||||
stream->_ungotc = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
char* fgets(char* s, int size, FILE* stream)
|
||||
{
|
||||
unsigned int rd = 0;
|
||||
char c;
|
||||
|
||||
if (!stream) {
|
||||
set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We need to flush the stdout and stderr streams before reading. */
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
while (c != '\n' && rd < size) {
|
||||
if ((c = fgetc(stream)) < 0) {
|
||||
if (rd == 0) {
|
||||
return NULL;
|
||||
}
|
||||
// EOF should be set
|
||||
s[rd] = '\0';
|
||||
break;
|
||||
}
|
||||
s[rd++] = c;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char* gets(char* str)
|
||||
{
|
||||
// Currently the max size of gets is 4096.
|
||||
return fgets(str, 4096, stdout);
|
||||
}
|
||||
|
||||
int setvbuf(FILE* stream, char* buf, int mode, size_t size)
|
||||
{
|
||||
if (!stream) {
|
||||
set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode != _IONBF && mode != _IOLBF && mode != _IOFBF) {
|
||||
set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Clear the buffer type flags and reset it. */
|
||||
|
||||
stream->_flags &= ~(int)(_IO_UNBUFFERED | _IO_LINE_BUF);
|
||||
if (mode & _IOLBF)
|
||||
stream->_flags |= _IO_LINE_BUF;
|
||||
|
||||
if (mode & _IONBF)
|
||||
stream->_flags |= _IO_UNBUFFERED;
|
||||
|
||||
_flush_wbuf(stream);
|
||||
|
||||
if (!_can_use_buffer(stream))
|
||||
return _free_buf(stream);
|
||||
|
||||
if (!buf)
|
||||
return _resize_buf(stream, size);
|
||||
|
||||
stream->_bf.base = buf;
|
||||
stream->_bf.size = size;
|
||||
_split_rwbuf(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setbuf(FILE* stream, char* buf)
|
||||
{
|
||||
setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
|
||||
}
|
||||
|
||||
void setlinebuf(FILE* stream)
|
||||
{
|
||||
setvbuf(stream, NULL, _IOLBF, 0);
|
||||
}
|
||||
|
||||
int fflush(FILE* stream)
|
||||
{
|
||||
if (!stream)
|
||||
return -EBADF;
|
||||
|
||||
return _flush_wbuf(stream);
|
||||
}
|
||||
|
||||
int feof(FILE* stream)
|
||||
{
|
||||
return stream->_flags & _IO_EOF_SEEN;
|
||||
}
|
||||
|
||||
int __stream_info(FILE* stream)
|
||||
{
|
||||
static const char* names[] = { "(STDIN) ", "(STDOUT) ", "(STDERR) " };
|
||||
char rwinfo[4] = "-/-";
|
||||
__fbuf_t *rbuf, *wbuf;
|
||||
const char* name;
|
||||
|
||||
if (!stream)
|
||||
return 1;
|
||||
|
||||
if (stream->_file >= 0 && stream->_file <= 2)
|
||||
name = names[stream->_file];
|
||||
|
||||
if (_can_read(stream)) {
|
||||
rwinfo[0] = 'r';
|
||||
rbuf = &stream->_bf.rbuf;
|
||||
}
|
||||
|
||||
if (_can_write(stream)) {
|
||||
rwinfo[2] = 'w';
|
||||
wbuf = &stream->_bf.wbuf;
|
||||
}
|
||||
|
||||
printf("__stream_info():\n");
|
||||
printf(" fd=%d %sflags=%s\n", stream->_file, name, rwinfo);
|
||||
printf(" ungotc=%s val=%x\n", stream->_ungotc == UNGOTC_EMPTY ? "False" : "True", stream->_ungotc);
|
||||
|
||||
if (_can_read(stream)) {
|
||||
printf(" read space left=%u\n", stream->_r);
|
||||
printf(" rbuf.base=%x rbuf.size=%u rbuf.ptr=%x\n", (size_t)rbuf->base,
|
||||
rbuf->size, (size_t)rbuf->ptr);
|
||||
}
|
||||
|
||||
if (_can_write(stream)) {
|
||||
printf(" write space left=%u\n", stream->_w);
|
||||
printf(" wbuf.base=%x wbuf.size=%u wbuf.ptr=%x\n", (size_t)wbuf->base,
|
||||
wbuf->size, (size_t)wbuf->ptr);
|
||||
}
|
||||
|
||||
printf(" rwbuf.base=%x rwbuf.size=%u\n", (size_t)stream->_bf.base,
|
||||
stream->_bf.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _stdio_init()
|
||||
{
|
||||
_init_file_with_fd(stdin, STDIN);
|
||||
_init_file_with_fd(stdout, STDOUT);
|
||||
_init_file_with_fd(stderr, STDERR);
|
||||
setbuf(stderr, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _stdio_deinit()
|
||||
{
|
||||
// FIXME
|
||||
_flush_wbuf(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Static functions */
|
||||
|
||||
static inline int _can_read(FILE* file)
|
||||
{
|
||||
return (file->_flags & _IO_NO_READS) == 0;
|
||||
}
|
||||
|
||||
static inline int _can_write(FILE* file)
|
||||
{
|
||||
return (file->_flags & _IO_NO_WRITES) == 0;
|
||||
}
|
||||
|
||||
static inline int _can_use_buffer(FILE* file)
|
||||
{
|
||||
return (file->_flags & _IO_UNBUFFERED) == 0;
|
||||
}
|
||||
|
||||
/* Because this checks the first and second character only, the possible
|
||||
combinations are: r, w, a, r+ and w+. */
|
||||
static int _parse_mode(const char* mode, mode_t* flags)
|
||||
{
|
||||
int has_plus, len;
|
||||
|
||||
if (!(len = strlen(mode)))
|
||||
return 0;
|
||||
|
||||
*flags = 0;
|
||||
if (len > 1 && mode[1] == '+')
|
||||
has_plus = 1;
|
||||
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
*flags = has_plus ? O_RDONLY : O_RDWR;
|
||||
return 0;
|
||||
|
||||
case 'w':
|
||||
*flags = has_plus ? (O_WRONLY | O_CREAT) : (O_RDWR | O_CREAT);
|
||||
return 0;
|
||||
|
||||
case 'a':
|
||||
*flags = O_APPEND | O_CREAT;
|
||||
return 0;
|
||||
|
||||
/* TODO: Add binary mode when the rest will support such option. */
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Buffer */
|
||||
|
||||
static inline int _free_buf(FILE* stream)
|
||||
{
|
||||
/* Don't free the buffer if the user provided one with setvbuf. */
|
||||
if (stream->_flags & _IO_USER_BUF)
|
||||
return 0;
|
||||
|
||||
if (stream->_bf.base)
|
||||
free(stream->_bf.base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _split_rwbuf(FILE* stream)
|
||||
{
|
||||
size_t rsize, wsize;
|
||||
|
||||
rsize = ((stream->_bf.size + 1) / 2) & (size_t)~0x03;
|
||||
wsize = (stream->_bf.size - rsize) & (size_t)~0x03;
|
||||
|
||||
/* TODO: Base on stream flags. */
|
||||
stream->_bf.rbuf.base = stream->_bf.base;
|
||||
stream->_bf.rbuf.ptr = stream->_bf.rbuf.base;
|
||||
stream->_bf.rbuf.size = rsize;
|
||||
|
||||
stream->_bf.wbuf.base = stream->_bf.base + stream->_bf.rbuf.size;
|
||||
stream->_bf.wbuf.ptr = stream->_bf.wbuf.base;
|
||||
stream->_bf.wbuf.size = wsize;
|
||||
|
||||
stream->_r = 0;
|
||||
stream->_w = stream->_bf.wbuf.size;
|
||||
}
|
||||
|
||||
static int _resize_buf(FILE* stream, size_t size)
|
||||
{
|
||||
_free_buf(stream);
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
stream->_bf.base = malloc(size);
|
||||
|
||||
if (!stream->_bf.base) {
|
||||
stream->_r = 0;
|
||||
stream->_w = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
stream->_bf.size = size;
|
||||
_split_rwbuf(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t _flush_wbuf(FILE* stream)
|
||||
{
|
||||
size_t write_size, written;
|
||||
|
||||
write_size = stream->_bf.wbuf.size - stream->_w;
|
||||
written = _do_system_write(stream->_bf.wbuf.base, write_size, stream);
|
||||
|
||||
if (written != write_size)
|
||||
return -EFAULT;
|
||||
|
||||
stream->_w = stream->_bf.wbuf.size;
|
||||
stream->_bf.wbuf.ptr = stream->_bf.wbuf.base;
|
||||
return (ssize_t)write;
|
||||
}
|
||||
|
||||
/* Stream */
|
||||
|
||||
static int _init_stream(FILE* file)
|
||||
{
|
||||
file->_file = -1;
|
||||
file->_flags = _IO_MAGIC;
|
||||
file->_r = 0;
|
||||
file->_w = 0;
|
||||
file->_bf.base = NULL;
|
||||
file->_bf.size = 0;
|
||||
file->_ungotc = UNGOTC_EMPTY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _init_file_with_fd(FILE* file, int fd)
|
||||
{
|
||||
_init_stream(file);
|
||||
_resize_buf(file, BUFSIZ);
|
||||
file->_file = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _open_file(FILE* file, const char* path, const char* mode)
|
||||
{
|
||||
mode_t flags = 0;
|
||||
int err = _parse_mode(mode, &flags);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
int fd = open(path, flags);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
|
||||
file->_file = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FILE* _fopen_internal(const char* path, const char* mode)
|
||||
{
|
||||
FILE* file = malloc(sizeof(FILE));
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
_init_stream(file);
|
||||
_resize_buf(file, BUFSIZ);
|
||||
_open_file(file, path, mode);
|
||||
return file;
|
||||
}
|
||||
|
||||
/* Read */
|
||||
|
||||
static size_t _do_system_read(char* ptr, size_t size, FILE* stream)
|
||||
{
|
||||
ssize_t read_size = read(stream->_file, ptr, size);
|
||||
return read_size < 0 ? 0 : (size_t)read_size;
|
||||
}
|
||||
|
||||
static size_t _do_system_write(const void* ptr, size_t size, FILE* stream)
|
||||
{
|
||||
ssize_t write_size = write(stream->_file, ptr, size);
|
||||
|
||||
if (write_size < 0)
|
||||
return 0;
|
||||
|
||||
return (size_t)write_size;
|
||||
}
|
||||
|
||||
static size_t _fread_internal(char* ptr, size_t size, FILE* stream)
|
||||
{
|
||||
size_t total_size, read_from_buf;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
if (!_can_use_buffer(stream)) {
|
||||
total_size = _do_system_read(ptr, size, stream);
|
||||
if (total_size < size) {
|
||||
stream->_flags |= _IO_EOF_SEEN;
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
total_size = 0;
|
||||
|
||||
/* If the ungot char buffer is not empty, push it onto the buffer first. */
|
||||
if (stream->_ungotc != UNGOTC_EMPTY) {
|
||||
ptr[0] = (char)stream->_ungotc;
|
||||
ptr++;
|
||||
size--;
|
||||
total_size++;
|
||||
stream->_ungotc = UNGOTC_EMPTY;
|
||||
}
|
||||
|
||||
/* First read any bytes still sitting in the read buffer. */
|
||||
if (stream->_r) {
|
||||
read_from_buf = min(stream->_r, size);
|
||||
memcpy(ptr, stream->_bf.rbuf.ptr, read_from_buf);
|
||||
ptr += read_from_buf;
|
||||
size -= read_from_buf;
|
||||
stream->_bf.rbuf.ptr += read_from_buf;
|
||||
stream->_r -= read_from_buf;
|
||||
total_size += read_from_buf;
|
||||
}
|
||||
|
||||
/* Read the remaining bytes that were not stored in the read buffer. */
|
||||
while (size > 0) {
|
||||
stream->_bf.rbuf.ptr = stream->_bf.rbuf.base;
|
||||
stream->_r = _do_system_read(
|
||||
stream->_bf.rbuf.ptr, stream->_bf.rbuf.size, stream);
|
||||
|
||||
if (!stream->_r) {
|
||||
if (size) {
|
||||
stream->_flags |= _IO_EOF_SEEN;
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
read_from_buf = min(stream->_r, size);
|
||||
memcpy(ptr, stream->_bf.rbuf.ptr, read_from_buf);
|
||||
ptr += read_from_buf;
|
||||
size -= read_from_buf;
|
||||
stream->_bf.rbuf.ptr += read_from_buf;
|
||||
stream->_r -= read_from_buf;
|
||||
total_size += read_from_buf;
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
static size_t _fwrite_internal(const void* ptr, size_t size, FILE* stream)
|
||||
{
|
||||
size_t total_size;
|
||||
|
||||
if (!_can_use_buffer(stream))
|
||||
return _do_system_write(ptr, size, stream);
|
||||
|
||||
total_size = 0;
|
||||
while (size > 0) {
|
||||
size_t write_size = min(stream->_w, size);
|
||||
memcpy(stream->_bf.wbuf.ptr, ptr, write_size);
|
||||
ptr += write_size;
|
||||
size -= write_size;
|
||||
stream->_bf.wbuf.ptr += write_size;
|
||||
stream->_w -= write_size;
|
||||
total_size += write_size;
|
||||
|
||||
if (!stream->_w)
|
||||
_flush_wbuf(stream);
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
115
libs/libc/stdlib/env.c
Normal file
115
libs/libc/stdlib/env.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void free_var(const char* string)
|
||||
{
|
||||
// TODO: Implement me!
|
||||
}
|
||||
|
||||
char* getenv(const char* name)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
for (int i = 0; environ[i]; i++) {
|
||||
const char* envv = environ[i];
|
||||
char* eqpos = strchr(envv, '=');
|
||||
if (!eqpos) {
|
||||
continue;
|
||||
}
|
||||
size_t curlen = (size_t)(eqpos - envv);
|
||||
if (curlen == len && strncmp(name, envv, len) == 0) {
|
||||
return (char*)&envv[len + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int setenv(const char* name, const char* value, int overwrite)
|
||||
{
|
||||
if (!overwrite && getenv(name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int name_len = strlen(name);
|
||||
int value_len = strlen(value);
|
||||
int len = name_len + 1 + value_len;
|
||||
char* string = (char*)malloc(len + 1);
|
||||
strncpy(string, name, name_len);
|
||||
string[name_len] = '=';
|
||||
strncpy(&string[name_len + 1], value, value_len);
|
||||
string[len] = '\0';
|
||||
return putenv(string);
|
||||
}
|
||||
|
||||
int putenv(char* string)
|
||||
{
|
||||
char* pos = strchr(string, '=');
|
||||
if (!pos) {
|
||||
return unsetenv(string);
|
||||
}
|
||||
|
||||
size_t len = (size_t)(pos - string);
|
||||
int env_i = 0;
|
||||
for (; environ[env_i]; env_i++) {
|
||||
const char* envv = environ[env_i];
|
||||
char* eqpos = strchr(envv, '=');
|
||||
if (!eqpos) {
|
||||
continue;
|
||||
}
|
||||
size_t curlen = (size_t)(eqpos - envv);
|
||||
if (len != curlen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(string, envv, len) == 0) {
|
||||
free_var(envv);
|
||||
environ[env_i] = string;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char** new_environ = (char**)malloc(sizeof(char*) * (env_i + 2));
|
||||
for (int i = 0; i < env_i; i++) {
|
||||
new_environ[i] = environ[i];
|
||||
}
|
||||
new_environ[env_i] = string;
|
||||
new_environ[env_i + 1] = NULL;
|
||||
|
||||
extern int __environ_malloced;
|
||||
if (__environ_malloced) {
|
||||
free(environ);
|
||||
}
|
||||
environ = new_environ;
|
||||
__environ_malloced = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unsetenv(const char* name)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
int env_i = 0;
|
||||
int remove_pos = 0;
|
||||
const char* remove_env = NULL;
|
||||
for (; environ[env_i]; env_i++) {
|
||||
const char* envv = environ[env_i];
|
||||
char* eqpos = strchr(envv, '=');
|
||||
if (!eqpos) {
|
||||
continue;
|
||||
}
|
||||
size_t curlen = (size_t)(eqpos - envv);
|
||||
if (len != curlen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(name, envv, len) == 0) {
|
||||
remove_pos = env_i;
|
||||
remove_env = envv;
|
||||
}
|
||||
}
|
||||
|
||||
size_t move_len = ((env_i - 1) - remove_pos) * sizeof(char*);
|
||||
memmove(&environ[remove_pos], &environ[remove_pos + 1], move_len);
|
||||
free_var(remove_env);
|
||||
return 0;
|
||||
}
|
||||
15
libs/libc/stdlib/exit.c
Normal file
15
libs/libc/stdlib/exit.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
void exit(int status)
|
||||
{
|
||||
DO_SYSCALL_1(SYS_EXIT, status);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void abort()
|
||||
{
|
||||
raise(SIGABRT);
|
||||
exit(127);
|
||||
}
|
||||
50
libs/libc/stdlib/pts.c
Normal file
50
libs/libc/stdlib/pts.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define _PATH_PTS "/dev/pts"
|
||||
#define MASTER_PTY(dev) (major(dev) == 128)
|
||||
#define SLAVE_PTY(dev) (major(dev) == 136)
|
||||
|
||||
int posix_openpt(int flags)
|
||||
{
|
||||
return open("/dev/ptmx", flags);
|
||||
}
|
||||
|
||||
int ptsname_r(int fd, char* buf, size_t buflen)
|
||||
{
|
||||
int len = strlen(_PATH_PTS);
|
||||
if (buflen < len + 2) {
|
||||
set_errno(ERANGE);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
stat_t stat;
|
||||
if (fstat(fd, &stat) < 0) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (!MASTER_PTY(stat.st_dev)) {
|
||||
set_errno(ENOTTY);
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
int ptyno = minor(stat.st_dev);
|
||||
|
||||
char* p = strcpy(buf, _PATH_PTS);
|
||||
p[len + 0] = '0' + ptyno;
|
||||
p[len + 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char ptsbuf[32];
|
||||
char* ptsname(int fd)
|
||||
{
|
||||
if (ptsname_r(fd, ptsbuf, sizeof(ptsbuf)) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ptsbuf;
|
||||
}
|
||||
144
libs/libc/stdlib/tools.c
Normal file
144
libs/libc/stdlib/tools.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int atoi(const char* s)
|
||||
{
|
||||
// FIXME: Add overflow checks
|
||||
int res = 0;
|
||||
int len = strlen(s);
|
||||
int mul = 1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
mul *= 10;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
mul /= 10;
|
||||
res += (s[i] - '0') * mul;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
long strtol(const char* nptr, char** endptr, int base)
|
||||
{
|
||||
const char* p = nptr;
|
||||
const char* endp = nptr;
|
||||
bool negative = false;
|
||||
bool overflow = false;
|
||||
unsigned long n = 0;
|
||||
|
||||
if (base < 0 || base == 1 || base > 36) {
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '+') {
|
||||
p++;
|
||||
} else if (*p == '-') {
|
||||
negative = 1;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '0') {
|
||||
p++;
|
||||
endp = p;
|
||||
if (base == 16 && (*p == 'X' || *p == 'x')) {
|
||||
p++;
|
||||
} else if (base == 0) {
|
||||
if (*p == 'X' || *p == 'x') {
|
||||
base = 16, p++;
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
} else if (base == 0) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
unsigned long cutoff = (negative) ? -(LONG_MIN / base) : LONG_MAX / base;
|
||||
int cutlim = (negative) ? -(LONG_MIN % base) : LONG_MAX % base;
|
||||
|
||||
for (;;) {
|
||||
int digit;
|
||||
if (*p >= 'a') {
|
||||
digit = (*p - 'a') + 10;
|
||||
} else if (*p >= 'A') {
|
||||
digit = *p - 'A' + 10;
|
||||
} else if (*p <= '9') {
|
||||
digit = *p - '0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (digit < 0 || digit >= base) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
endp = p;
|
||||
|
||||
if (overflow) {
|
||||
if (endptr) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (n > cutoff || (n == cutoff && digit > cutlim)) {
|
||||
overflow = 1;
|
||||
continue;
|
||||
}
|
||||
n = n * base + digit;
|
||||
}
|
||||
|
||||
if (endptr) {
|
||||
*endptr = (char*)endp;
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
set_errno(ERANGE);
|
||||
return ((negative) ? LONG_MIN : LONG_MAX);
|
||||
}
|
||||
return (long)((negative) ? -n : n);
|
||||
}
|
||||
|
||||
#define SWAPARR(a, b, size) \
|
||||
do { \
|
||||
size_t __size = (size); \
|
||||
char *__a = (a), *__b = (b); \
|
||||
do { \
|
||||
char __tmp = *__a; \
|
||||
*__a++ = *__b; \
|
||||
*__b++ = __tmp; \
|
||||
} while (--__size > 0); \
|
||||
} while (0)
|
||||
|
||||
void __qsortimpl(void* vbase, size_t n, size_t size, int (*compar)(const void*, const void*), int l, int r)
|
||||
{
|
||||
char* base = (char*)vbase;
|
||||
|
||||
if (l >= r) {
|
||||
return;
|
||||
}
|
||||
|
||||
int lm = l - 1;
|
||||
for (int rm = l; rm < r; rm++) {
|
||||
if (compar(&base[rm * size], &base[r * size]) < 0) {
|
||||
lm++;
|
||||
SWAPARR(&base[lm * size], &base[rm * size], size);
|
||||
}
|
||||
}
|
||||
SWAPARR(&base[(lm + 1) * size], &base[r * size], size);
|
||||
|
||||
__qsortimpl(vbase, n, size, compar, l, lm);
|
||||
__qsortimpl(vbase, n, size, compar, lm + 2, r);
|
||||
}
|
||||
|
||||
void qsort(void* vbase, size_t n, size_t size, int (*compar)(const void*, const void*))
|
||||
{
|
||||
__qsortimpl(vbase, n, size, compar, 0, n - 1);
|
||||
}
|
||||
94
libs/libc/string/routines/arm32/memset.S
Normal file
94
libs/libc/string/routines/arm32/memset.S
Normal file
@@ -0,0 +1,94 @@
|
||||
// Target ARMv7
|
||||
|
||||
.global memset
|
||||
|
||||
// r0 - dest
|
||||
// r1 - ch
|
||||
// r2 - len
|
||||
memset:
|
||||
mov r3, r0
|
||||
|
||||
cmp r2, #0
|
||||
beq memset_exit
|
||||
|
||||
tst r3, #3 // Will set N
|
||||
beq memset_4bytes_aligned_entry
|
||||
|
||||
memset_byte:
|
||||
subs r2, r2, #1
|
||||
strb r1, [r3], #1
|
||||
|
||||
cmp r2, #0
|
||||
beq memset_exit
|
||||
|
||||
tst r3, #3
|
||||
bne memset_byte
|
||||
|
||||
memset_4bytes_aligned_entry:
|
||||
cmp r2, #4
|
||||
blt memset_byte_2
|
||||
|
||||
and r1, #0xFF
|
||||
orr r1, r1, r1, lsl#8
|
||||
orr r1, r1, r1, lsl#16
|
||||
|
||||
tst r3, #15
|
||||
beq memset_16bytes_aligned_entry
|
||||
|
||||
memset_4bytes_aligned_loop:
|
||||
subs r2, r2, #4
|
||||
str r1, [r3], #4
|
||||
|
||||
cmp r2, #0
|
||||
beq memset_exit
|
||||
|
||||
cmp r2, #4
|
||||
blt memset_byte_2
|
||||
|
||||
tst r3, #15 // Test if we can put 16bytes block.
|
||||
bne memset_4bytes_aligned_loop // If not repeat 4 byte block again.
|
||||
|
||||
memset_16bytes_aligned_entry:
|
||||
push {r5, r6, r7}
|
||||
cmp r2, #16
|
||||
blt memset_16bytes_aligned_exit
|
||||
|
||||
memset_16bytes_aligned_preloop:
|
||||
// Load ch into all bytes of 32bit r1 register
|
||||
mov r5, r1
|
||||
mov r6, r1
|
||||
mov r7, r1
|
||||
|
||||
memset_16bytes_aligned_loop:
|
||||
subs r2, r2, #16
|
||||
stmia r3!,{r1,r5,r6,r7}
|
||||
|
||||
cmp r2, #16
|
||||
bge memset_16bytes_aligned_loop
|
||||
|
||||
memset_16bytes_aligned_exit:
|
||||
pop {r5, r6, r7}
|
||||
cmp r2, #0
|
||||
beq memset_exit
|
||||
|
||||
memset_4bytes_aligned_entry_2:
|
||||
cmp r2, #4
|
||||
blt memset_byte_2
|
||||
|
||||
memset_4bytes_aligned_loop_2:
|
||||
subs r2, r2, #4
|
||||
str r1, [r3], #4
|
||||
|
||||
cmp r2, #0
|
||||
beq memset_exit
|
||||
|
||||
cmp r2, #4
|
||||
bge memset_4bytes_aligned_loop_2
|
||||
|
||||
memset_byte_2:
|
||||
subs r2, r2, #1
|
||||
strb r1, [r3], #1
|
||||
bne memset_byte_2
|
||||
|
||||
memset_exit:
|
||||
bx lr
|
||||
277
libs/libc/string/string.c
Normal file
277
libs/libc/string/string.c
Normal file
@@ -0,0 +1,277 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __arm__
|
||||
void* memset(void* dest, int fill, size_t nbytes)
|
||||
{
|
||||
for (int i = 0; i < nbytes; ++i)
|
||||
((uint8_t*)dest)[i] = fill;
|
||||
|
||||
return dest;
|
||||
}
|
||||
#endif //__arm__
|
||||
|
||||
void* memmove(void* dest, const void* src, size_t nbytes)
|
||||
{
|
||||
if (src > dest) {
|
||||
memcpy(dest, src, nbytes);
|
||||
return dest;
|
||||
}
|
||||
|
||||
for (int i = nbytes - 1; i >= 0; --i)
|
||||
((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* This optimized version of memcpy uses 32 bit chunks to copy over data on
|
||||
the 32 bit architecture this library is built for. If this function gets
|
||||
used on a 64 bit arch, be sure to use 8 byte chunks so each chunk fits
|
||||
in a single register. The important part is this should be compiled with
|
||||
atleast -O1 or -Os, because -O0 just makes this function too big for what
|
||||
it does.
|
||||
|
||||
GCC does a better job at optimizing this if the pointers are restricted,
|
||||
making the copying part have less instructions. Clang on the other hand
|
||||
does not really change anything if the pointers are restricted or not. */
|
||||
void* memcpy(void* __restrict dest, const void* __restrict src, size_t nbytes)
|
||||
{
|
||||
size_t chunks, rest, i;
|
||||
|
||||
rest = nbytes % 4;
|
||||
chunks = (nbytes - rest) >> 2;
|
||||
|
||||
if (!chunks)
|
||||
goto skip_chunks;
|
||||
|
||||
for (i = 0; i < chunks; i++)
|
||||
((uint32_t*)dest)[i] = ((uint32_t*)src)[i];
|
||||
|
||||
skip_chunks:
|
||||
|
||||
/* Multiplying chunks by 4 will give us the offset of the 'rest' bytes,
|
||||
which were not copied over along with the 4 byte chunks. */
|
||||
chunks <<= 2;
|
||||
|
||||
for (i = 0; i < rest; i++)
|
||||
((uint8_t*)dest)[chunks + i] = ((uint8_t*)src)[chunks + i];
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void* memccpy(void* dest, const void* src, int stop, size_t nbytes)
|
||||
{
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
*((uint8_t*)dest + i) = *((uint8_t*)src + i);
|
||||
|
||||
if (*((uint8_t*)src + i) == stop)
|
||||
return ((uint8_t*)dest + i + 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int memcmp(const void* src1, const void* src2, size_t nbytes)
|
||||
{
|
||||
const uint8_t* first = src1;
|
||||
const uint8_t* second = src2;
|
||||
|
||||
for (int i = 0; i < nbytes; i++) {
|
||||
/* Return the difference if the byte does not match. */
|
||||
if (first[i] != second[i])
|
||||
return (int)first[i] - (int)second[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* memchr(const void* ptr, int c, size_t size)
|
||||
{
|
||||
char ch = c;
|
||||
const char* cptr = (const char*)ptr;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (cptr[i] == ch) {
|
||||
return (char*)(cptr + i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int strcmp(const char* a, const char* b)
|
||||
{
|
||||
while (*a == *b && *a != '\0' && *b != '\0') {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
}
|
||||
if (*a > *b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strncmp(const char* a, const char* b, size_t num)
|
||||
{
|
||||
while (*a == *b && *a != 0 && *b != 0 && num) {
|
||||
a++;
|
||||
b++;
|
||||
num--;
|
||||
}
|
||||
|
||||
if (!num) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*a < *b) {
|
||||
return -1;
|
||||
}
|
||||
if (*a > *b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t strlen(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i])
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
char* strcpy(char* dest, const char* src)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; src[i] != 0; i++)
|
||||
dest[i] = src[i];
|
||||
|
||||
dest[i] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strncpy(char* dest, const char* src, size_t nbytes)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nbytes && src[i] != 0; i++)
|
||||
dest[i] = src[i];
|
||||
|
||||
/* Fill the rest with null bytes */
|
||||
for (; i < nbytes; i++)
|
||||
dest[i] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strchr(const char* s, int c)
|
||||
{
|
||||
for (;; s++) {
|
||||
if (*s == c) {
|
||||
return (char*)s;
|
||||
}
|
||||
if (!(*s)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* strtok_r(char* str, const char* delim, char** saveptr)
|
||||
{
|
||||
if (!str) {
|
||||
if (!saveptr) {
|
||||
return NULL;
|
||||
}
|
||||
str = *saveptr;
|
||||
}
|
||||
|
||||
size_t start = 0;
|
||||
size_t end = 0;
|
||||
size_t n = strlen(str);
|
||||
size_t m = strlen(delim);
|
||||
bool ok = false;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
ok = false;
|
||||
for (size_t j = 0; j < m; j++) {
|
||||
if (str[i] == delim[j]) {
|
||||
if (end - start == 0) {
|
||||
start++;
|
||||
break;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
break;
|
||||
}
|
||||
end++;
|
||||
}
|
||||
|
||||
if (str[start] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (end == 0) {
|
||||
*saveptr = NULL;
|
||||
return &str[start];
|
||||
}
|
||||
|
||||
if (str[end] == '\0') {
|
||||
*saveptr = &str[end];
|
||||
} else {
|
||||
*saveptr = &str[end + 1];
|
||||
}
|
||||
|
||||
str[end] = '\0';
|
||||
return &str[start];
|
||||
}
|
||||
|
||||
char* strtok(char* str, const char* delim)
|
||||
{
|
||||
static char* saveptr;
|
||||
return strtok_r(str, delim, &saveptr);
|
||||
}
|
||||
|
||||
char* strstr(const char* haystack, const char* needle)
|
||||
{
|
||||
size_t n = strlen(needle);
|
||||
|
||||
while (*haystack) {
|
||||
if (!memcmp(haystack, needle, n)) {
|
||||
return (char*)haystack;
|
||||
}
|
||||
haystack++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* strcat(char* dest, const char* src)
|
||||
{
|
||||
size_t dest_len = strlen(dest);
|
||||
size_t i = 0;
|
||||
|
||||
while (src[i] != '\0') {
|
||||
dest[dest_len + i] = src[i];
|
||||
i++;
|
||||
}
|
||||
dest[dest_len + i] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strrchr(const char* str, int ch)
|
||||
{
|
||||
char c;
|
||||
char* last = NULL;
|
||||
|
||||
while ((c = *str)) {
|
||||
if (c == ch) {
|
||||
last = (char*)(str);
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
21
libs/libc/sysdeps/unix/arm32/crt0.S
Normal file
21
libs/libc/sysdeps/unix/arm32/crt0.S
Normal file
@@ -0,0 +1,21 @@
|
||||
.section .text
|
||||
|
||||
.extern main
|
||||
.extern exit
|
||||
.extern _init
|
||||
.extern _deinit
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
push {r0-r2}
|
||||
sub sp, sp, #4 // align to 16bytes
|
||||
bl _init
|
||||
add sp, sp, #4
|
||||
pop {r0-r2}
|
||||
bl main
|
||||
push {r0}
|
||||
sub sp, sp, #12 // align to 16bytes
|
||||
bl _deinit
|
||||
add sp, sp, #12
|
||||
pop {r0}
|
||||
bl exit
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user