This commit is contained in:
2026-04-18 13:21:06 +08:00
parent e83b51f220
commit 2f0ee08485
21 changed files with 1522 additions and 291 deletions

View File

@@ -1,4 +1,6 @@
#include "cmd_runtime.h"
#include <stdio.h>
static int ush_cmd_cat(const ush_state *sh, const char *arg) {
char path[USH_PATH_MAX];
char buf[USH_CAT_MAX + 1ULL];
@@ -8,28 +10,28 @@ static int ush_cmd_cat(const ush_state *sh, const char *arg) {
if (arg == (const char *)0 || arg[0] == '\0') {
if (ush_pipeline_stdin_text != (const char *)0 && ush_pipeline_stdin_len > 0ULL) {
ush_write(ush_pipeline_stdin_text);
(void)fputs(ush_pipeline_stdin_text, 1);
return 1;
}
ush_writeln("cat: file path required");
(void)puts("cat: file path required");
return 0;
}
if (ush_resolve_path(sh, arg, path, (u64)sizeof(path)) == 0) {
ush_writeln("cat: invalid path");
(void)puts("cat: invalid path");
return 0;
}
if (cleonos_sys_fs_stat_type(path) != 1ULL) {
ush_writeln("cat: file not found");
(void)puts("cat: file not found");
return 0;
}
size = cleonos_sys_fs_stat_size(path);
if (size == (u64)-1) {
ush_writeln("cat: failed to stat file");
(void)puts("cat: failed to stat file");
return 0;
}
@@ -41,7 +43,7 @@ static int ush_cmd_cat(const ush_state *sh, const char *arg) {
got = cleonos_sys_fs_read(path, buf, req);
if (got == 0ULL) {
ush_writeln("cat: read failed");
(void)puts("cat: read failed");
return 0;
}
@@ -50,10 +52,10 @@ static int ush_cmd_cat(const ush_state *sh, const char *arg) {
}
buf[got] = '\0';
ush_writeln(buf);
(void)puts(buf);
if (size > got) {
ush_writeln("[cat] output truncated");
(void)puts("[cat] output truncated");
}
return 1;

View File

@@ -4,16 +4,10 @@ const char *ush_pipeline_stdin_text = (const char *)0;
u64 ush_pipeline_stdin_len = 0ULL;
void ush_zero(void *ptr, u64 size) {
u64 i;
char *bytes = (char *)ptr;
if (bytes == (char *)0) {
if (ptr == (void *)0 || size == 0ULL) {
return;
}
for (i = 0ULL; i < size; i++) {
bytes[i] = 0;
}
(void)memset(ptr, 0, (size_t)size);
}
void ush_init_state(ush_state *sh) {
@@ -27,84 +21,47 @@ void ush_init_state(ush_state *sh) {
}
u64 ush_strlen(const char *str) {
u64 len = 0ULL;
if (str == (const char *)0) {
return 0ULL;
}
while (str[len] != '\0') {
len++;
}
return len;
return (str == (const char *)0) ? 0ULL : (u64)strlen(str);
}
int ush_streq(const char *left, const char *right) {
u64 i = 0ULL;
if (left == (const char *)0 || right == (const char *)0) {
return 0;
}
while (left[i] != '\0' && right[i] != '\0') {
if (left[i] != right[i]) {
return 0;
}
i++;
}
return (left[i] == right[i]) ? 1 : 0;
return (strcmp(left, right) == 0) ? 1 : 0;
}
int ush_is_space(char ch) {
return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ? 1 : 0;
return (isspace((unsigned char)ch) != 0) ? 1 : 0;
}
int ush_is_printable(char ch) {
return (ch >= 32 && ch <= 126) ? 1 : 0;
return (isprint((unsigned char)ch) != 0) ? 1 : 0;
}
int ush_has_suffix(const char *name, const char *suffix) {
u64 name_len;
u64 suffix_len;
u64 i;
size_t name_len;
size_t suffix_len;
if (name == (const char *)0 || suffix == (const char *)0) {
return 0;
}
name_len = ush_strlen(name);
suffix_len = ush_strlen(suffix);
name_len = strlen(name);
suffix_len = strlen(suffix);
if (suffix_len > name_len) {
return 0;
}
for (i = 0ULL; i < suffix_len; i++) {
if (name[name_len - suffix_len + i] != suffix[i]) {
return 0;
}
}
return 1;
return (strncmp(name + (name_len - suffix_len), suffix, suffix_len) == 0) ? 1 : 0;
}
int ush_contains_char(const char *text, char needle) {
u64 i = 0ULL;
if (text == (const char *)0) {
return 0;
}
while (text[i] != '\0') {
if (text[i] == needle) {
return 1;
}
i++;
}
return 0;
return (strchr(text, (int)needle) != (char *)0) ? 1 : 0;
}
int ush_parse_u64_dec(const char *text, u64 *out_value) {
@@ -118,7 +75,7 @@ int ush_parse_u64_dec(const char *text, u64 *out_value) {
while (text[i] != '\0') {
u64 digit;
if (text[i] < '0' || text[i] > '9') {
if (isdigit((unsigned char)text[i]) == 0) {
return 0;
}
@@ -137,45 +94,34 @@ int ush_parse_u64_dec(const char *text, u64 *out_value) {
}
void ush_copy(char *dst, u64 dst_size, const char *src) {
u64 i = 0ULL;
if (dst == (char *)0 || src == (const char *)0 || dst_size == 0ULL) {
return;
}
while (src[i] != '\0' && i + 1ULL < dst_size) {
dst[i] = src[i];
i++;
}
dst[i] = '\0';
(void)strncpy(dst, src, (size_t)(dst_size - 1ULL));
dst[dst_size - 1ULL] = '\0';
}
void ush_trim_line(char *line) {
u64 start = 0ULL;
u64 i = 0ULL;
u64 len;
size_t start = 0U;
size_t len;
if (line == (char *)0) {
return;
}
while (line[start] != '\0' && ush_is_space(line[start]) != 0) {
while (line[start] != '\0' && isspace((unsigned char)line[start]) != 0) {
start++;
}
if (start > 0ULL) {
while (line[start + i] != '\0') {
line[i] = line[start + i];
i++;
}
line[i] = '\0';
if (start > 0U) {
size_t remain = strlen(line + start) + 1U;
(void)memmove(line, line + start, remain);
}
len = ush_strlen(line);
len = strlen(line);
while (len > 0ULL && ush_is_space(line[len - 1ULL]) != 0) {
line[len - 1ULL] = '\0';
while (len > 0U && isspace((unsigned char)line[len - 1U]) != 0) {
line[len - 1U] = '\0';
len--;
}
}
@@ -220,37 +166,14 @@ void ush_parse_line(const char *line, char *out_cmd, u64 cmd_size, char *out_arg
}
void ush_write(const char *text) {
u64 len;
const char *cursor;
u64 left;
if (text == (const char *)0) {
return;
}
len = ush_strlen(text);
if (len == 0ULL) {
return;
}
cursor = text;
left = len;
while (left > 0ULL) {
u64 wrote = cleonos_sys_fd_write(1ULL, cursor, left);
if (wrote == 0ULL || wrote == (u64)-1) {
break;
}
cursor += wrote;
left -= wrote;
}
(void)fputs(text, 1);
}
void ush_write_char(char ch) {
(void)cleonos_sys_fd_write(1ULL, &ch, 1ULL);
(void)fputc((int)(unsigned char)ch, 1);
}
void ush_writeln(const char *text) {
@@ -470,11 +393,9 @@ int ush_path_is_under_system(const char *path) {
if (path == (const char *)0) {
return 0;
}
if (path[0] != '/' || path[1] != 's' || path[2] != 'y' || path[3] != 's' || path[4] != 't' || path[5] != 'e' || path[6] != 'm') {
if (strncmp(path, "/system", 7U) != 0) {
return 0;
}
return (path[7] == '\0' || path[7] == '/') ? 1 : 0;
}
@@ -482,11 +403,9 @@ int ush_path_is_under_temp(const char *path) {
if (path == (const char *)0) {
return 0;
}
if (path[0] != '/' || path[1] != 't' || path[2] != 'e' || path[3] != 'm' || path[4] != 'p') {
if (strncmp(path, "/temp", 5U) != 0) {
return 0;
}
return (path[5] == '\0' || path[5] == '/') ? 1 : 0;
}

View File

@@ -2,6 +2,10 @@
#define CLEONOS_CMD_RUNTIME_H
#include <cleonos_syscall.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef long long i64;

View File

@@ -1,10 +1,12 @@
#include "cmd_runtime.h"
#include <stdio.h>
static void ush_grep_write_u64_dec(u64 value) {
char tmp[32];
u64 len = 0ULL;
if (value == 0ULL) {
ush_write_char('0');
(void)putchar('0');
return;
}
@@ -15,7 +17,7 @@ static void ush_grep_write_u64_dec(u64 value) {
while (len > 0ULL) {
len--;
ush_write_char(tmp[len]);
(void)putchar((unsigned char)tmp[len]);
}
}
@@ -73,14 +75,14 @@ static u64 ush_grep_emit_matches(const char *input, u64 input_len, const char *p
if (with_line_number != 0) {
ush_grep_write_u64_dec(line_no);
ush_write(":");
(void)fputs(":", 1);
}
for (j = 0ULL; j < line_len; j++) {
ush_write_char(input[start + j]);
(void)putchar((unsigned char)input[start + j]);
}
ush_write_char('\n');
(void)putchar('\n');
}
start = i + 1ULL;
@@ -108,12 +110,12 @@ static int ush_cmd_grep(const ush_state *sh, const char *arg) {
static char file_buf[USH_COPY_MAX + 1U];
if (sh == (const ush_state *)0 || arg == (const char *)0 || arg[0] == '\0') {
ush_writeln("grep: usage grep [-n] <pattern> [file]");
(void)puts("grep: usage grep [-n] <pattern> [file]");
return 0;
}
if (ush_split_first_and_rest(arg, first, (u64)sizeof(first), &rest) == 0) {
ush_writeln("grep: usage grep [-n] <pattern> [file]");
(void)puts("grep: usage grep [-n] <pattern> [file]");
return 0;
}
@@ -121,7 +123,7 @@ static int ush_cmd_grep(const ush_state *sh, const char *arg) {
with_line_number = 1;
if (ush_split_first_and_rest(rest, second, (u64)sizeof(second), &rest2) == 0) {
ush_writeln("grep: usage grep [-n] <pattern> [file]");
(void)puts("grep: usage grep [-n] <pattern> [file]");
return 0;
}
@@ -133,43 +135,43 @@ static int ush_cmd_grep(const ush_state *sh, const char *arg) {
if (rest != (const char *)0 && rest[0] != '\0') {
if (ush_split_first_and_rest(rest, third, (u64)sizeof(third), &rest2) == 0) {
ush_writeln("grep: usage grep [-n] <pattern> [file]");
(void)puts("grep: usage grep [-n] <pattern> [file]");
return 0;
}
file_arg = third;
if (rest2 != (const char *)0 && rest2[0] != '\0') {
ush_writeln("grep: usage grep [-n] <pattern> [file]");
(void)puts("grep: usage grep [-n] <pattern> [file]");
return 0;
}
}
if (pattern == (const char *)0 || pattern[0] == '\0') {
ush_writeln("grep: pattern required");
(void)puts("grep: pattern required");
return 0;
}
if (file_arg != (const char *)0) {
if (ush_resolve_path(sh, file_arg, path, (u64)sizeof(path)) == 0) {
ush_writeln("grep: invalid path");
(void)puts("grep: invalid path");
return 0;
}
if (cleonos_sys_fs_stat_type(path) != 1ULL) {
ush_writeln("grep: file not found");
(void)puts("grep: file not found");
return 0;
}
size = cleonos_sys_fs_stat_size(path);
if (size == (u64)-1) {
ush_writeln("grep: failed to stat file");
(void)puts("grep: failed to stat file");
return 0;
}
if (size > (u64)USH_COPY_MAX) {
ush_writeln("grep: file too large for user buffer");
(void)puts("grep: file too large for user buffer");
return 0;
}
@@ -180,7 +182,7 @@ static int ush_cmd_grep(const ush_state *sh, const char *arg) {
got = cleonos_sys_fs_read(path, file_buf, size);
if (got == 0ULL || got != size) {
ush_writeln("grep: read failed");
(void)puts("grep: read failed");
return 0;
}
@@ -189,7 +191,7 @@ static int ush_cmd_grep(const ush_state *sh, const char *arg) {
input_len = got;
} else {
if (ush_pipeline_stdin_text == (const char *)0) {
ush_writeln("grep: file path required (or pipeline input)");
(void)puts("grep: file path required (or pipeline input)");
return 0;
}

View File

@@ -1,4 +1,5 @@
#include "cmd_runtime.h"
#include <stdio.h>
static int ush_head_parse_args(const char *arg, u64 *out_line_count, char *out_file, u64 out_file_size) {
char first[USH_PATH_MAX];
@@ -69,24 +70,24 @@ static int ush_head_load_input(const ush_state *sh, const char *file_arg, const
if (file_arg != (const char *)0 && file_arg[0] != '\0') {
if (ush_resolve_path(sh, file_arg, path, (u64)sizeof(path)) == 0) {
ush_writeln("head: invalid path");
(void)puts("head: invalid path");
return 0;
}
if (cleonos_sys_fs_stat_type(path) != 1ULL) {
ush_writeln("head: file not found");
(void)puts("head: file not found");
return 0;
}
size = cleonos_sys_fs_stat_size(path);
if (size == (u64)-1) {
ush_writeln("head: failed to stat file");
(void)puts("head: failed to stat file");
return 0;
}
if (size > (u64)USH_COPY_MAX) {
ush_writeln("head: file too large for user buffer");
(void)puts("head: file too large for user buffer");
return 0;
}
@@ -100,7 +101,7 @@ static int ush_head_load_input(const ush_state *sh, const char *file_arg, const
got = cleonos_sys_fs_read(path, file_buf, size);
if (got == 0ULL || got != size) {
ush_writeln("head: read failed");
(void)puts("head: read failed");
return 0;
}
@@ -111,7 +112,7 @@ static int ush_head_load_input(const ush_state *sh, const char *file_arg, const
}
if (ush_pipeline_stdin_text == (const char *)0) {
ush_writeln("head: file path required (or pipeline input)");
(void)puts("head: file path required (or pipeline input)");
return 0;
}
@@ -133,7 +134,7 @@ static void ush_head_emit(const char *input, u64 input_len, u64 line_count) {
break;
}
ush_write_char(input[i]);
(void)putchar((unsigned char)input[i]);
if (input[i] == '\n') {
emitted++;
@@ -152,7 +153,7 @@ static int ush_cmd_head(const ush_state *sh, const char *arg) {
}
if (ush_head_parse_args(arg, &line_count, file_arg, (u64)sizeof(file_arg)) == 0) {
ush_writeln("head: usage head [-n N] [file]");
(void)puts("head: usage head [-n N] [file]");
return 0;
}

View File

@@ -1,7 +1,6 @@
#include <cleonos_syscall.h>
#include <stdio.h>
int cleonos_app_main(void) {
static const char msg[] = "[USER][HELLO] Hello world from /hello.elf\n";
(void)cleonos_sys_fd_write(1ULL, msg, (u64)(sizeof(msg) - 1U));
(void)printf("[USER][HELLO] Hello world from %s\n", "/hello.elf");
return 0;
}

View File

@@ -1,4 +1,23 @@
#include "cmd_runtime.h"
#include <stdio.h>
static void clio_write(const char *text) {
(void)fputs(text, 1);
}
static void clio_writeln(const char *text) {
(void)fputs(text, 1);
(void)putchar('\n');
}
static void clio_write_char(char ch) {
(void)putchar((unsigned char)ch);
}
static void clio_write_hex_u64(u64 value) {
(void)printf("0X%llX", (unsigned long long)value);
}
static int ush_ls_join_path(const char *dir_path, const char *name, char *out_path, u64 out_size) {
u64 p = 0ULL;
u64 i;
@@ -80,30 +99,30 @@ static int ush_ls_is_dot_entry(const char *name) {
static void ush_ls_print_one(const char *name, u64 type, u64 size, int long_mode) {
if (long_mode == 0) {
ush_writeln(name);
clio_writeln(name);
return;
}
if (type == 2ULL) {
ush_write("d ");
clio_write("d ");
} else if (type == 1ULL) {
ush_write("f ");
clio_write("f ");
} else {
ush_write("? ");
clio_write("? ");
}
ush_write(name);
clio_write(name);
if (type == 1ULL) {
ush_write(" size=");
ush_write_hex_u64(size);
clio_write(" size=");
clio_write_hex_u64(size);
} else if (type == 2ULL) {
ush_write(" <DIR>");
clio_write(" <DIR>");
} else {
ush_write(" <UNKNOWN>");
clio_write(" <UNKNOWN>");
}
ush_write_char('\n');
clio_write_char('\n');
}
static int ush_ls_parse_args(const char *arg,
@@ -186,19 +205,19 @@ static int ush_ls_dir(const char *path,
u64 i;
if (depth > 16ULL) {
ush_writeln("ls: recursion depth limit reached");
clio_writeln("ls: recursion depth limit reached");
return 0;
}
count = cleonos_sys_fs_child_count(path);
if (print_header != 0) {
ush_write(path);
ush_writeln(":");
clio_write(path);
clio_writeln(":");
}
if (count == 0ULL) {
ush_writeln("(empty)");
clio_writeln("(empty)");
}
for (i = 0ULL; i < count; i++) {
@@ -249,7 +268,7 @@ static int ush_ls_dir(const char *path,
}
if (cleonos_sys_fs_stat_type(child_path) == 2ULL) {
ush_write_char('\n');
clio_write_char('\n');
(void)ush_ls_dir(child_path, long_mode, recursive, 1, depth + 1ULL);
}
}
@@ -265,12 +284,12 @@ static int ush_cmd_ls(const ush_state *sh, const char *arg) {
int recursive;
if (ush_ls_parse_args(arg, &long_mode, &recursive, target, (u64)sizeof(target)) == 0) {
ush_writeln("ls: usage ls [-l] [-R] [path]");
clio_writeln("ls: usage ls [-l] [-R] [path]");
return 0;
}
if (ush_resolve_path(sh, target, path, (u64)sizeof(path)) == 0) {
ush_writeln("ls: invalid path");
clio_writeln("ls: invalid path");
return 0;
}
@@ -283,7 +302,7 @@ static int ush_cmd_ls(const ush_state *sh, const char *arg) {
}
if (type != 2ULL) {
ush_writeln("ls: path not found");
clio_writeln("ls: path not found");
return 0;
}

View File

@@ -2,6 +2,10 @@
#define CLEONOS_USER_SHELL_INTERNAL_H
#include <cleonos_syscall.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef long long i64;

View File

@@ -5,106 +5,53 @@ void ush_init_state(ush_state *sh) {
return;
}
sh->line[0] = '\0';
sh->line_len = 0ULL;
sh->cursor = 0ULL;
sh->rendered_len = 0ULL;
(void)memset(sh, 0, sizeof(*sh));
ush_copy(sh->cwd, (u64)sizeof(sh->cwd), "/");
sh->history_count = 0ULL;
sh->history_nav = -1;
sh->nav_saved_line[0] = '\0';
sh->nav_saved_len = 0ULL;
sh->nav_saved_cursor = 0ULL;
sh->cmd_total = 0ULL;
sh->cmd_ok = 0ULL;
sh->cmd_fail = 0ULL;
sh->cmd_unknown = 0ULL;
sh->exit_requested = 0;
sh->exit_code = 0ULL;
}
u64 ush_strlen(const char *str) {
u64 len = 0ULL;
if (str == (const char *)0) {
return 0ULL;
}
while (str[len] != '\0') {
len++;
}
return len;
return (str == (const char *)0) ? 0ULL : (u64)strlen(str);
}
int ush_streq(const char *left, const char *right) {
u64 i = 0ULL;
if (left == (const char *)0 || right == (const char *)0) {
return 0;
}
while (left[i] != '\0' && right[i] != '\0') {
if (left[i] != right[i]) {
return 0;
}
i++;
}
return (left[i] == right[i]) ? 1 : 0;
return (strcmp(left, right) == 0) ? 1 : 0;
}
int ush_is_space(char ch) {
return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ? 1 : 0;
return (isspace((unsigned char)ch) != 0) ? 1 : 0;
}
int ush_is_printable(char ch) {
return (ch >= 32 && ch <= 126) ? 1 : 0;
return (isprint((unsigned char)ch) != 0) ? 1 : 0;
}
int ush_has_suffix(const char *name, const char *suffix) {
u64 name_len;
u64 suffix_len;
u64 i;
size_t name_len;
size_t suffix_len;
if (name == (const char *)0 || suffix == (const char *)0) {
return 0;
}
name_len = ush_strlen(name);
suffix_len = ush_strlen(suffix);
name_len = strlen(name);
suffix_len = strlen(suffix);
if (suffix_len > name_len) {
return 0;
}
for (i = 0ULL; i < suffix_len; i++) {
if (name[name_len - suffix_len + i] != suffix[i]) {
return 0;
}
}
return 1;
return (strncmp(name + (name_len - suffix_len), suffix, suffix_len) == 0) ? 1 : 0;
}
int ush_contains_char(const char *text, char needle) {
u64 i = 0ULL;
if (text == (const char *)0) {
return 0;
}
while (text[i] != '\0') {
if (text[i] == needle) {
return 1;
}
i++;
}
return 0;
return (strchr(text, (int)needle) != (char *)0) ? 1 : 0;
}
int ush_parse_u64_dec(const char *text, u64 *out_value) {
@@ -118,7 +65,7 @@ int ush_parse_u64_dec(const char *text, u64 *out_value) {
while (text[i] != '\0') {
u64 digit;
if (text[i] < '0' || text[i] > '9') {
if (isdigit((unsigned char)text[i]) == 0) {
return 0;
}
@@ -137,45 +84,34 @@ int ush_parse_u64_dec(const char *text, u64 *out_value) {
}
void ush_copy(char *dst, u64 dst_size, const char *src) {
u64 i = 0ULL;
if (dst == (char *)0 || src == (const char *)0 || dst_size == 0ULL) {
return;
}
while (src[i] != '\0' && i + 1ULL < dst_size) {
dst[i] = src[i];
i++;
}
dst[i] = '\0';
(void)strncpy(dst, src, (size_t)(dst_size - 1ULL));
dst[dst_size - 1ULL] = '\0';
}
void ush_trim_line(char *line) {
u64 start = 0ULL;
u64 i = 0ULL;
u64 len;
size_t start = 0U;
size_t len;
if (line == (char *)0) {
return;
}
while (line[start] != '\0' && ush_is_space(line[start]) != 0) {
while (line[start] != '\0' && isspace((unsigned char)line[start]) != 0) {
start++;
}
if (start > 0ULL) {
while (line[start + i] != '\0') {
line[i] = line[start + i];
i++;
}
line[i] = '\0';
if (start > 0U) {
size_t remain = strlen(line + start) + 1U;
(void)memmove(line, line + start, remain);
}
len = ush_strlen(line);
len = strlen(line);
while (len > 0ULL && ush_is_space(line[len - 1ULL]) != 0) {
line[len - 1ULL] = '\0';
while (len > 0U && isspace((unsigned char)line[len - 1U]) != 0) {
line[len - 1U] = '\0';
len--;
}
}
@@ -231,7 +167,6 @@ static int ush_out_fd_mirror_tty = 1;
static void ush_output_capture_append(const char *text, u64 len) {
u64 writable;
u64 i;
if (ush_out_capture_active == 0 || text == (const char *)0 || len == 0ULL) {
return;
@@ -254,9 +189,7 @@ static void ush_output_capture_append(const char *text, u64 len) {
ush_out_capture_truncated = 1;
}
for (i = 0ULL; i < len; i++) {
ush_out_capture_buffer[ush_out_capture_length + i] = text[i];
}
(void)memcpy(ush_out_capture_buffer + ush_out_capture_length, text, (size_t)len);
ush_out_capture_length += len;
ush_out_capture_buffer[ush_out_capture_length] = '\0';
@@ -341,19 +274,7 @@ void ush_write(const char *text) {
}
if (should_write_tty != 0) {
const char *cursor = text;
u64 left = len;
while (left > 0ULL) {
u64 wrote = cleonos_sys_fd_write(1ULL, cursor, left);
if (wrote == 0ULL || wrote == (u64)-1) {
break;
}
cursor += wrote;
left -= wrote;
}
(void)fputs(text, 1);
}
}
@@ -377,7 +298,7 @@ void ush_write_char(char ch) {
}
if (should_write_tty != 0) {
(void)cleonos_sys_fd_write(1ULL, &ch, 1ULL);
(void)fputc((int)(unsigned char)ch, 1);
}
}

View File

@@ -1,11 +1,11 @@
#include <cleonos_syscall.h>
#include <stdio.h>
int cleonos_app_main(void) {
static const char banner[] =
"spin: busy loop started (test Alt+Ctrl+C force stop)\n";
volatile u64 noise = 0xC1E0C1E0ULL;
volatile unsigned long long noise = 0xC1E0C1E0ULL;
(void)cleonos_sys_fd_write(1ULL, banner, (u64)(sizeof(banner) - 1U));
(void)fputs(banner, 1);
for (;;) {
noise ^= (noise << 7);

View File

@@ -1,4 +1,5 @@
#include "cmd_runtime.h"
#include <stdio.h>
static int ush_tail_parse_args(const char *arg, u64 *out_line_count, char *out_file, u64 out_file_size) {
char first[USH_PATH_MAX];
@@ -69,24 +70,24 @@ static int ush_tail_load_input(const ush_state *sh, const char *file_arg, const
if (file_arg != (const char *)0 && file_arg[0] != '\0') {
if (ush_resolve_path(sh, file_arg, path, (u64)sizeof(path)) == 0) {
ush_writeln("tail: invalid path");
(void)puts("tail: invalid path");
return 0;
}
if (cleonos_sys_fs_stat_type(path) != 1ULL) {
ush_writeln("tail: file not found");
(void)puts("tail: file not found");
return 0;
}
size = cleonos_sys_fs_stat_size(path);
if (size == (u64)-1) {
ush_writeln("tail: failed to stat file");
(void)puts("tail: failed to stat file");
return 0;
}
if (size > (u64)USH_COPY_MAX) {
ush_writeln("tail: file too large for user buffer");
(void)puts("tail: file too large for user buffer");
return 0;
}
@@ -100,7 +101,7 @@ static int ush_tail_load_input(const ush_state *sh, const char *file_arg, const
got = cleonos_sys_fs_read(path, file_buf, size);
if (got == 0ULL || got != size) {
ush_writeln("tail: read failed");
(void)puts("tail: read failed");
return 0;
}
@@ -111,7 +112,7 @@ static int ush_tail_load_input(const ush_state *sh, const char *file_arg, const
}
if (ush_pipeline_stdin_text == (const char *)0) {
ush_writeln("tail: file path required (or pipeline input)");
(void)puts("tail: file path required (or pipeline input)");
return 0;
}
@@ -174,7 +175,7 @@ static int ush_cmd_tail(const ush_state *sh, const char *arg) {
}
if (ush_tail_parse_args(arg, &line_count, file_arg, (u64)sizeof(file_arg)) == 0) {
ush_writeln("tail: usage tail [-n N] [file]");
(void)puts("tail: usage tail [-n N] [file]");
return 0;
}
@@ -191,7 +192,7 @@ static int ush_cmd_tail(const ush_state *sh, const char *arg) {
start_offset = ush_tail_find_start_offset(input, input_len, skip_lines);
for (i = start_offset; i < input_len; i++) {
ush_write_char(input[i]);
(void)putchar((unsigned char)input[i]);
}
return 1;

View File

@@ -1,11 +1,12 @@
#include "cmd_runtime.h"
#include <stdio.h>
static void ush_wc_write_u64_dec(u64 value) {
char tmp[32];
u64 len = 0ULL;
if (value == 0ULL) {
ush_write_char('0');
(void)putchar('0');
return;
}
@@ -16,7 +17,7 @@ static void ush_wc_write_u64_dec(u64 value) {
while (len > 0ULL) {
len--;
ush_write_char(tmp[len]);
(void)putchar((unsigned char)tmp[len]);
}
}
@@ -61,24 +62,24 @@ static int ush_wc_load_input(const ush_state *sh, const char *file_arg, const ch
if (file_arg != (const char *)0 && file_arg[0] != '\0') {
if (ush_resolve_path(sh, file_arg, path, (u64)sizeof(path)) == 0) {
ush_writeln("wc: invalid path");
(void)puts("wc: invalid path");
return 0;
}
if (cleonos_sys_fs_stat_type(path) != 1ULL) {
ush_writeln("wc: file not found");
(void)puts("wc: file not found");
return 0;
}
size = cleonos_sys_fs_stat_size(path);
if (size == (u64)-1) {
ush_writeln("wc: failed to stat file");
(void)puts("wc: failed to stat file");
return 0;
}
if (size > (u64)USH_COPY_MAX) {
ush_writeln("wc: file too large for user buffer");
(void)puts("wc: file too large for user buffer");
return 0;
}
@@ -92,7 +93,7 @@ static int ush_wc_load_input(const ush_state *sh, const char *file_arg, const ch
got = cleonos_sys_fs_read(path, file_buf, size);
if (got == 0ULL || got != size) {
ush_writeln("wc: read failed");
(void)puts("wc: read failed");
return 0;
}
@@ -103,7 +104,7 @@ static int ush_wc_load_input(const ush_state *sh, const char *file_arg, const ch
}
if (ush_pipeline_stdin_text == (const char *)0) {
ush_writeln("wc: file path required (or pipeline input)");
(void)puts("wc: file path required (or pipeline input)");
return 0;
}
@@ -127,7 +128,7 @@ static int ush_cmd_wc(const ush_state *sh, const char *arg) {
}
if (ush_wc_parse_args(arg, file_arg, (u64)sizeof(file_arg)) == 0) {
ush_writeln("wc: usage wc [file]");
(void)puts("wc: usage wc [file]");
return 0;
}
@@ -153,11 +154,11 @@ static int ush_cmd_wc(const ush_state *sh, const char *arg) {
}
ush_wc_write_u64_dec(lines);
ush_write(" ");
(void)putchar(' ');
ush_wc_write_u64_dec(words);
ush_write(" ");
(void)putchar(' ');
ush_wc_write_u64_dec(bytes);
ush_write_char('\n');
(void)putchar('\n');
return 1;
}

View File

@@ -0,0 +1,6 @@
#ifndef CLEONOS_STDIO_H
#define CLEONOS_STDIO_H
#include <stdio.h>
#endif

16
cleonos/c/include/ctype.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef CLEONOS_LIBC_CTYPE_H
#define CLEONOS_LIBC_CTYPE_H
int isspace(int ch);
int isdigit(int ch);
int isalpha(int ch);
int isalnum(int ch);
int isxdigit(int ch);
int isupper(int ch);
int islower(int ch);
int isprint(int ch);
int iscntrl(int ch);
int tolower(int ch);
int toupper(int ch);
#endif

27
cleonos/c/include/stdio.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef CLEONOS_LIBC_STDIO_H
#define CLEONOS_LIBC_STDIO_H
#include <stdarg.h>
#ifndef EOF
#define EOF (-1)
#endif
int putchar(int ch);
int getchar(void);
int fputc(int ch, int fd);
int fgetc(int fd);
int fputs(const char *text, int fd);
int puts(const char *text);
int vsnprintf(char *out, unsigned long out_size, const char *fmt, va_list args);
int snprintf(char *out, unsigned long out_size, const char *fmt, ...);
int vdprintf(int fd, const char *fmt, va_list args);
int dprintf(int fd, const char *fmt, ...);
int vfprintf(int fd, const char *fmt, va_list args);
int fprintf(int fd, const char *fmt, ...);
int vprintf(const char *fmt, va_list args);
int printf(const char *fmt, ...);
#endif

View File

@@ -0,0 +1,36 @@
#ifndef CLEONOS_LIBC_STDLIB_H
#define CLEONOS_LIBC_STDLIB_H
#include <stddef.h>
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef RAND_MAX
#define RAND_MAX 32767
#endif
int abs(int value);
long labs(long value);
long long llabs(long long value);
int atoi(const char *text);
long atol(const char *text);
long long atoll(const char *text);
long strtol(const char *text, char **out_end, int base);
unsigned long strtoul(const char *text, char **out_end, int base);
long long strtoll(const char *text, char **out_end, int base);
unsigned long long strtoull(const char *text, char **out_end, int base);
void srand(unsigned int seed);
int rand(void);
void exit(int status);
void abort(void);
#endif

View File

@@ -0,0 +1,29 @@
#ifndef CLEONOS_LIBC_STRING_H
#define CLEONOS_LIBC_STRING_H
#include <stddef.h>
void *memset(void *dst, int value, size_t size);
void *memcpy(void *dst, const void *src, size_t size);
void *memmove(void *dst, const void *src, size_t size);
int memcmp(const void *left, const void *right, size_t size);
void *memchr(const void *src, int value, size_t size);
size_t strlen(const char *text);
size_t strnlen(const char *text, size_t max_size);
char *strcpy(char *dst, const char *src);
char *strncpy(char *dst, const char *src, size_t size);
int strcmp(const char *left, const char *right);
int strncmp(const char *left, const char *right, size_t size);
char *strchr(const char *text, int ch);
char *strrchr(const char *text, int ch);
char *strstr(const char *haystack, const char *needle);
size_t strspn(const char *text, const char *accept);
size_t strcspn(const char *text, const char *reject);
char *strpbrk(const char *text, const char *accept);
char *strtok_r(char *text, const char *delim, char **saveptr);
char *strtok(char *text, const char *delim);
char *strcat(char *dst, const char *src);
char *strncat(char *dst, const char *src, size_t size);
#endif

View File

@@ -0,0 +1,45 @@
#include <ctype.h>
int isspace(int ch) {
return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\v' || ch == '\f') ? 1 : 0;
}
int isdigit(int ch) {
return (ch >= '0' && ch <= '9') ? 1 : 0;
}
int isalpha(int ch) {
return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) ? 1 : 0;
}
int isalnum(int ch) {
return (isalpha(ch) != 0 || isdigit(ch) != 0) ? 1 : 0;
}
int isxdigit(int ch) {
return (isdigit(ch) != 0 || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) ? 1 : 0;
}
int isupper(int ch) {
return (ch >= 'A' && ch <= 'Z') ? 1 : 0;
}
int islower(int ch) {
return (ch >= 'a' && ch <= 'z') ? 1 : 0;
}
int isprint(int ch) {
return (ch >= 0x20 && ch <= 0x7E) ? 1 : 0;
}
int iscntrl(int ch) {
return (ch >= 0x00 && ch <= 0x1F) || ch == 0x7F ? 1 : 0;
}
int tolower(int ch) {
return (isupper(ch) != 0) ? (ch - 'A' + 'a') : ch;
}
int toupper(int ch) {
return (islower(ch) != 0) ? (ch - 'a' + 'A') : ch;
}

254
cleonos/c/src/libc_stdlib.c Normal file
View File

@@ -0,0 +1,254 @@
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <cleonos_syscall.h>
static int clib_digit_value(int ch) {
if (ch >= '0' && ch <= '9') {
return ch - '0';
}
if (ch >= 'a' && ch <= 'z') {
return 10 + (ch - 'a');
}
if (ch >= 'A' && ch <= 'Z') {
return 10 + (ch - 'A');
}
return -1;
}
static const char *clib_skip_space(const char *text) {
const char *p = text;
if (p == (const char *)0) {
return (const char *)0;
}
while (*p != '\0' && isspace((unsigned char)*p) != 0) {
p++;
}
return p;
}
int abs(int value) {
return (value < 0) ? -value : value;
}
long labs(long value) {
return (value < 0L) ? -value : value;
}
long long llabs(long long value) {
return (value < 0LL) ? -value : value;
}
int atoi(const char *text) {
return (int)strtol(text, (char **)0, 10);
}
long atol(const char *text) {
return strtol(text, (char **)0, 10);
}
long long atoll(const char *text) {
return strtoll(text, (char **)0, 10);
}
unsigned long strtoul(const char *text, char **out_end, int base) {
const char *p = clib_skip_space(text);
int negative = 0;
unsigned long value = 0UL;
int any = 0;
int overflow = 0;
if (out_end != (char **)0) {
*out_end = (char *)text;
}
if (p == (const char *)0) {
return 0UL;
}
if (*p == '+' || *p == '-') {
negative = (*p == '-') ? 1 : 0;
p++;
}
if (base == 0) {
if (p[0] == '0') {
if ((p[1] == 'x' || p[1] == 'X') && isxdigit((unsigned char)p[2]) != 0) {
base = 16;
p += 2;
} else {
base = 8;
}
} else {
base = 10;
}
} else if (base == 16) {
if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
p += 2;
}
}
if (base < 2 || base > 36) {
return 0UL;
}
while (*p != '\0') {
int digit = clib_digit_value((unsigned char)*p);
if (digit < 0 || digit >= base) {
break;
}
any = 1;
if (value > (ULONG_MAX - (unsigned long)digit) / (unsigned long)base) {
overflow = 1;
value = ULONG_MAX;
} else if (overflow == 0) {
value = value * (unsigned long)base + (unsigned long)digit;
}
p++;
}
if (any == 0) {
return 0UL;
}
if (out_end != (char **)0) {
*out_end = (char *)p;
}
if (negative != 0) {
return (unsigned long)(0UL - value);
}
return value;
}
long strtol(const char *text, char **out_end, int base) {
const char *p = clib_skip_space(text);
int negative = 0;
unsigned long long value = 0ULL;
unsigned long long limit;
int any = 0;
int overflow = 0;
if (out_end != (char **)0) {
*out_end = (char *)text;
}
if (p == (const char *)0) {
return 0L;
}
if (*p == '+' || *p == '-') {
negative = (*p == '-') ? 1 : 0;
p++;
}
if (base == 0) {
if (p[0] == '0') {
if ((p[1] == 'x' || p[1] == 'X') && isxdigit((unsigned char)p[2]) != 0) {
base = 16;
p += 2;
} else {
base = 8;
}
} else {
base = 10;
}
} else if (base == 16) {
if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
p += 2;
}
}
if (base < 2 || base > 36) {
return 0L;
}
limit = (negative != 0) ? ((unsigned long long)LONG_MAX + 1ULL) : (unsigned long long)LONG_MAX;
while (*p != '\0') {
int digit = clib_digit_value((unsigned char)*p);
if (digit < 0 || digit >= base) {
break;
}
any = 1;
if (value > (limit - (unsigned long long)digit) / (unsigned long long)base) {
overflow = 1;
value = limit;
} else if (overflow == 0) {
value = value * (unsigned long long)base + (unsigned long long)digit;
}
p++;
}
if (any == 0) {
return 0L;
}
if (out_end != (char **)0) {
*out_end = (char *)p;
}
if (overflow != 0) {
return (negative != 0) ? LONG_MIN : LONG_MAX;
}
if (negative != 0) {
if (value == ((unsigned long long)LONG_MAX + 1ULL)) {
return LONG_MIN;
}
return -(long)value;
}
return (long)value;
}
long long strtoll(const char *text, char **out_end, int base) {
return (long long)strtol(text, out_end, base);
}
unsigned long long strtoull(const char *text, char **out_end, int base) {
return (unsigned long long)strtoul(text, out_end, base);
}
static unsigned long clib_rand_state = 1UL;
void srand(unsigned int seed) {
clib_rand_state = (unsigned long)seed;
if (clib_rand_state == 0UL) {
clib_rand_state = 1UL;
}
}
int rand(void) {
clib_rand_state = (1103515245UL * clib_rand_state) + 12345UL;
return (int)((clib_rand_state >> 16) & (unsigned long)RAND_MAX);
}
void exit(int status) {
(void)cleonos_sys_exit((u64)(unsigned long long)status);
for (;;) {
(void)cleonos_sys_yield();
}
}
void abort(void) {
exit(EXIT_FAILURE);
}

445
cleonos/c/src/libc_string.c Normal file
View File

@@ -0,0 +1,445 @@
#include <string.h>
void *memset(void *dst, int value, size_t size) {
unsigned char *d = (unsigned char *)dst;
unsigned char byte = (unsigned char)value;
size_t i;
if (d == (unsigned char *)0) {
return dst;
}
for (i = 0U; i < size; i++) {
d[i] = byte;
}
return dst;
}
void *memcpy(void *dst, const void *src, size_t size) {
unsigned char *d = (unsigned char *)dst;
const unsigned char *s = (const unsigned char *)src;
size_t i;
if (d == (unsigned char *)0 || s == (const unsigned char *)0) {
return dst;
}
for (i = 0U; i < size; i++) {
d[i] = s[i];
}
return dst;
}
void *memmove(void *dst, const void *src, size_t size) {
unsigned char *d = (unsigned char *)dst;
const unsigned char *s = (const unsigned char *)src;
size_t i;
if (d == (unsigned char *)0 || s == (const unsigned char *)0 || d == s || size == 0U) {
return dst;
}
if (d < s || d >= s + size) {
for (i = 0U; i < size; i++) {
d[i] = s[i];
}
} else {
for (i = size; i > 0U; i--) {
d[i - 1U] = s[i - 1U];
}
}
return dst;
}
int memcmp(const void *left, const void *right, size_t size) {
const unsigned char *a = (const unsigned char *)left;
const unsigned char *b = (const unsigned char *)right;
size_t i;
if (a == b || size == 0U) {
return 0;
}
if (a == (const unsigned char *)0) {
return -1;
}
if (b == (const unsigned char *)0) {
return 1;
}
for (i = 0U; i < size; i++) {
if (a[i] != b[i]) {
return (a[i] < b[i]) ? -1 : 1;
}
}
return 0;
}
void *memchr(const void *src, int value, size_t size) {
const unsigned char *s = (const unsigned char *)src;
unsigned char needle = (unsigned char)value;
size_t i;
if (s == (const unsigned char *)0) {
return (void *)0;
}
for (i = 0U; i < size; i++) {
if (s[i] == needle) {
return (void *)(s + i);
}
}
return (void *)0;
}
size_t strlen(const char *text) {
size_t len = 0U;
if (text == (const char *)0) {
return 0U;
}
while (text[len] != '\0') {
len++;
}
return len;
}
size_t strnlen(const char *text, size_t max_size) {
size_t len = 0U;
if (text == (const char *)0) {
return 0U;
}
while (len < max_size && text[len] != '\0') {
len++;
}
return len;
}
char *strcpy(char *dst, const char *src) {
size_t i = 0U;
if (dst == (char *)0 || src == (const char *)0) {
return dst;
}
while (src[i] != '\0') {
dst[i] = src[i];
i++;
}
dst[i] = '\0';
return dst;
}
char *strncpy(char *dst, const char *src, size_t size) {
size_t i = 0U;
if (dst == (char *)0 || src == (const char *)0) {
return dst;
}
while (i < size && src[i] != '\0') {
dst[i] = src[i];
i++;
}
while (i < size) {
dst[i++] = '\0';
}
return dst;
}
int strcmp(const char *left, const char *right) {
size_t i = 0U;
if (left == right) {
return 0;
}
if (left == (const char *)0) {
return -1;
}
if (right == (const char *)0) {
return 1;
}
while (left[i] != '\0' && right[i] != '\0') {
if (left[i] != right[i]) {
return (left[i] < right[i]) ? -1 : 1;
}
i++;
}
if (left[i] == right[i]) {
return 0;
}
return (left[i] < right[i]) ? -1 : 1;
}
int strncmp(const char *left, const char *right, size_t size) {
size_t i = 0U;
if (size == 0U || left == right) {
return 0;
}
if (left == (const char *)0) {
return -1;
}
if (right == (const char *)0) {
return 1;
}
while (i < size && left[i] != '\0' && right[i] != '\0') {
if (left[i] != right[i]) {
return (left[i] < right[i]) ? -1 : 1;
}
i++;
}
if (i == size) {
return 0;
}
if (left[i] == right[i]) {
return 0;
}
return (left[i] < right[i]) ? -1 : 1;
}
char *strchr(const char *text, int ch) {
char needle = (char)ch;
size_t i = 0U;
if (text == (const char *)0) {
return (char *)0;
}
while (text[i] != '\0') {
if (text[i] == needle) {
return (char *)(text + i);
}
i++;
}
if (needle == '\0') {
return (char *)(text + i);
}
return (char *)0;
}
char *strrchr(const char *text, int ch) {
char needle = (char)ch;
const char *last = (const char *)0;
size_t i = 0U;
if (text == (const char *)0) {
return (char *)0;
}
while (text[i] != '\0') {
if (text[i] == needle) {
last = text + i;
}
i++;
}
if (needle == '\0') {
return (char *)(text + i);
}
return (char *)last;
}
char *strstr(const char *haystack, const char *needle) {
size_t i;
size_t j;
size_t nlen;
if (haystack == (const char *)0 || needle == (const char *)0) {
return (char *)0;
}
nlen = strlen(needle);
if (nlen == 0U) {
return (char *)haystack;
}
for (i = 0U; haystack[i] != '\0'; i++) {
if (haystack[i] != needle[0]) {
continue;
}
for (j = 1U; j < nlen; j++) {
if (haystack[i + j] == '\0' || haystack[i + j] != needle[j]) {
break;
}
}
if (j == nlen) {
return (char *)(haystack + i);
}
}
return (char *)0;
}
static int clib_delim_contains(const char *delim, char ch) {
size_t i = 0U;
if (delim == (const char *)0) {
return 0;
}
while (delim[i] != '\0') {
if (delim[i] == ch) {
return 1;
}
i++;
}
return 0;
}
size_t strspn(const char *text, const char *accept) {
size_t n = 0U;
if (text == (const char *)0 || accept == (const char *)0) {
return 0U;
}
while (text[n] != '\0' && clib_delim_contains(accept, text[n]) != 0) {
n++;
}
return n;
}
size_t strcspn(const char *text, const char *reject) {
size_t n = 0U;
if (text == (const char *)0 || reject == (const char *)0) {
return 0U;
}
while (text[n] != '\0' && clib_delim_contains(reject, text[n]) == 0) {
n++;
}
return n;
}
char *strpbrk(const char *text, const char *accept) {
size_t i = 0U;
if (text == (const char *)0 || accept == (const char *)0) {
return (char *)0;
}
while (text[i] != '\0') {
if (clib_delim_contains(accept, text[i]) != 0) {
return (char *)(text + i);
}
i++;
}
return (char *)0;
}
char *strtok_r(char *text, const char *delim, char **saveptr) {
char *start;
char *cursor;
if (delim == (const char *)0 || saveptr == (char **)0) {
return (char *)0;
}
if (text != (char *)0) {
cursor = text;
} else {
cursor = *saveptr;
}
if (cursor == (char *)0) {
return (char *)0;
}
while (*cursor != '\0' && clib_delim_contains(delim, *cursor) != 0) {
cursor++;
}
if (*cursor == '\0') {
*saveptr = cursor;
return (char *)0;
}
start = cursor;
while (*cursor != '\0' && clib_delim_contains(delim, *cursor) == 0) {
cursor++;
}
if (*cursor == '\0') {
*saveptr = cursor;
} else {
*cursor = '\0';
*saveptr = cursor + 1;
}
return start;
}
char *strtok(char *text, const char *delim) {
static char *state = (char *)0;
return strtok_r(text, delim, &state);
}
char *strcat(char *dst, const char *src) {
size_t dlen = strlen(dst);
size_t i = 0U;
if (dst == (char *)0 || src == (const char *)0) {
return dst;
}
while (src[i] != '\0') {
dst[dlen + i] = src[i];
i++;
}
dst[dlen + i] = '\0';
return dst;
}
char *strncat(char *dst, const char *src, size_t size) {
size_t dlen = strlen(dst);
size_t i = 0U;
if (dst == (char *)0 || src == (const char *)0) {
return dst;
}
while (i < size && src[i] != '\0') {
dst[dlen + i] = src[i];
i++;
}
dst[dlen + i] = '\0';
return dst;
}

500
cleonos/c/src/stdio.c Normal file
View File

@@ -0,0 +1,500 @@
#include <stdio.h>
#include <cleonos_syscall.h>
typedef unsigned long clio_size_t;
#define CLIO_SINK_FD 1
#define CLIO_SINK_BUF 2
struct clio_sink {
int mode;
int fd;
char *buffer;
clio_size_t capacity;
clio_size_t count;
int failed;
};
static clio_size_t clio_strlen(const char *text) {
clio_size_t len = 0UL;
if (text == (const char *)0) {
return 0UL;
}
while (text[len] != '\0') {
len++;
}
return len;
}
static int clio_write_all_fd(int fd, const char *text, clio_size_t len) {
const char *cursor = text;
clio_size_t left = len;
if (fd < 0 || (text == (const char *)0 && len != 0UL)) {
return EOF;
}
while (left > 0UL) {
u64 wrote = cleonos_sys_fd_write((u64)fd, cursor, (u64)left);
clio_size_t progressed;
if (wrote == 0ULL || wrote == (u64)-1) {
return EOF;
}
progressed = (wrote > (u64)left) ? left : (clio_size_t)wrote;
cursor += progressed;
left -= progressed;
}
if (len > 0x7FFFFFFFUL) {
return 0x7FFFFFFF;
}
return (int)len;
}
static void clio_sink_init_fd(struct clio_sink *sink, int fd) {
sink->mode = CLIO_SINK_FD;
sink->fd = fd;
sink->buffer = (char *)0;
sink->capacity = 0UL;
sink->count = 0UL;
sink->failed = 0;
}
static void clio_sink_init_buffer(struct clio_sink *sink, char *out, clio_size_t out_size) {
sink->mode = CLIO_SINK_BUF;
sink->fd = -1;
sink->buffer = out;
sink->capacity = out_size;
sink->count = 0UL;
sink->failed = 0;
if (out != (char *)0 && out_size > 0UL) {
out[0] = '\0';
}
}
static void clio_sink_finalize_buffer(struct clio_sink *sink) {
if (sink->mode != CLIO_SINK_BUF || sink->buffer == (char *)0 || sink->capacity == 0UL) {
return;
}
if (sink->count < sink->capacity) {
sink->buffer[sink->count] = '\0';
} else {
sink->buffer[sink->capacity - 1UL] = '\0';
}
}
static int clio_sink_emit(struct clio_sink *sink, const char *text, clio_size_t len) {
if (sink == (struct clio_sink *)0 || text == (const char *)0 || len == 0UL) {
return 1;
}
if (sink->mode == CLIO_SINK_FD) {
if (clio_write_all_fd(sink->fd, text, len) == EOF) {
sink->failed = 1;
return 0;
}
} else {
if (sink->buffer != (char *)0 && sink->capacity > 0UL) {
clio_size_t i;
clio_size_t start = sink->count;
clio_size_t writable = 0UL;
if (start + 1UL < sink->capacity) {
writable = (sink->capacity - 1UL) - start;
}
if (len < writable) {
writable = len;
}
for (i = 0UL; i < writable; i++) {
sink->buffer[start + i] = text[i];
}
}
}
sink->count += len;
return 1;
}
static clio_size_t clio_u64_to_base(unsigned long long value,
unsigned int base,
int uppercase,
char *out,
clio_size_t out_size) {
char tmp[64];
clio_size_t pos = 0UL;
clio_size_t i = 0UL;
if (out == (char *)0 || out_size < 2UL || base < 2U || base > 16U) {
return 0UL;
}
if (value == 0ULL) {
out[0] = '0';
out[1] = '\0';
return 1UL;
}
while (value != 0ULL && pos < (clio_size_t)sizeof(tmp)) {
unsigned long long digit = value % (unsigned long long)base;
if (digit < 10ULL) {
tmp[pos++] = (char)('0' + digit);
} else {
char alpha = (uppercase != 0) ? 'A' : 'a';
tmp[pos++] = (char)(alpha + (char)(digit - 10ULL));
}
value /= (unsigned long long)base;
}
if (pos + 1UL > out_size) {
return 0UL;
}
while (pos > 0UL) {
pos--;
out[i++] = tmp[pos];
}
out[i] = '\0';
return i;
}
static clio_size_t clio_i64_to_dec(long long value, char *out, clio_size_t out_size) {
unsigned long long magnitude;
clio_size_t offset = 0UL;
clio_size_t len;
if (out == (char *)0 || out_size < 2UL) {
return 0UL;
}
if (value < 0LL) {
out[offset++] = '-';
if (offset + 2UL > out_size) {
return 0UL;
}
magnitude = (unsigned long long)(-(value + 1LL)) + 1ULL;
} else {
magnitude = (unsigned long long)value;
}
len = clio_u64_to_base(magnitude, 10U, 0, out + offset, out_size - offset);
if (len == 0UL) {
return 0UL;
}
return offset + len;
}
static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) {
const char *cursor = fmt;
if (sink == (struct clio_sink *)0 || fmt == (const char *)0) {
return EOF;
}
while (*cursor != '\0') {
if (*cursor != '%') {
if (clio_sink_emit(sink, cursor, 1UL) == 0) {
return EOF;
}
cursor++;
continue;
}
cursor++;
if (*cursor == '%') {
if (clio_sink_emit(sink, "%", 1UL) == 0) {
return EOF;
}
cursor++;
continue;
}
{
int length_mode = 0; /* 0: default, 1: l, 2: ll, 3: z */
char spec = *cursor;
char number_buf[64];
clio_size_t out_len = 0UL;
if (spec == 'l') {
cursor++;
spec = *cursor;
length_mode = 1;
if (spec == 'l') {
cursor++;
spec = *cursor;
length_mode = 2;
}
} else if (spec == 'z') {
cursor++;
spec = *cursor;
length_mode = 3;
}
if (spec == '\0') {
break;
}
if (spec == 's') {
const char *text = va_arg(args, const char *);
if (text == (const char *)0) {
text = "(null)";
}
out_len = clio_strlen(text);
if (clio_sink_emit(sink, text, out_len) == 0) {
return EOF;
}
} else if (spec == 'c') {
char out = (char)va_arg(args, int);
if (clio_sink_emit(sink, &out, 1UL) == 0) {
return EOF;
}
} else if (spec == 'd' || spec == 'i') {
long long value;
if (length_mode == 2) {
value = va_arg(args, long long);
} else if (length_mode == 1) {
value = (long long)va_arg(args, long);
} else if (length_mode == 3) {
value = (long long)va_arg(args, long long);
} else {
value = (long long)va_arg(args, int);
}
out_len = clio_i64_to_dec(value, number_buf, (clio_size_t)sizeof(number_buf));
if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) {
return EOF;
}
} else if (spec == 'u' || spec == 'x' || spec == 'X') {
unsigned long long value;
unsigned int base = (spec == 'u') ? 10U : 16U;
int upper = (spec == 'X') ? 1 : 0;
if (length_mode == 2) {
value = va_arg(args, unsigned long long);
} else if (length_mode == 1) {
value = (unsigned long long)va_arg(args, unsigned long);
} else if (length_mode == 3) {
value = (unsigned long long)va_arg(args, unsigned long long);
} else {
value = (unsigned long long)va_arg(args, unsigned int);
}
out_len = clio_u64_to_base(value, base, upper, number_buf, (clio_size_t)sizeof(number_buf));
if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) {
return EOF;
}
} else if (spec == 'p') {
const void *ptr = va_arg(args, const void *);
unsigned long long value = (unsigned long long)(unsigned long)ptr;
if (clio_sink_emit(sink, "0x", 2UL) == 0) {
return EOF;
}
out_len = clio_u64_to_base(value, 16U, 0, number_buf, (clio_size_t)sizeof(number_buf));
if (out_len == 0UL || clio_sink_emit(sink, number_buf, out_len) == 0) {
return EOF;
}
} else {
char fallback[2];
fallback[0] = spec;
fallback[1] = '\0';
if (clio_sink_emit(sink, "%", 1UL) == 0 || clio_sink_emit(sink, fallback, 1UL) == 0) {
return EOF;
}
}
cursor++;
}
}
if (sink->mode == CLIO_SINK_BUF) {
clio_sink_finalize_buffer(sink);
}
if (sink->failed != 0) {
return EOF;
}
if (sink->count > 0x7FFFFFFFUL) {
return 0x7FFFFFFF;
}
return (int)sink->count;
}
int putchar(int ch) {
char out = (char)(ch & 0xFF);
return (clio_write_all_fd(1, &out, 1UL) == EOF) ? EOF : (int)(unsigned char)out;
}
int getchar(void) {
char ch = '\0';
for (;;) {
u64 got = cleonos_sys_fd_read(0ULL, &ch, 1ULL);
if (got == 1ULL) {
return (int)(unsigned char)ch;
}
if (got == (u64)-1) {
return EOF;
}
(void)cleonos_sys_yield();
}
}
int fputc(int ch, int fd) {
char out = (char)(ch & 0xFF);
return (clio_write_all_fd(fd, &out, 1UL) == EOF) ? EOF : (int)(unsigned char)out;
}
int fgetc(int fd) {
char ch = '\0';
if (fd < 0) {
return EOF;
}
for (;;) {
u64 got = cleonos_sys_fd_read((u64)fd, &ch, 1ULL);
if (got == 1ULL) {
return (int)(unsigned char)ch;
}
if (got == (u64)-1) {
return EOF;
}
(void)cleonos_sys_yield();
}
}
int fputs(const char *text, int fd) {
clio_size_t len;
if (text == (const char *)0) {
return EOF;
}
len = clio_strlen(text);
return clio_write_all_fd(fd, text, len);
}
int puts(const char *text) {
int wrote = fputs(text, 1);
if (wrote == EOF) {
return EOF;
}
if (putchar('\n') == EOF) {
return EOF;
}
return wrote + 1;
}
int vsnprintf(char *out, unsigned long out_size, const char *fmt, va_list args) {
struct clio_sink sink;
va_list args_copy;
int rc;
clio_sink_init_buffer(&sink, out, out_size);
va_copy(args_copy, args);
rc = clio_vformat(&sink, fmt, args_copy);
va_end(args_copy);
return rc;
}
int snprintf(char *out, unsigned long out_size, const char *fmt, ...) {
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(out, out_size, fmt, args);
va_end(args);
return rc;
}
int vdprintf(int fd, const char *fmt, va_list args) {
struct clio_sink sink;
va_list args_copy;
int rc;
clio_sink_init_fd(&sink, fd);
va_copy(args_copy, args);
rc = clio_vformat(&sink, fmt, args_copy);
va_end(args_copy);
return rc;
}
int dprintf(int fd, const char *fmt, ...) {
va_list args;
int rc;
va_start(args, fmt);
rc = vdprintf(fd, fmt, args);
va_end(args);
return rc;
}
int vfprintf(int fd, const char *fmt, va_list args) {
return vdprintf(fd, fmt, args);
}
int fprintf(int fd, const char *fmt, ...) {
va_list args;
int rc;
va_start(args, fmt);
rc = vdprintf(fd, fmt, args);
va_end(args);
return rc;
}
int vprintf(const char *fmt, va_list args) {
return vdprintf(1, fmt, args);
}
int printf(const char *fmt, ...) {
va_list args;
int rc;
va_start(args, fmt);
rc = vdprintf(1, fmt, args);
va_end(args);
return rc;
}