mirror of
https://github.com/ziglang/zig.git
synced 2025-12-13 09:43:09 +00:00
144 lines
4.7 KiB
Zig
144 lines
4.7 KiB
Zig
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
|
|
const Walk = @import("Walk");
|
|
const Decl = Walk.Decl;
|
|
const html_render = @import("html_render");
|
|
|
|
const gpa = std.heap.wasm_allocator;
|
|
const log = std.log;
|
|
|
|
const js = struct {
|
|
extern "js" fn log(ptr: [*]const u8, len: usize) void;
|
|
extern "js" fn panic(ptr: [*]const u8, len: usize) noreturn;
|
|
};
|
|
|
|
pub const std_options: std.Options = .{
|
|
.logFn = logFn,
|
|
};
|
|
|
|
pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noreturn {
|
|
_ = st;
|
|
_ = addr;
|
|
log.err("panic: {s}", .{msg});
|
|
@trap();
|
|
}
|
|
|
|
fn logFn(
|
|
comptime message_level: log.Level,
|
|
comptime scope: @TypeOf(.enum_literal),
|
|
comptime format: []const u8,
|
|
args: anytype,
|
|
) void {
|
|
const level_txt = comptime message_level.asText();
|
|
const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
|
|
var buf: [500]u8 = undefined;
|
|
const line = std.fmt.bufPrint(&buf, level_txt ++ prefix2 ++ format, args) catch l: {
|
|
buf[buf.len - 3 ..][0..3].* = "...".*;
|
|
break :l &buf;
|
|
};
|
|
js.log(line.ptr, line.len);
|
|
}
|
|
|
|
export fn alloc(n: usize) [*]u8 {
|
|
const slice = gpa.alloc(u8, n) catch @panic("OOM");
|
|
return slice.ptr;
|
|
}
|
|
|
|
export fn unpack(tar_ptr: [*]u8, tar_len: usize) void {
|
|
const tar_bytes = tar_ptr[0..tar_len];
|
|
log.debug("received {d} bytes of tar file", .{tar_bytes.len});
|
|
|
|
unpackInner(tar_bytes) catch |err| {
|
|
fatal("unable to unpack tar: {s}", .{@errorName(err)});
|
|
};
|
|
}
|
|
|
|
/// Set by `set_input_string`.
|
|
var input_string: std.ArrayListUnmanaged(u8) = .{};
|
|
var string_result: std.ArrayListUnmanaged(u8) = .{};
|
|
|
|
export fn set_input_string(len: usize) [*]u8 {
|
|
input_string.resize(gpa, len) catch @panic("OOM");
|
|
return input_string.items.ptr;
|
|
}
|
|
|
|
/// Looks up the root struct decl corresponding to a file by path.
|
|
/// Uses `input_string`.
|
|
export fn find_file_root() Decl.Index {
|
|
const file: Walk.File.Index = @enumFromInt(Walk.files.getIndex(input_string.items) orelse return .none);
|
|
return file.findRootDecl();
|
|
}
|
|
|
|
export fn decl_source_html(decl_index: Decl.Index) String {
|
|
const decl = decl_index.get();
|
|
|
|
string_result.clearRetainingCapacity();
|
|
html_render.fileSourceHtml(decl.file, &string_result, decl.ast_node, .{}) catch |err| {
|
|
fatal("unable to render source: {s}", .{@errorName(err)});
|
|
};
|
|
return String.init(string_result.items);
|
|
}
|
|
|
|
const String = Slice(u8);
|
|
|
|
fn Slice(T: type) type {
|
|
return packed struct(u64) {
|
|
ptr: u32,
|
|
len: u32,
|
|
|
|
fn init(s: []const T) @This() {
|
|
return .{
|
|
.ptr = @intFromPtr(s.ptr),
|
|
.len = s.len,
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
fn unpackInner(tar_bytes: []u8) !void {
|
|
var fbs = std.io.fixedBufferStream(tar_bytes);
|
|
var file_name_buffer: [1024]u8 = undefined;
|
|
var link_name_buffer: [1024]u8 = undefined;
|
|
var it = std.tar.iterator(fbs.reader(), .{
|
|
.file_name_buffer = &file_name_buffer,
|
|
.link_name_buffer = &link_name_buffer,
|
|
});
|
|
while (try it.next()) |tar_file| {
|
|
switch (tar_file.kind) {
|
|
.file => {
|
|
if (tar_file.size == 0 and tar_file.name.len == 0) break;
|
|
if (std.mem.endsWith(u8, tar_file.name, ".zig")) {
|
|
log.debug("found file: '{s}'", .{tar_file.name});
|
|
const file_name = try gpa.dupe(u8, tar_file.name);
|
|
if (std.mem.indexOfScalar(u8, file_name, '/')) |pkg_name_end| {
|
|
const pkg_name = file_name[0..pkg_name_end];
|
|
const gop = try Walk.modules.getOrPut(gpa, pkg_name);
|
|
const file: Walk.File.Index = @enumFromInt(Walk.files.entries.len);
|
|
if (!gop.found_existing or
|
|
std.mem.eql(u8, file_name[pkg_name_end..], "/root.zig") or
|
|
std.mem.eql(u8, file_name[pkg_name_end + 1 .. file_name.len - ".zig".len], pkg_name))
|
|
{
|
|
gop.value_ptr.* = file;
|
|
}
|
|
const file_bytes = tar_bytes[fbs.pos..][0..@intCast(tar_file.size)];
|
|
assert(file == try Walk.add_file(file_name, file_bytes));
|
|
}
|
|
} else {
|
|
log.warn("skipping: '{s}' - the tar creation should have done that", .{tar_file.name});
|
|
}
|
|
},
|
|
else => continue,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn fatal(comptime format: []const u8, args: anytype) noreturn {
|
|
var buf: [500]u8 = undefined;
|
|
const line = std.fmt.bufPrint(&buf, format, args) catch l: {
|
|
buf[buf.len - 3 ..][0..3].* = "...".*;
|
|
break :l &buf;
|
|
};
|
|
js.panic(line.ptr, line.len);
|
|
}
|