Squash commits for public release

This commit is contained in:
2025-02-12 09:54:05 -05:00
commit 7118adc514
1108 changed files with 80873 additions and 0 deletions

6
libs/libapi/BUILD.gn Normal file
View File

@@ -0,0 +1,6 @@
import("//build/libs/TEMPLATE.gni")
xOS_static_library("libapi") {
sources = []
configs = [ "//build/libs:lib_flags" ]
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -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
View 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" ]
}
}

View 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
View 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
View 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);
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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
View 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 */

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

View 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

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

View 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

View 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

View 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

View 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

View 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

View 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

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

View 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

View 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

View File

@@ -0,0 +1,4 @@
#ifndef _LIBC_SYS__STRUCTS_H
#define _LIBC_SYS__STRUCTS_H
#endif

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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 */

View 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

View 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

View 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

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

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

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

View File

@@ -0,0 +1,5 @@
int errno;
void _init()
{
}

View 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, &params);
RETURN_WITH_ERRNO(res, 0, res);
}

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

View 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

View 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

View 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

View 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

View 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
View 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);
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

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

View 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