diff options
| author | Bobby <[email protected]> | 2026-02-15 21:57:56 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-02-15 21:57:56 +0530 |
| commit | 98d2a091f675f2bf6987098ffe11f765835459c0 (patch) | |
| tree | 4cb911ad1eebf56e87fe75f28a2a5a90324b2388 | |
| parent | f5d145b42408d18a6f7b8c59616efc29697fd2ba (diff) | |
| download | akiba-98d2a091f675f2bf6987098ffe11f765835459c0.tar.xz akiba-98d2a091f675f2bf6987098ffe11f765835459c0.zip | |
Make all binaries use library imports. Remove akiba library.
| -rw-r--r-- | binaries/mi/mi.zig | 230 | ||||
| -rw-r--r-- | binaries/mi/mi.zon | 9 | ||||
| -rw-r--r-- | binaries/nav/nav.zig | 35 | ||||
| -rw-r--r-- | binaries/nav/nav.zon | 9 | ||||
| -rw-r--r-- | binaries/rd/rd.zig | 48 | ||||
| -rw-r--r-- | binaries/rd/rd.zon | 9 | ||||
| -rw-r--r-- | binaries/wipe/wipe.zig | 5 | ||||
| -rw-r--r-- | binaries/wipe/wipe.zon | 7 | ||||
| -rw-r--r-- | system/ash/ash.zig | 110 | ||||
| -rw-r--r-- | system/ash/ash.zon | 9 | ||||
| -rw-r--r-- | system/libraries/akiba/akiba.zig | 10 | ||||
| -rw-r--r-- | system/libraries/akiba/akiba.zon | 6 | ||||
| -rw-r--r-- | system/libraries/akiba/io.zig | 168 | ||||
| -rw-r--r-- | system/libraries/akiba/kata.zig | 38 | ||||
| -rw-r--r-- | system/libraries/akiba/start.zig | 31 | ||||
| -rw-r--r-- | system/libraries/akiba/sys.zig | 40 | ||||
| -rw-r--r-- | system/pulse/pulse.zig | 22 | ||||
| -rw-r--r-- | system/pulse/pulse.zon | 8 |
18 files changed, 138 insertions, 656 deletions
diff --git a/binaries/mi/mi.zig b/binaries/mi/mi.zig index 1e158a9..ca9e46f 100644 --- a/binaries/mi/mi.zig +++ b/binaries/mi/mi.zig @@ -1,28 +1,18 @@ -//! mi - Professional stack viewer for Akiba OS +//! mi - Stack viewer for Akiba OS -const akiba = @import("akiba"); - -const Color = struct { - const white: u32 = 0x00FFFFFF; - const cyan: u32 = 0x0000FFFF; - const blue: u32 = 0x004488DD; - const green: u32 = 0x0000DD88; - const yellow: u32 = 0x00DDDD00; - const gray: u32 = 0x00777777; - const purple: u32 = 0x00BB88FF; - const red: u32 = 0x00FF4444; -}; +const colors = @import("colors"); +const format = @import("format"); +const io = @import("io"); +const sys = @import("sys"); const PERM_OWNER: u8 = 1; const PERM_WORLD: u8 = 2; const PERM_READ_ONLY: u8 = 3; export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { - // Use first argument as path, or default to "" var target_path: []const u8 = ""; if (pc > 1) { - // Get pv[1] as the target path const arg = pv[1]; var len: usize = 0; while (arg[len] != 0) : (len += 1) {} @@ -30,7 +20,9 @@ export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { } display_stack(target_path) catch |err| { - mark_error(@errorName(err)); + format.color("mi: ", colors.white); + format.color(@errorName(err), colors.red); + format.print("\n"); return 1; }; @@ -38,29 +30,24 @@ export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { } fn display_stack(path: []const u8) !void { - var entries: [128]akiba.io.StackEntry = undefined; - const count = akiba.io.viewstack(path, &entries) catch { - // Path doesn't exist or isn't a directory - _ = akiba.io.mark(akiba.io.stream, "mi: cannot access '", Color.red) catch 0; - _ = akiba.io.mark(akiba.io.stream, path, Color.white) catch 0; - _ = akiba.io.mark(akiba.io.stream, "': No such stack.\n", Color.red) catch 0; + var entries: [128]io.StackEntry = undefined; + const count = io.viewstack(path, &entries) catch { + format.color("mi: cannot access '", colors.red); + format.print(path); + format.colorln("': No such stack.", colors.red); return; }; - // Check for empty directory (valid directory with 0 entries) if (count == 0) { - _ = akiba.io.mark(akiba.io.stream, path, Color.cyan) catch 0; - _ = akiba.io.mark(akiba.io.stream, " is empty.\n", Color.gray) catch 0; + format.color(path, colors.cyan); + format.colorln(" is empty.", colors.gray); return; } - // Calculate max widths for each column var max_access_len: usize = 6; var max_size_len: usize = 4; var max_owner_len: usize = 7; - var max_date_len: usize = 8; - const formatted_date_len: usize = 19; - if (formatted_date_len > max_date_len) max_date_len = formatted_date_len; + const max_date_len: usize = 19; for (0..count) |i| { const entry = &entries[i]; @@ -68,7 +55,7 @@ fn display_stack(path: []const u8) !void { if (perms.len > max_access_len) max_access_len = perms.len; var size_buf: [32]u8 = undefined; - const size_str = format_size(entry.size, &size_buf); + const size_str = format.formatSize(entry.size, &size_buf); if (size_str.len > max_size_len) max_size_len = size_str.len; if (entry.owner_name_len > max_owner_len) { @@ -76,16 +63,15 @@ fn display_stack(path: []const u8) !void { } } - // Print header - _ = akiba.io.mark(akiba.io.stream, "Access", Color.white) catch 0; + format.print("Access"); print_padding(max_access_len - 6 + 2); - _ = akiba.io.mark(akiba.io.stream, "Size", Color.white) catch 0; + format.print("Size"); print_padding(max_size_len - 4 + 2); - _ = akiba.io.mark(akiba.io.stream, "Persona", Color.white) catch 0; + format.print("Persona"); print_padding(max_owner_len - 7 + 3); - _ = akiba.io.mark(akiba.io.stream, "Modified", Color.white) catch 0; + format.print("Modified"); print_padding(max_date_len - 8 + 1); - _ = akiba.io.mark(akiba.io.stream, "Name\n", Color.white) catch 0; + format.println("Name"); var stack_count: usize = 0; var unit_count: usize = 0; @@ -97,43 +83,44 @@ fn display_stack(path: []const u8) !void { const owner = entry.owner_name[0..entry.owner_name_len]; const perms = get_permissions(entry.permission_type); - _ = akiba.io.mark(akiba.io.stream, perms, Color.cyan) catch 0; + format.color(perms, colors.cyan); print_padding(max_access_len - perms.len + 2); var size_buf: [32]u8 = undefined; - const size_str = format_size(entry.size, &size_buf); - _ = akiba.io.mark(akiba.io.stream, size_str, Color.green) catch 0; + const size_str = format.formatSize(entry.size, &size_buf); + format.color(size_str, colors.green); print_padding(max_size_len - size_str.len + 2); - _ = akiba.io.mark(akiba.io.stream, owner, Color.yellow) catch 0; + format.color(owner, colors.yellow); print_padding(max_owner_len - owner.len + 3); - format_date(entry.modified_time); - print_padding(1); + var date_buf: [32]u8 = undefined; + const date_str = format.formatDate(entry.modified_time, &date_buf); + format.color(date_str, colors.blue); + print_padding(max_date_len - date_str.len + 2); if (entry.is_stack) { stack_count += 1; total_size += entry.size; - _ = akiba.io.mark(akiba.io.stream, identity, Color.cyan) catch 0; - _ = akiba.io.mark(akiba.io.stream, "/", Color.blue) catch 0; + format.color(identity, colors.cyan); + format.color("/", colors.blue); } else { unit_count += 1; total_size += entry.size; - _ = akiba.io.mark(akiba.io.stream, identity, Color.white) catch 0; + format.print(identity); } - _ = akiba.io.mark(akiba.io.stream, "\n", Color.white) catch 0; + format.print("\n"); } - _ = akiba.io.mark(akiba.io.stream, "\n", Color.white) catch 0; - // Summary + format.print("\n"); + var buf: [16]u8 = undefined; - _ = akiba.io.mark(akiba.io.stream, int_to_str(stack_count, &buf), Color.gray) catch 0; - _ = akiba.io.mark(akiba.io.stream, " stacks ", Color.gray) catch 0; - _ = akiba.io.mark(akiba.io.stream, int_to_str(unit_count, &buf), Color.gray) catch 0; - _ = akiba.io.mark(akiba.io.stream, " units ", Color.gray) catch 0; + format.color(format.intToStr(stack_count, &buf), colors.gray); + format.color(" stacks ", colors.gray); + format.color(format.intToStr(unit_count, &buf), colors.gray); + format.color(" units ", colors.gray); var size_buf: [32]u8 = undefined; - _ = akiba.io.mark(akiba.io.stream, format_size(total_size, &size_buf), Color.gray) catch 0; - _ = akiba.io.mark(akiba.io.stream, "\n", Color.white) catch 0; + format.colorln(format.formatSize(total_size, &size_buf), colors.gray); } fn get_permissions(perm_type: u8) []const u8 { @@ -148,139 +135,6 @@ fn get_permissions(perm_type: u8) []const u8 { fn print_padding(count: usize) void { var i: usize = 0; while (i < count) : (i += 1) { - _ = akiba.io.mark(akiba.io.stream, " ", Color.white) catch {}; - } -} - -fn format_date(timestamp: u64) void { - if (timestamp == 0) { - _ = akiba.io.mark(akiba.io.stream, " 1 Jan 1970 00:00 ", Color.blue) catch 0; - return; - } - const SECONDS_PER_DAY: u64 = 86400; - const SECONDS_PER_HOUR: u64 = 3600; - const SECONDS_PER_MINUTE: u64 = 60; - const days_since_epoch = timestamp / SECONDS_PER_DAY; - const seconds_today = timestamp % SECONDS_PER_DAY; - const hours = seconds_today / SECONDS_PER_HOUR; - const minutes = (seconds_today % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE; - const DAYS_PER_4_YEARS: u64 = 1461; - var year: u64 = 1970; - var remaining_days = days_since_epoch; - const four_year_cycles = remaining_days / DAYS_PER_4_YEARS; - year += four_year_cycles * 4; - remaining_days = remaining_days % DAYS_PER_4_YEARS; - while (remaining_days >= 365) { - const is_leap = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0); - const days_this_year: u64 = if (is_leap) 366 else 365; - if (remaining_days >= days_this_year) { - remaining_days -= days_this_year; - year += 1; - } else { - break; - } - } - const is_leap = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0); - const days_in_months = if (is_leap) [_]u64{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } else [_]u64{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - const month_names = [_][]const u8{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - var month: usize = 0; - var day: u64 = remaining_days + 1; - for (days_in_months, 0..) |days, m| { - if (day <= days) { - month = m; - break; - } - day -= days; - } - var buf: [20]u8 = undefined; - var pos: usize = 0; - if (day < 10) { - buf[pos] = '0'; - pos += 1; - } - const day_str = int_to_str(day, buf[pos..]); - pos += day_str.len; - buf[pos] = ' '; - pos += 1; - for (month_names[month]) |c| { - buf[pos] = c; - pos += 1; + format.print(" "); } - buf[pos] = ' '; - pos += 1; - const year_str = int_to_str(year, buf[pos..]); - pos += year_str.len; - buf[pos] = ' '; - pos += 1; - if (hours < 10) { - buf[pos] = '0'; - pos += 1; - } - const hour_str = int_to_str(hours, buf[pos..]); - pos += hour_str.len; - buf[pos] = ':'; - pos += 1; - if (minutes < 10) { - buf[pos] = '0'; - pos += 1; - } - const min_str = int_to_str(minutes, buf[pos..]); - pos += min_str.len; - buf[pos] = ' '; - pos += 1; - buf[pos] = ' '; - pos += 1; - _ = akiba.io.mark(akiba.io.stream, buf[0..pos], Color.blue) catch 0; -} - -fn format_size(size: u64, buf: []u8) []u8 { - if (size < 1024) { - const s = int_to_str(size, buf); - buf[s.len] = 'B'; - return buf[0 .. s.len + 1]; - } else if (size < 1024 * 1024) { - const kb = size / 1024; - const s = int_to_str(kb, buf); - buf[s.len] = 'K'; - buf[s.len + 1] = 'B'; - return buf[0 .. s.len + 2]; - } else if (size < 1024 * 1024 * 1024) { - const mb = size / (1024 * 1024); - const s = int_to_str(mb, buf); - buf[s.len] = 'M'; - buf[s.len + 1] = 'B'; - return buf[0 .. s.len + 2]; - } else { - const gb = size / (1024 * 1024 * 1024); - const s = int_to_str(gb, buf); - buf[s.len] = 'G'; - buf[s.len + 1] = 'B'; - return buf[0 .. s.len + 2]; - } -} - -fn int_to_str(num: usize, buf: []u8) []u8 { - if (num == 0) { - buf[0] = '0'; - return buf[0..1]; - } - var n = num; - var i: usize = 0; - while (n > 0) : (i += 1) { - buf[i] = @as(u8, @intCast((n % 10) + '0')); - n /= 10; - } - var j: usize = 0; - while (j < i / 2) : (j += 1) { - const tmp = buf[j]; - buf[j] = buf[i - 1 - j]; - buf[i - 1 - j] = tmp; - } - return buf[0..i]; -} - -fn mark_error(msg: []const u8) void { - _ = akiba.io.mark(akiba.io.trace, "mi: ", Color.white) catch 0; - _ = akiba.io.mark(akiba.io.trace, msg, Color.white) catch 0; - _ = akiba.io.mark(akiba.io.trace, "\n", Color.white) catch 0; } diff --git a/binaries/mi/mi.zon b/binaries/mi/mi.zon index b7faaf0..352d31e 100644 --- a/binaries/mi/mi.zon +++ b/binaries/mi/mi.zon @@ -2,9 +2,10 @@ .name = "mi", .version = "0.1.0", .dependencies = .{ - .akiba = .{ .path = "../../system/libraries/akiba" }, - }, - .paths = .{ - "mi.zig", + .sys, + .io, + .colors, + .format, }, + .entry = "mi.zig", } diff --git a/binaries/nav/nav.zig b/binaries/nav/nav.zig index 98883d0..acdeeb6 100644 --- a/binaries/nav/nav.zig +++ b/binaries/nav/nav.zig @@ -1,44 +1,31 @@ //! nav - Navigate the filesystem -//! -//! nav - Print current location -//! nav <path> - Navigate to path -//! nav ^ - Navigate to parent -//! nav / - Navigate to root -const akiba = @import("akiba"); +const colors = @import("colors"); +const format = @import("format"); +const io = @import("io"); +const sys = @import("sys"); -const Color = struct { - const white: u32 = 0x00FFFFFF; - const green: u32 = 0x0088FF88; - const red: u32 = 0x00FF4444; -}; - -// Global buffer var location_buf: [256]u8 = undefined; export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { - // No arguments - print current location if (pc <= 1) { - const location = akiba.io.getlocation(&location_buf) catch { - _ = akiba.io.mark(akiba.io.stream, "nav: cannot get current location.\n", Color.red) catch 0; + const location = io.getlocation(&location_buf) catch { + format.colorln("nav: cannot get current location.", colors.red); return 1; }; - _ = akiba.io.mark(akiba.io.stream, location, Color.green) catch 0; - _ = akiba.io.mark(akiba.io.stream, "\n", Color.white) catch 0; + format.colorln(location, colors.green); return 0; } - // Get target path from argument const arg = pv[1]; var target_len: usize = 0; while (arg[target_len] != 0) : (target_len += 1) {} const target = arg[0..target_len]; - // Navigate - setlocation auto-sends letter to parent - akiba.io.setlocation(target) catch { - _ = akiba.io.mark(akiba.io.stream, "nav: cannot navigate to '", Color.red) catch 0; - _ = akiba.io.mark(akiba.io.stream, target, Color.white) catch 0; - _ = akiba.io.mark(akiba.io.stream, "': No such stack.\n", Color.red) catch 0; + io.setlocation(target) catch { + format.color("nav: cannot navigate to '", colors.red); + format.print(target); + format.colorln("': No such stack.", colors.red); return 1; }; diff --git a/binaries/nav/nav.zon b/binaries/nav/nav.zon index 8597b44..21d50a4 100644 --- a/binaries/nav/nav.zon +++ b/binaries/nav/nav.zon @@ -2,9 +2,10 @@ .name = "nav", .version = "0.1.0", .dependencies = .{ - .akiba = .{ .path = "../../system/libraries/akiba" }, - }, - .paths = .{ - "nav.zig", + .sys, + .io, + .colors, + .format, }, + .entry = "nav.zig", } diff --git a/binaries/rd/rd.zig b/binaries/rd/rd.zig index e16f7cc..008cb54 100644 --- a/binaries/rd/rd.zig +++ b/binaries/rd/rd.zig @@ -1,61 +1,47 @@ //! rd - Read unit contents -//! -//! rd <location> - Display contents of a unit (file) -//! rd - Error: no location specified -const akiba = @import("akiba"); +const colors = @import("colors"); +const format = @import("format"); +const io = @import("io"); +const sys = @import("sys"); -const Color = struct { - const white: u32 = 0x00FFFFFF; - const red: u32 = 0x00FF4444; - const gray: u32 = 0x00888888; -}; - -// Buffer for file contents (64KB max) var file_buffer: [64 * 1024]u8 = undefined; export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { - // No arguments - show error if (pc <= 1) { - _ = akiba.io.mark(akiba.io.stream, "rd: missing unit location.\n", Color.red) catch 0; + format.colorln("rd: missing unit location.", colors.red); return 1; } - // Get location from argument const arg = pv[1]; var location_len: usize = 0; while (arg[location_len] != 0) : (location_len += 1) {} const location = arg[0..location_len]; - // Open the file - const fd = akiba.io.attach(location, akiba.io.VIEW_ONLY) catch { - _ = akiba.io.mark(akiba.io.stream, "rd: cannot access '", Color.red) catch 0; - _ = akiba.io.mark(akiba.io.stream, location, Color.white) catch 0; - _ = akiba.io.mark(akiba.io.stream, "': No such unit.\n", Color.red) catch 0; + const fd = io.attach(location, io.VIEW_ONLY) catch { + format.color("rd: cannot access '", colors.red); + format.print(location); + format.colorln("': No such unit.", colors.red); return 1; }; - // Read contents - const bytes_read = akiba.io.view(fd, &file_buffer) catch { - _ = akiba.io.mark(akiba.io.stream, "rd: cannot read '", Color.red) catch 0; - _ = akiba.io.mark(akiba.io.stream, location, Color.white) catch 0; - _ = akiba.io.mark(akiba.io.stream, "'.\n", Color.red) catch 0; - akiba.io.seal(fd); + const bytes_read = io.view(fd, &file_buffer) catch { + format.color("rd: cannot read '", colors.red); + format.print(location); + format.colorln("'.", colors.red); + io.seal(fd); return 1; }; - // Display contents if (bytes_read > 0) { - _ = akiba.io.mark(akiba.io.stream, file_buffer[0..bytes_read], Color.white) catch 0; + format.print(file_buffer[0..bytes_read]); - // Add newline if file doesn't end with one if (file_buffer[bytes_read - 1] != '\n') { - _ = akiba.io.mark(akiba.io.stream, "\n", Color.white) catch 0; + format.print("\n"); } } - // Close file - akiba.io.seal(fd); + io.seal(fd); return 0; } diff --git a/binaries/rd/rd.zon b/binaries/rd/rd.zon index 0480840..47cddc8 100644 --- a/binaries/rd/rd.zon +++ b/binaries/rd/rd.zon @@ -2,9 +2,10 @@ .name = "rd", .version = "0.1.0", .dependencies = .{ - .akiba = .{ .path = "../../system/libraries/akiba" }, - }, - .paths = .{ - "rd.zig", + .sys, + .io, + .colors, + .format, }, + .entry = "rd.zig", } diff --git a/binaries/wipe/wipe.zig b/binaries/wipe/wipe.zig index 34c6f95..8bdc336 100644 --- a/binaries/wipe/wipe.zig +++ b/binaries/wipe/wipe.zig @@ -1,10 +1,11 @@ //! wipe - Clear the terminal screen -const akiba = @import("akiba"); +const io = @import("io"); +const sys = @import("sys"); export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { _ = pc; _ = pv; - akiba.io.wipe(); + io.wipe(); return 0; } diff --git a/binaries/wipe/wipe.zon b/binaries/wipe/wipe.zon index 0c6f141..4c90d6c 100644 --- a/binaries/wipe/wipe.zon +++ b/binaries/wipe/wipe.zon @@ -2,9 +2,8 @@ .name = "wipe", .version = "0.1.0", .dependencies = .{ - .akiba = .{ .path = "../../system/libraries/akiba" }, - }, - .paths = .{ - "wipe.zig", + .sys, + .io, }, + .entry = "wipe.zig", } diff --git a/system/ash/ash.zig b/system/ash/ash.zig index 013de87..5149ab8 100644 --- a/system/ash/ash.zig +++ b/system/ash/ash.zig @@ -1,6 +1,11 @@ //! Ash - Akiba Shell -const akiba = @import("akiba"); +const colors = @import("colors"); +const format = @import("format"); +const io = @import("io"); +const kata = @import("kata"); +const string = @import("string"); +const sys = @import("sys"); const MAX_INPUT = 256; const MAX_ARGS = 16; @@ -14,41 +19,35 @@ var letter_buffer: [256]u8 = undefined; var arg_ptrs: [MAX_ARGS][*:0]const u8 = undefined; var arg_storage: [MAX_ARGS][128]u8 = undefined; -const Color = struct { - const white: u32 = 0x00FFFFFF; - const green: u32 = 0x0088FF88; - const red: u32 = 0x00FF4444; -}; - export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { _ = pc; _ = pv; while (true) { - const location = akiba.io.getlocation(&location_buffer) catch "/"; - const stack_name = get_stack_name(location); + const location = io.getlocation(&location_buffer) catch "/"; + const stack_name = string.getStackName(location); - _ = akiba.io.mark(akiba.io.stream, "(", Color.white) catch {}; - _ = akiba.io.mark(akiba.io.stream, stack_name, Color.green) catch {}; - _ = akiba.io.mark(akiba.io.stream, ") >>> ", Color.white) catch {}; + format.print("("); + format.color(stack_name, colors.green); + format.print(") >>> "); input_len = 0; while (true) { - const char = akiba.io.getchar() catch continue; + const char = io.getchar() catch continue; if (char == '\n') { - _ = akiba.io.mark(akiba.io.stream, "\n", Color.white) catch {}; + format.print("\n"); break; } else if (char == '\x08') { if (input_len > 0) { input_len -= 1; - _ = akiba.io.mark(akiba.io.stream, "\x08", Color.white) catch {}; + format.print("\x08"); } } else if (char >= 32 and char <= 126 and input_len < MAX_INPUT - 1) { input_buffer[input_len] = char; input_len += 1; char_buffer[0] = char; - _ = akiba.io.mark(akiba.io.stream, &char_buffer, Color.white) catch {}; + format.print(&char_buffer); } } @@ -87,99 +86,40 @@ fn execute_command(input: []const u8) void { if (argc == 0) return; - const cmd = arg_storage[0][0..find_null(&arg_storage[0])]; + const cmd = arg_storage[0][0..string.findNull(&arg_storage[0])]; var path_buf: [512]u8 = undefined; + const path = string.concat3(&path_buf, "/binaries/", cmd, ".akiba"); - const path = build_path(&path_buf, "/binaries/", cmd, ".akiba"); if (try_spawn_with_args(path, arg_ptrs[0..argc])) { process_letters(); return; } - _ = akiba.io.mark(akiba.io.stream, "ash: binary not found: ", Color.red) catch {}; - _ = akiba.io.mark(akiba.io.stream, cmd, Color.white) catch {}; - _ = akiba.io.mark(akiba.io.stream, ".\n", Color.white) catch {}; + format.color("ash: binary not found: ", colors.red); + format.print(cmd); + format.println("."); } fn try_spawn_with_args(path: []const u8, argv: [][*:0]const u8) bool { - const pid = akiba.kata.spawn_with_args(path, argv) catch { + const pid = kata.spawnWithArgs(path, argv) catch { return false; }; - _ = akiba.kata.wait(pid) catch {}; + _ = kata.wait(pid) catch {}; return true; } fn process_letters() void { - const letter_type = akiba.io.read_letter(&letter_buffer) catch return; + const letter_type = io.readLetter(&letter_buffer) catch return; - if (letter_type == akiba.io.Letter.NAVIGATE) { + if (letter_type == io.Letter.NAVIGATE) { var len: usize = 0; while (len < letter_buffer.len and letter_buffer[len] != 0) : (len += 1) {} if (len > 0) { - akiba.io.setlocation(letter_buffer[0..len]) catch {}; + io.setlocation(letter_buffer[0..len]) catch {}; } } } - -fn find_null(buf: []const u8) usize { - var len: usize = 0; - while (len < buf.len and buf[len] != 0) : (len += 1) {} - return len; -} - -fn build_path(buf: []u8, prefix: []const u8, name: []const u8, suffix: []const u8) []const u8 { - var pos: usize = 0; - for (prefix) |c| { - if (pos >= buf.len) break; - buf[pos] = c; - pos += 1; - } - for (name) |c| { - if (pos >= buf.len) break; - buf[pos] = c; - pos += 1; - } - for (suffix) |c| { - if (pos >= buf.len) break; - buf[pos] = c; - pos += 1; - } - return buf[0..pos]; -} - -fn get_stack_name(location: []const u8) []const u8 { - // Root case - if (location.len == 0 or (location.len == 1 and location[0] == '/')) { - return "/"; - } - - // Find last '/' and return everything after it - var last_slash: usize = 0; - for (location, 0..) |c, i| { - if (c == '/') { - last_slash = i; - } - } - - // If path ends with '/', look for second-to-last slash - if (last_slash == location.len - 1 and location.len > 1) { - var i: usize = location.len - 2; - while (i > 0) : (i -= 1) { - if (location[i] == '/') { - return location[i + 1 .. location.len - 1]; - } - } - return location[1 .. location.len - 1]; - } - - // Return part after last slash - if (last_slash + 1 < location.len) { - return location[last_slash + 1 ..]; - } - - return location; -} diff --git a/system/ash/ash.zon b/system/ash/ash.zon index 0c72775..e96488a 100644 --- a/system/ash/ash.zon +++ b/system/ash/ash.zon @@ -1,8 +1,13 @@ .{ .name = "ash", .version = "0.1.0", - .paths = .{""}, .dependencies = .{ - .akiba = .{ .path = "../libraries/akiba" }, + .sys, + .io, + .kata, + .colors, + .string, + .format, }, + .entry = "ash.zig", } diff --git a/system/libraries/akiba/akiba.zig b/system/libraries/akiba/akiba.zig deleted file mode 100644 index 77911e1..0000000 --- a/system/libraries/akiba/akiba.zig +++ /dev/null @@ -1,10 +0,0 @@ -//! Akiba Runtime - Core system library - -pub const kata = @import("kata.zig"); -pub const io = @import("io.zig"); -pub const sys = @import("sys.zig"); -pub const start = @import("start.zig"); - -comptime { - _ = start; -} diff --git a/system/libraries/akiba/akiba.zon b/system/libraries/akiba/akiba.zon deleted file mode 100644 index aad4a03..0000000 --- a/system/libraries/akiba/akiba.zon +++ /dev/null @@ -1,6 +0,0 @@ -.{ - .name = "akiba", - .version = "1.0.0", - .type = .library, - .entry = "akiba.zig", -} diff --git a/system/libraries/akiba/io.zig b/system/libraries/akiba/io.zig deleted file mode 100644 index 155ac70..0000000 --- a/system/libraries/akiba/io.zig +++ /dev/null @@ -1,168 +0,0 @@ -//! File I/O operations - -const sys = @import("sys.zig"); -const kata = @import("kata.zig"); - -pub const Error = error{ - NotFound, - PermissionDenied, - InvalidDescriptor, - ReadFailed, - WriteFailed, -}; - -pub const FileDescriptor = u32; - -// Standard file descriptors -pub const source: FileDescriptor = 0; // Input stream -pub const stream: FileDescriptor = 1; // Output stream -pub const trace: FileDescriptor = 2; // Error/trace stream - -// Open modes -pub const VIEW_ONLY: u32 = 0x01; -pub const MARK_ONLY: u32 = 0x02; -pub const BOTH: u32 = 0x03; -pub const CREATE: u32 = 0x0100; - -pub const StackEntry = extern struct { - identity: [64]u8, - identity_len: u8, - is_stack: bool, - owner_name_len: u8, - permission_type: u8, - size: u32, - modified_time: u64, - owner_name: [64]u8, -}; - -// Letter types -pub const Letter = struct { - pub const NONE: u8 = 0; - pub const NAVIGATE: u8 = 1; -}; - -pub fn attach(path: []const u8, flags: u32) Error!FileDescriptor { - const result = sys.syscall(.attach, .{ @intFromPtr(path.ptr), flags }); - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return Error.NotFound; - } - return @truncate(result); -} - -pub fn seal(fd: FileDescriptor) void { - _ = sys.syscall(.seal, .{fd}); -} - -pub fn view(fd: FileDescriptor, buffer: []u8) Error!usize { - const result = sys.syscall(.view, .{ fd, @intFromPtr(buffer.ptr), buffer.len }); - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return Error.ReadFailed; - } - return result; -} - -pub fn viewstack(path: []const u8, entries: []StackEntry) !usize { - const result = sys.syscall(.viewstack, .{ - @intFromPtr(path.ptr), - path.len, - @intFromPtr(entries.ptr), - entries.len, - }); - - // Check for error (-1) - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.InvalidPath; - } - - return @intCast(result); -} - -pub fn mark(fd: FileDescriptor, data: []const u8, color: u32) Error!usize { - const result = sys.syscall(.mark, .{ fd, @intFromPtr(data.ptr), data.len, color }); - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return Error.WriteFailed; - } - return result; -} - -pub fn getchar() !u8 { - // Loop until character is available - while (true) { - const result = sys.syscall(.getkeychar, .{}); - if (result != @as(u64, @bitCast(@as(i64, -2)))) { - if (result != @as(u64, @bitCast(@as(i64, -1)))) { - return @truncate(result); - } - return error.ReadFailed; - } - // No input yet (-2 = EAGAIN), yield to kernel - kata.yield(); - } -} - -pub fn getlocation(buffer: []u8) ![]u8 { - const result = sys.syscall(.getlocation, .{ - @intFromPtr(buffer.ptr), - buffer.len, - }); - - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.GetLocationFailed; - } - - return buffer[0..@intCast(result)]; -} - -pub fn setlocation(path: []const u8) !void { - const result = sys.syscall(.setlocation, .{ - @intFromPtr(path.ptr), - path.len, - }); - - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.InvalidPath; - } -} - -/// Send a letter to parent Kata -pub fn send_letter(letter_type: u8, data: []const u8) !void { - const result = sys.syscall(.postman, .{ - @as(u64, 0), // MODE_SEND - @as(u64, letter_type), - @intFromPtr(data.ptr), - data.len, - }); - - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.SendFailed; - } -} - -/// Read letter from inbox -/// Returns letter type (0 = no letter), copies data to buffer -pub fn read_letter(buffer: []u8) !u8 { - const result = sys.syscall(.postman, .{ - @as(u64, 1), // MODE_READ - @intFromPtr(buffer.ptr), - buffer.len, - }); - - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.ReadFailed; - } - - return @intCast(result); -} - -pub fn wipe() void { - _ = sys.syscall(.wipe, .{}); -} - -pub fn print(text: []const u8) Error!void { - _ = try mark(stream, text, 0x00FFFFFF); -} - -pub fn println(text: []const u8) Error!void { - _ = try mark(stream, text, 0x00FFFFFF); - _ = try mark(stream, "\n", 0x00FFFFFF); -} diff --git a/system/libraries/akiba/kata.zig b/system/libraries/akiba/kata.zig deleted file mode 100644 index be3189b..0000000 --- a/system/libraries/akiba/kata.zig +++ /dev/null @@ -1,38 +0,0 @@ -//! Kata (process) control functions - -const sys = @import("sys.zig"); - -pub fn yield() void { - _ = sys.syscall(.yield, .{}); -} - -pub fn exit(code: u64) noreturn { - _ = sys.syscall(.exit, .{code}); - unreachable; -} - -pub fn spawn(path: []const u8) !u32 { - const result = sys.syscall(.spawn, .{ @intFromPtr(path.ptr), path.len, @as(u64, 0), @as(u64, 0) }); - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.SpawnFailed; - } - return @truncate(result); -} - -pub fn spawn_with_args(path: []const u8, argv: [][*:0]const u8) !u32 { - const result = sys.syscall(.spawn, .{ @intFromPtr(path.ptr), path.len, @intFromPtr(argv.ptr), argv.len }); - if (result == @as(u64, @bitCast(@as(i64, -1)))) { - return error.SpawnFailed; - } - return @truncate(result); -} - -pub fn wait(pid: u32) !u64 { - while (true) { - const result = sys.syscall(.wait, .{pid}); - if (result != @as(u64, @bitCast(@as(i64, -1)))) { - return result; - } - yield(); - } -} diff --git a/system/libraries/akiba/start.zig b/system/libraries/akiba/start.zig deleted file mode 100644 index fbe11e2..0000000 --- a/system/libraries/akiba/start.zig +++ /dev/null @@ -1,31 +0,0 @@ -//! Akiba Runtime Entry Point -//! Provides _start that calls user's main(pc, pv) and handles exit - -// User must provide this -extern fn main(pc: u32, pv: [*]const [*:0]const u8) u8; - -export fn _start() callconv(.naked) noreturn { - // At entry, stack layout is: - // [RSP + 0] = pc (parameter count, 64-bit but only low 32 used) - // [RSP + 8] = pv (pointer to parameter vector) - // - // x86-64 calling convention: - // First arg (u32) -> EDI - // Second arg (ptr) -> RSI - - asm volatile ( - // Load arguments for main(pc, pv) - \\mov (%%rsp), %%edi - \\mov 8(%%rsp), %%rsi - // Align stack to 16 bytes before call (required by ABI) - \\and $-16, %%rsp - \\call main - // main returned exit code in AL, zero-extend to RDI for exit syscall - \\movzbl %%al, %%edi - // exit syscall (0x01) - \\mov $0x01, %%eax - \\syscall - // Should never reach here - \\ud2 - ); -} diff --git a/system/libraries/akiba/sys.zig b/system/libraries/akiba/sys.zig deleted file mode 100644 index b2da4f1..0000000 --- a/system/libraries/akiba/sys.zig +++ /dev/null @@ -1,40 +0,0 @@ -//! Low-level invocation interface - -pub const Invocation = enum(u64) { exit = 0x01, attach = 0x02, seal = 0x03, view = 0x04, mark = 0x05, spawn = 0x06, wait = 0x07, yield = 0x08, getkeychar = 0x09, viewstack = 0x0A, getlocation = 0x0B, setlocation = 0x0C, postman = 0x0D, wipe = 0x0E }; - -/// Perform a system invocation with variable arguments -/// Uses comptime to handle different argument counts -pub inline fn syscall(invocation: Invocation, args: anytype) u64 { - const Args = @TypeOf(args); - const fields = @typeInfo(Args).@"struct".fields; - - // Always set all 6 argument registers, defaulting unused ones to 0 - const arg0: u64 = if (fields.len > 0) @as(u64, @bitCast(toU64(args[0]))) else 0; - const arg1: u64 = if (fields.len > 1) @as(u64, @bitCast(toU64(args[1]))) else 0; - const arg2: u64 = if (fields.len > 2) @as(u64, @bitCast(toU64(args[2]))) else 0; - const arg3: u64 = if (fields.len > 3) @as(u64, @bitCast(toU64(args[3]))) else 0; - const arg4: u64 = if (fields.len > 4) @as(u64, @bitCast(toU64(args[4]))) else 0; - const arg5: u64 = if (fields.len > 5) @as(u64, @bitCast(toU64(args[5]))) else 0; - - return asm volatile ("syscall" - : [ret] "={rax}" (-> u64), - : [number] "{rax}" (@intFromEnum(invocation)), - [arg0] "{rdi}" (arg0), - [arg1] "{rsi}" (arg1), - [arg2] "{rdx}" (arg2), - [arg3] "{r10}" (arg3), - [arg4] "{r8}" (arg4), - [arg5] "{r9}" (arg5), - : .{ .rcx = true, .r11 = true, .memory = true }); -} - -/// Convert various types to u64 for syscall arguments -inline fn toU64(value: anytype) u64 { - const T = @TypeOf(value); - return switch (@typeInfo(T)) { - .int, .comptime_int => @as(u64, @intCast(value)), - .pointer => @intFromPtr(value), - .@"enum" => @intFromEnum(value), - else => @as(u64, @bitCast(value)), - }; -} diff --git a/system/pulse/pulse.zig b/system/pulse/pulse.zig index d0f3dd2..3ef1091 100644 --- a/system/pulse/pulse.zig +++ b/system/pulse/pulse.zig @@ -1,29 +1,27 @@ //! Pulse - Akiba OS Init System -//! First Kata to run (PID 1), manages system lifecycle -const akiba = @import("akiba"); +const format = @import("format"); +const kata = @import("kata"); +const sys = @import("sys"); export fn main(pc: u32, pv: [*]const [*:0]const u8) u8 { _ = pc; _ = pv; - // Init loop - respawn shell when it exits while (true) { - const shell_pid = akiba.kata.spawn("/system/ash/ash.akiba") catch { - akiba.io.println("Pulse: Failed to spawn shell") catch {}; - akiba.kata.yield(); + const shell_pid = kata.spawn("/system/ash/ash.akiba") catch { + format.println("Pulse: Failed to spawn shell"); + kata.yield(); continue; }; - // Wait for shell to exit - _ = akiba.kata.wait(shell_pid) catch { - akiba.io.println("Pulse: Shell wait failed") catch {}; - akiba.kata.yield(); + _ = kata.wait(shell_pid) catch { + format.println("Pulse: Shell wait failed"); + kata.yield(); continue; }; - // Shell exited, respawn - akiba.io.println("\nPulse: Shell exited, respawning...\n") catch {}; + format.println("\nPulse: Shell exited, respawning...\n"); } return 0; diff --git a/system/pulse/pulse.zon b/system/pulse/pulse.zon index d35e8c9..6a8da7f 100644 --- a/system/pulse/pulse.zon +++ b/system/pulse/pulse.zon @@ -1,8 +1,10 @@ .{ .name = "pulse", - .version = "1.0.0", - .type = .init, + .version = "0.1.0", .dependencies = .{ - "akiba", + .sys, + .kata, + .format, }, + .entry = "pulse.zig", } |
