Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

writeCoff

cvtres.writeCoff
pub fn writeCoff(
    allocator: Allocator,
    writer: *std.Io.Writer,
    resources: []const Resource,
    options: CoffOptions,
    diagnostics: ?*Diagnostics,
) !void

File

Code

pub fn writeCoff(
    allocator: Allocator,
    writer: *std.Io.Writer,
    resources: []const Resource,
    options: CoffOptions,
    diagnostics: ?*Diagnostics,
) !void {
    var resource_tree = ResourceTree.init(allocator, options);
    defer resource_tree.deinit();

    for (resources, 0..) |*resource, i| {
        resource_tree.put(resource, i) catch |err| {
            switch (err) {
                error.DuplicateResource => {
                    if (diagnostics) |d_ptr| d_ptr.* = .{ .duplicate_resource = i };
                },
                error.ResourceDataTooLong, error.TotalResourceDataTooLong => {
                    if (diagnostics) |d_ptr| d_ptr.* = .{ .overflow_resource = i };
                },
                else => {},
            }
            return err;
        };
    }

    const lengths = resource_tree.dataLengths();
    const byte_size_of_relocation = 10;
    const relocations_len: u32 = @intCast(byte_size_of_relocation * resources.len);
    const pointer_to_rsrc01_data = @sizeOf(std.coff.Header) + (@sizeOf(std.coff.SectionHeader) * 2);
    const pointer_to_relocations = pointer_to_rsrc01_data + lengths.rsrc01;
    const pointer_to_rsrc02_data = pointer_to_relocations + relocations_len;
    const pointer_to_symbol_table = pointer_to_rsrc02_data + lengths.rsrc02;

    const timestamp: i64 = options.timestamp;
    const size_of_optional_header = 0;
    const machine_type: std.coff.IMAGE.FILE.MACHINE = options.target;
    const flags = std.coff.Header.Flags{
        .@"32BIT_MACHINE" = true,
    };
    const number_of_symbols = 5 + @as(u32, @intCast(resources.len)) + @intFromBool(options.define_external_symbol != null);
    const coff_header = std.coff.Header{
        .machine = machine_type,
        .number_of_sections = 2,
        .time_date_stamp = @as(u32, @truncate(@as(u64, @bitCast(timestamp)))),
        .pointer_to_symbol_table = pointer_to_symbol_table,
        .number_of_symbols = number_of_symbols,
        .size_of_optional_header = size_of_optional_header,
        .flags = flags,
    };

    try writer.writeStruct(coff_header, .little);

    const rsrc01_header = std.coff.SectionHeader{
        .name = ".rsrc$01".*,
        .virtual_size = 0,
        .virtual_address = 0,
        .size_of_raw_data = lengths.rsrc01,
        .pointer_to_raw_data = pointer_to_rsrc01_data,
        .pointer_to_relocations = if (relocations_len != 0) pointer_to_relocations else 0,
        .pointer_to_linenumbers = 0,
        .number_of_relocations = @intCast(resources.len),
        .number_of_linenumbers = 0,
        .flags = .{
            .CNT_INITIALIZED_DATA = true,
            .MEM_WRITE = !options.read_only,
            .MEM_READ = true,
        },
    };
    try writer.writeStruct(rsrc01_header, .little);

    const rsrc02_header = std.coff.SectionHeader{
        .name = ".rsrc$02".*,
        .virtual_size = 0,
        .virtual_address = 0,
        .size_of_raw_data = lengths.rsrc02,
        .pointer_to_raw_data = pointer_to_rsrc02_data,
        .pointer_to_relocations = 0,
        .pointer_to_linenumbers = 0,
        .number_of_relocations = 0,
        .number_of_linenumbers = 0,
        .flags = .{
            .CNT_INITIALIZED_DATA = true,
            .MEM_WRITE = !options.read_only,
            .MEM_READ = true,
        },
    };
    try writer.writeStruct(rsrc02_header, .little);

    // TODO: test surrogate pairs
    try resource_tree.sort();

    var string_table = StringTable{};
    defer string_table.deinit(allocator);
    const resource_symbols = try resource_tree.writeCoff(
        allocator,
        writer,
        resources,
        lengths,
        &string_table,
    );
    defer allocator.free(resource_symbols);

    try writeSymbol(writer, .{
        .name = "@feat.00".*,
        .value = 0x11,
        .section_number = .ABSOLUTE,
        .type = .{
            .base_type = .NULL,
            .complex_type = .NULL,
        },
        .storage_class = .STATIC,
        .number_of_aux_symbols = 0,
    });

    try writeSymbol(writer, .{
        .name = ".rsrc$01".*,
        .value = 0,
        .section_number = @fromBackingInt(@intCast(1)),
        .type = .{
            .base_type = .NULL,
            .complex_type = .NULL,
        },
        .storage_class = .STATIC,
        .number_of_aux_symbols = 1,
    });
    try writeSectionDefinition(writer, .{
        .length = lengths.rsrc01,
        .number_of_relocations = @intCast(resources.len),
        .number_of_linenumbers = 0,
        .checksum = 0,
        .number = 0,
        .selection = .NONE,
        .unused = @splat(0),
    });

    try writeSymbol(writer, .{
        .name = ".rsrc$02".*,
        .value = 0,
        .section_number = @fromBackingInt(@intCast(2)),
        .type = .{
            .base_type = .NULL,
            .complex_type = .NULL,
        },
        .storage_class = .STATIC,
        .number_of_aux_symbols = 1,
    });
    try writeSectionDefinition(writer, .{
        .length = lengths.rsrc02,
        .number_of_relocations = 0,
        .number_of_linenumbers = 0,
        .checksum = 0,
        .number = 0,
        .selection = .NONE,
        .unused = @splat(0),
    });

    for (resource_symbols) |resource_symbol| {
        try writeSymbol(writer, resource_symbol);
    }

    if (options.define_external_symbol) |external_symbol_name| {
        const name_bytes: [8]u8 = name_bytes: {
            if (external_symbol_name.len > 8) {
                const string_table_offset: u32 = try string_table.put(allocator, external_symbol_name);
                var bytes: [8]u8 = @splat(0);
                std.mem.writeInt(u32, bytes[4..8], string_table_offset, .little);
                break :name_bytes bytes;
            } else {
                var symbol_shortname: [8]u8 = @splat(0);
                @memcpy(symbol_shortname[0..external_symbol_name.len], external_symbol_name);
                break :name_bytes symbol_shortname;
            }
        };

        try writeSymbol(writer, .{
            .name = name_bytes,
            .value = 0,
            .section_number = .ABSOLUTE,
            .type = .{
                .base_type = .NULL,
                .complex_type = .NULL,
            },
            .storage_class = .EXTERNAL,
            .number_of_aux_symbols = 0,
        });
    }

    try writer.writeInt(u32, string_table.totalByteLength(), .little);
    try writer.writeAll(string_table.bytes.items);
}