| author | |
| committer | |
| log | 46b60dc06945152eee8280b8ff5b1e629ed74553 |
| tree | 8166732fc4fa0f467ba018bf0f1811f2b7d1fe31 |
| parent | 9b47dd2028deb45324ca19d909d0cee69f51f1b9 |
16 files changed, 472 insertions(+), 556 deletions(-)
lib/compiler/resinator/ani.zig+13-13| ... | @@ -16,31 +16,31 @@ const std = @import("std"); | ... | @@ -16,31 +16,31 @@ const std = @import("std"); |
| 16 | 16 | ||
| 17 | const AF_ICON: u32 = 1; | 17 | const AF_ICON: u32 = 1; |
| 18 | 18 | ||
| 19 | pub fn isAnimatedIcon(reader: anytype) bool { | 19 | pub fn isAnimatedIcon(reader: *std.Io.Reader) bool { |
| 20 | const flags = getAniheaderFlags(reader) catch return false; | 20 | const flags = getAniheaderFlags(reader) catch return false; |
| 21 | return flags & AF_ICON == AF_ICON; | 21 | return flags & AF_ICON == AF_ICON; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | fn getAniheaderFlags(reader: anytype) !u32 { | 24 | fn getAniheaderFlags(reader: *std.Io.Reader) !u32 { |
| 25 | const riff_header = try reader.readBytesNoEof(4); | 25 | const riff_header = try reader.takeArray(4); |
| 26 | if (!std.mem.eql(u8, &riff_header, "RIFF")) return error.InvalidFormat; | 26 | if (!std.mem.eql(u8, riff_header, "RIFF")) return error.InvalidFormat; |
| 27 | 27 | ||
| 28 | _ = try reader.readInt(u32, .little); // size of RIFF chunk | 28 | _ = try reader.takeInt(u32, .little); // size of RIFF chunk |
| 29 | 29 | ||
| 30 | const form_type = try reader.readBytesNoEof(4); | 30 | const form_type = try reader.takeArray(4); |
| 31 | if (!std.mem.eql(u8, &form_type, "ACON")) return error.InvalidFormat; | 31 | if (!std.mem.eql(u8, form_type, "ACON")) return error.InvalidFormat; |
| 32 | 32 | ||
| 33 | while (true) { | 33 | while (true) { |
| 34 | const chunk_id = try reader.readBytesNoEof(4); | 34 | const chunk_id = try reader.takeArray(4); |
| 35 | const chunk_len = try reader.readInt(u32, .little); | 35 | const chunk_len = try reader.takeInt(u32, .little); |
| 36 | if (!std.mem.eql(u8, &chunk_id, "anih")) { | 36 | if (!std.mem.eql(u8, chunk_id, "anih")) { |
| 37 | // TODO: Move file cursor instead of skipBytes | 37 | // TODO: Move file cursor instead of skipBytes |
| 38 | try reader.skipBytes(chunk_len, .{}); | 38 | try reader.discardAll(chunk_len); |
| 39 | continue; | 39 | continue; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | const aniheader = try reader.readStruct(ANIHEADER); | 42 | const aniheader = try reader.takeStruct(ANIHEADER, .little); |
| 43 | return std.mem.nativeToLittle(u32, aniheader.flags); | 43 | return aniheader.flags; |
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | 46 |
lib/compiler/resinator/ast.zig+40-40| ... | @@ -22,13 +22,13 @@ pub const Tree = struct { | ... | @@ -22,13 +22,13 @@ pub const Tree = struct { |
| 22 | return @alignCast(@fieldParentPtr("base", self.node)); | 22 | return @alignCast(@fieldParentPtr("base", self.node)); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | pub fn dump(self: *Tree, writer: anytype) @TypeOf(writer).Error!void { | 25 | pub fn dump(self: *Tree, writer: *std.io.Writer) !void { |
| 26 | try self.node.dump(self, writer, 0); | 26 | try self.node.dump(self, writer, 0); |
| 27 | } | 27 | } |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | pub const CodePageLookup = struct { | 30 | pub const CodePageLookup = struct { |
| 31 | lookup: std.ArrayListUnmanaged(SupportedCodePage) = .empty, | 31 | lookup: std.ArrayList(SupportedCodePage) = .empty, |
| 32 | allocator: Allocator, | 32 | allocator: Allocator, |
| 33 | default_code_page: SupportedCodePage, | 33 | default_code_page: SupportedCodePage, |
| 34 | 34 | ||
| ... | @@ -726,10 +726,10 @@ pub const Node = struct { | ... | @@ -726,10 +726,10 @@ pub const Node = struct { |
| 726 | pub fn dump( | 726 | pub fn dump( |
| 727 | node: *const Node, | 727 | node: *const Node, |
| 728 | tree: *const Tree, | 728 | tree: *const Tree, |
| 729 | writer: anytype, | 729 | writer: *std.io.Writer, |
| 730 | indent: usize, | 730 | indent: usize, |
| 731 | ) @TypeOf(writer).Error!void { | 731 | ) std.io.Writer.Error!void { |
| 732 | try writer.writeByteNTimes(' ', indent); | 732 | try writer.splatByteAll(' ', indent); |
| 733 | try writer.writeAll(@tagName(node.id)); | 733 | try writer.writeAll(@tagName(node.id)); |
| 734 | switch (node.id) { | 734 | switch (node.id) { |
| 735 | .root => { | 735 | .root => { |
| ... | @@ -768,11 +768,11 @@ pub const Node = struct { | ... | @@ -768,11 +768,11 @@ pub const Node = struct { |
| 768 | .grouped_expression => { | 768 | .grouped_expression => { |
| 769 | const grouped: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node)); | 769 | const grouped: *const Node.GroupedExpression = @alignCast(@fieldParentPtr("base", node)); |
| 770 | try writer.writeAll("\n"); | 770 | try writer.writeAll("\n"); |
| 771 | try writer.writeByteNTimes(' ', indent); | 771 | try writer.splatByteAll(' ', indent); |
| 772 | try writer.writeAll(grouped.open_token.slice(tree.source)); | 772 | try writer.writeAll(grouped.open_token.slice(tree.source)); |
| 773 | try writer.writeAll("\n"); | 773 | try writer.writeAll("\n"); |
| 774 | try grouped.expression.dump(tree, writer, indent + 1); | 774 | try grouped.expression.dump(tree, writer, indent + 1); |
| 775 | try writer.writeByteNTimes(' ', indent); | 775 | try writer.splatByteAll(' ', indent); |
| 776 | try writer.writeAll(grouped.close_token.slice(tree.source)); | 776 | try writer.writeAll(grouped.close_token.slice(tree.source)); |
| 777 | try writer.writeAll("\n"); | 777 | try writer.writeAll("\n"); |
| 778 | }, | 778 | }, |
| ... | @@ -790,13 +790,13 @@ pub const Node = struct { | ... | @@ -790,13 +790,13 @@ pub const Node = struct { |
| 790 | for (accelerators.optional_statements) |statement| { | 790 | for (accelerators.optional_statements) |statement| { |
| 791 | try statement.dump(tree, writer, indent + 1); | 791 | try statement.dump(tree, writer, indent + 1); |
| 792 | } | 792 | } |
| 793 | try writer.writeByteNTimes(' ', indent); | 793 | try writer.splatByteAll(' ', indent); |
| 794 | try writer.writeAll(accelerators.begin_token.slice(tree.source)); | 794 | try writer.writeAll(accelerators.begin_token.slice(tree.source)); |
| 795 | try writer.writeAll("\n"); | 795 | try writer.writeAll("\n"); |
| 796 | for (accelerators.accelerators) |accelerator| { | 796 | for (accelerators.accelerators) |accelerator| { |
| 797 | try accelerator.dump(tree, writer, indent + 1); | 797 | try accelerator.dump(tree, writer, indent + 1); |
| 798 | } | 798 | } |
| 799 | try writer.writeByteNTimes(' ', indent); | 799 | try writer.splatByteAll(' ', indent); |
| 800 | try writer.writeAll(accelerators.end_token.slice(tree.source)); | 800 | try writer.writeAll(accelerators.end_token.slice(tree.source)); |
| 801 | try writer.writeAll("\n"); | 801 | try writer.writeAll("\n"); |
| 802 | }, | 802 | }, |
| ... | @@ -815,25 +815,25 @@ pub const Node = struct { | ... | @@ -815,25 +815,25 @@ pub const Node = struct { |
| 815 | const dialog: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node)); | 815 | const dialog: *const Node.Dialog = @alignCast(@fieldParentPtr("base", node)); |
| 816 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ dialog.id.slice(tree.source), dialog.type.slice(tree.source), dialog.common_resource_attributes.len }); | 816 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ dialog.id.slice(tree.source), dialog.type.slice(tree.source), dialog.common_resource_attributes.len }); |
| 817 | inline for (.{ "x", "y", "width", "height" }) |arg| { | 817 | inline for (.{ "x", "y", "width", "height" }) |arg| { |
| 818 | try writer.writeByteNTimes(' ', indent + 1); | 818 | try writer.splatByteAll(' ', indent + 1); |
| 819 | try writer.writeAll(arg ++ ":\n"); | 819 | try writer.writeAll(arg ++ ":\n"); |
| 820 | try @field(dialog, arg).dump(tree, writer, indent + 2); | 820 | try @field(dialog, arg).dump(tree, writer, indent + 2); |
| 821 | } | 821 | } |
| 822 | if (dialog.help_id) |help_id| { | 822 | if (dialog.help_id) |help_id| { |
| 823 | try writer.writeByteNTimes(' ', indent + 1); | 823 | try writer.splatByteAll(' ', indent + 1); |
| 824 | try writer.writeAll("help_id:\n"); | 824 | try writer.writeAll("help_id:\n"); |
| 825 | try help_id.dump(tree, writer, indent + 2); | 825 | try help_id.dump(tree, writer, indent + 2); |
| 826 | } | 826 | } |
| 827 | for (dialog.optional_statements) |statement| { | 827 | for (dialog.optional_statements) |statement| { |
| 828 | try statement.dump(tree, writer, indent + 1); | 828 | try statement.dump(tree, writer, indent + 1); |
| 829 | } | 829 | } |
| 830 | try writer.writeByteNTimes(' ', indent); | 830 | try writer.splatByteAll(' ', indent); |
| 831 | try writer.writeAll(dialog.begin_token.slice(tree.source)); | 831 | try writer.writeAll(dialog.begin_token.slice(tree.source)); |
| 832 | try writer.writeAll("\n"); | 832 | try writer.writeAll("\n"); |
| 833 | for (dialog.controls) |control| { | 833 | for (dialog.controls) |control| { |
| 834 | try control.dump(tree, writer, indent + 1); | 834 | try control.dump(tree, writer, indent + 1); |
| 835 | } | 835 | } |
| 836 | try writer.writeByteNTimes(' ', indent); | 836 | try writer.splatByteAll(' ', indent); |
| 837 | try writer.writeAll(dialog.end_token.slice(tree.source)); | 837 | try writer.writeAll(dialog.end_token.slice(tree.source)); |
| 838 | try writer.writeAll("\n"); | 838 | try writer.writeAll("\n"); |
| 839 | }, | 839 | }, |
| ... | @@ -845,30 +845,30 @@ pub const Node = struct { | ... | @@ -845,30 +845,30 @@ pub const Node = struct { |
| 845 | } | 845 | } |
| 846 | try writer.writeByte('\n'); | 846 | try writer.writeByte('\n'); |
| 847 | if (control.class) |class| { | 847 | if (control.class) |class| { |
| 848 | try writer.writeByteNTimes(' ', indent + 1); | 848 | try writer.splatByteAll(' ', indent + 1); |
| 849 | try writer.writeAll("class:\n"); | 849 | try writer.writeAll("class:\n"); |
| 850 | try class.dump(tree, writer, indent + 2); | 850 | try class.dump(tree, writer, indent + 2); |
| 851 | } | 851 | } |
| 852 | inline for (.{ "id", "x", "y", "width", "height" }) |arg| { | 852 | inline for (.{ "id", "x", "y", "width", "height" }) |arg| { |
| 853 | try writer.writeByteNTimes(' ', indent + 1); | 853 | try writer.splatByteAll(' ', indent + 1); |
| 854 | try writer.writeAll(arg ++ ":\n"); | 854 | try writer.writeAll(arg ++ ":\n"); |
| 855 | try @field(control, arg).dump(tree, writer, indent + 2); | 855 | try @field(control, arg).dump(tree, writer, indent + 2); |
| 856 | } | 856 | } |
| 857 | inline for (.{ "style", "exstyle", "help_id" }) |arg| { | 857 | inline for (.{ "style", "exstyle", "help_id" }) |arg| { |
| 858 | if (@field(control, arg)) |val_node| { | 858 | if (@field(control, arg)) |val_node| { |
| 859 | try writer.writeByteNTimes(' ', indent + 1); | 859 | try writer.splatByteAll(' ', indent + 1); |
| 860 | try writer.writeAll(arg ++ ":\n"); | 860 | try writer.writeAll(arg ++ ":\n"); |
| 861 | try val_node.dump(tree, writer, indent + 2); | 861 | try val_node.dump(tree, writer, indent + 2); |
| 862 | } | 862 | } |
| 863 | } | 863 | } |
| 864 | if (control.extra_data_begin != null) { | 864 | if (control.extra_data_begin != null) { |
| 865 | try writer.writeByteNTimes(' ', indent); | 865 | try writer.splatByteAll(' ', indent); |
| 866 | try writer.writeAll(control.extra_data_begin.?.slice(tree.source)); | 866 | try writer.writeAll(control.extra_data_begin.?.slice(tree.source)); |
| 867 | try writer.writeAll("\n"); | 867 | try writer.writeAll("\n"); |
| 868 | for (control.extra_data) |data_node| { | 868 | for (control.extra_data) |data_node| { |
| 869 | try data_node.dump(tree, writer, indent + 1); | 869 | try data_node.dump(tree, writer, indent + 1); |
| 870 | } | 870 | } |
| 871 | try writer.writeByteNTimes(' ', indent); | 871 | try writer.splatByteAll(' ', indent); |
| 872 | try writer.writeAll(control.extra_data_end.?.slice(tree.source)); | 872 | try writer.writeAll(control.extra_data_end.?.slice(tree.source)); |
| 873 | try writer.writeAll("\n"); | 873 | try writer.writeAll("\n"); |
| 874 | } | 874 | } |
| ... | @@ -877,17 +877,17 @@ pub const Node = struct { | ... | @@ -877,17 +877,17 @@ pub const Node = struct { |
| 877 | const toolbar: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node)); | 877 | const toolbar: *const Node.Toolbar = @alignCast(@fieldParentPtr("base", node)); |
| 878 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ toolbar.id.slice(tree.source), toolbar.type.slice(tree.source), toolbar.common_resource_attributes.len }); | 878 | try writer.print(" {s} {s} [{d} common_resource_attributes]\n", .{ toolbar.id.slice(tree.source), toolbar.type.slice(tree.source), toolbar.common_resource_attributes.len }); |
| 879 | inline for (.{ "button_width", "button_height" }) |arg| { | 879 | inline for (.{ "button_width", "button_height" }) |arg| { |
| 880 | try writer.writeByteNTimes(' ', indent + 1); | 880 | try writer.splatByteAll(' ', indent + 1); |
| 881 | try writer.writeAll(arg ++ ":\n"); | 881 | try writer.writeAll(arg ++ ":\n"); |
| 882 | try @field(toolbar, arg).dump(tree, writer, indent + 2); | 882 | try @field(toolbar, arg).dump(tree, writer, indent + 2); |
| 883 | } | 883 | } |
| 884 | try writer.writeByteNTimes(' ', indent); | 884 | try writer.splatByteAll(' ', indent); |
| 885 | try writer.writeAll(toolbar.begin_token.slice(tree.source)); | 885 | try writer.writeAll(toolbar.begin_token.slice(tree.source)); |
| 886 | try writer.writeAll("\n"); | 886 | try writer.writeAll("\n"); |
| 887 | for (toolbar.buttons) |button_or_sep| { | 887 | for (toolbar.buttons) |button_or_sep| { |
| 888 | try button_or_sep.dump(tree, writer, indent + 1); | 888 | try button_or_sep.dump(tree, writer, indent + 1); |
| 889 | } | 889 | } |
| 890 | try writer.writeByteNTimes(' ', indent); | 890 | try writer.splatByteAll(' ', indent); |
| 891 | try writer.writeAll(toolbar.end_token.slice(tree.source)); | 891 | try writer.writeAll(toolbar.end_token.slice(tree.source)); |
| 892 | try writer.writeAll("\n"); | 892 | try writer.writeAll("\n"); |
| 893 | }, | 893 | }, |
| ... | @@ -898,17 +898,17 @@ pub const Node = struct { | ... | @@ -898,17 +898,17 @@ pub const Node = struct { |
| 898 | try statement.dump(tree, writer, indent + 1); | 898 | try statement.dump(tree, writer, indent + 1); |
| 899 | } | 899 | } |
| 900 | if (menu.help_id) |help_id| { | 900 | if (menu.help_id) |help_id| { |
| 901 | try writer.writeByteNTimes(' ', indent + 1); | 901 | try writer.splatByteAll(' ', indent + 1); |
| 902 | try writer.writeAll("help_id:\n"); | 902 | try writer.writeAll("help_id:\n"); |
| 903 | try help_id.dump(tree, writer, indent + 2); | 903 | try help_id.dump(tree, writer, indent + 2); |
| 904 | } | 904 | } |
| 905 | try writer.writeByteNTimes(' ', indent); | 905 | try writer.splatByteAll(' ', indent); |
| 906 | try writer.writeAll(menu.begin_token.slice(tree.source)); | 906 | try writer.writeAll(menu.begin_token.slice(tree.source)); |
| 907 | try writer.writeAll("\n"); | 907 | try writer.writeAll("\n"); |
| 908 | for (menu.items) |item| { | 908 | for (menu.items) |item| { |
| 909 | try item.dump(tree, writer, indent + 1); | 909 | try item.dump(tree, writer, indent + 1); |
| 910 | } | 910 | } |
| 911 | try writer.writeByteNTimes(' ', indent); | 911 | try writer.splatByteAll(' ', indent); |
| 912 | try writer.writeAll(menu.end_token.slice(tree.source)); | 912 | try writer.writeAll(menu.end_token.slice(tree.source)); |
| 913 | try writer.writeAll("\n"); | 913 | try writer.writeAll("\n"); |
| 914 | }, | 914 | }, |
| ... | @@ -926,7 +926,7 @@ pub const Node = struct { | ... | @@ -926,7 +926,7 @@ pub const Node = struct { |
| 926 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source) }); | 926 | try writer.print(" {s} {s}\n", .{ menu_item.menuitem.slice(tree.source), menu_item.text.slice(tree.source) }); |
| 927 | inline for (.{ "id", "type", "state" }) |arg| { | 927 | inline for (.{ "id", "type", "state" }) |arg| { |
| 928 | if (@field(menu_item, arg)) |val_node| { | 928 | if (@field(menu_item, arg)) |val_node| { |
| 929 | try writer.writeByteNTimes(' ', indent + 1); | 929 | try writer.splatByteAll(' ', indent + 1); |
| 930 | try writer.writeAll(arg ++ ":\n"); | 930 | try writer.writeAll(arg ++ ":\n"); |
| 931 | try val_node.dump(tree, writer, indent + 2); | 931 | try val_node.dump(tree, writer, indent + 2); |
| 932 | } | 932 | } |
| ... | @@ -935,13 +935,13 @@ pub const Node = struct { | ... | @@ -935,13 +935,13 @@ pub const Node = struct { |
| 935 | .popup => { | 935 | .popup => { |
| 936 | const popup: *const Node.Popup = @alignCast(@fieldParentPtr("base", node)); | 936 | const popup: *const Node.Popup = @alignCast(@fieldParentPtr("base", node)); |
| 937 | try writer.print(" {s} {s} [{d} options]\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source), popup.option_list.len }); | 937 | try writer.print(" {s} {s} [{d} options]\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source), popup.option_list.len }); |
| 938 | try writer.writeByteNTimes(' ', indent); | 938 | try writer.splatByteAll(' ', indent); |
| 939 | try writer.writeAll(popup.begin_token.slice(tree.source)); | 939 | try writer.writeAll(popup.begin_token.slice(tree.source)); |
| 940 | try writer.writeAll("\n"); | 940 | try writer.writeAll("\n"); |
| 941 | for (popup.items) |item| { | 941 | for (popup.items) |item| { |
| 942 | try item.dump(tree, writer, indent + 1); | 942 | try item.dump(tree, writer, indent + 1); |
| 943 | } | 943 | } |
| 944 | try writer.writeByteNTimes(' ', indent); | 944 | try writer.splatByteAll(' ', indent); |
| 945 | try writer.writeAll(popup.end_token.slice(tree.source)); | 945 | try writer.writeAll(popup.end_token.slice(tree.source)); |
| 946 | try writer.writeAll("\n"); | 946 | try writer.writeAll("\n"); |
| 947 | }, | 947 | }, |
| ... | @@ -950,18 +950,18 @@ pub const Node = struct { | ... | @@ -950,18 +950,18 @@ pub const Node = struct { |
| 950 | try writer.print(" {s} {s}\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source) }); | 950 | try writer.print(" {s} {s}\n", .{ popup.popup.slice(tree.source), popup.text.slice(tree.source) }); |
| 951 | inline for (.{ "id", "type", "state", "help_id" }) |arg| { | 951 | inline for (.{ "id", "type", "state", "help_id" }) |arg| { |
| 952 | if (@field(popup, arg)) |val_node| { | 952 | if (@field(popup, arg)) |val_node| { |
| 953 | try writer.writeByteNTimes(' ', indent + 1); | 953 | try writer.splatByteAll(' ', indent + 1); |
| 954 | try writer.writeAll(arg ++ ":\n"); | 954 | try writer.writeAll(arg ++ ":\n"); |
| 955 | try val_node.dump(tree, writer, indent + 2); | 955 | try val_node.dump(tree, writer, indent + 2); |
| 956 | } | 956 | } |
| 957 | } | 957 | } |
| 958 | try writer.writeByteNTimes(' ', indent); | 958 | try writer.splatByteAll(' ', indent); |
| 959 | try writer.writeAll(popup.begin_token.slice(tree.source)); | 959 | try writer.writeAll(popup.begin_token.slice(tree.source)); |
| 960 | try writer.writeAll("\n"); | 960 | try writer.writeAll("\n"); |
| 961 | for (popup.items) |item| { | 961 | for (popup.items) |item| { |
| 962 | try item.dump(tree, writer, indent + 1); | 962 | try item.dump(tree, writer, indent + 1); |
| 963 | } | 963 | } |
| 964 | try writer.writeByteNTimes(' ', indent); | 964 | try writer.splatByteAll(' ', indent); |
| 965 | try writer.writeAll(popup.end_token.slice(tree.source)); | 965 | try writer.writeAll(popup.end_token.slice(tree.source)); |
| 966 | try writer.writeAll("\n"); | 966 | try writer.writeAll("\n"); |
| 967 | }, | 967 | }, |
| ... | @@ -971,13 +971,13 @@ pub const Node = struct { | ... | @@ -971,13 +971,13 @@ pub const Node = struct { |
| 971 | for (version_info.fixed_info) |fixed_info| { | 971 | for (version_info.fixed_info) |fixed_info| { |
| 972 | try fixed_info.dump(tree, writer, indent + 1); | 972 | try fixed_info.dump(tree, writer, indent + 1); |
| 973 | } | 973 | } |
| 974 | try writer.writeByteNTimes(' ', indent); | 974 | try writer.splatByteAll(' ', indent); |
| 975 | try writer.writeAll(version_info.begin_token.slice(tree.source)); | 975 | try writer.writeAll(version_info.begin_token.slice(tree.source)); |
| 976 | try writer.writeAll("\n"); | 976 | try writer.writeAll("\n"); |
| 977 | for (version_info.block_statements) |block| { | 977 | for (version_info.block_statements) |block| { |
| 978 | try block.dump(tree, writer, indent + 1); | 978 | try block.dump(tree, writer, indent + 1); |
| 979 | } | 979 | } |
| 980 | try writer.writeByteNTimes(' ', indent); | 980 | try writer.splatByteAll(' ', indent); |
| 981 | try writer.writeAll(version_info.end_token.slice(tree.source)); | 981 | try writer.writeAll(version_info.end_token.slice(tree.source)); |
| 982 | try writer.writeAll("\n"); | 982 | try writer.writeAll("\n"); |
| 983 | }, | 983 | }, |
| ... | @@ -994,13 +994,13 @@ pub const Node = struct { | ... | @@ -994,13 +994,13 @@ pub const Node = struct { |
| 994 | for (block.values) |value| { | 994 | for (block.values) |value| { |
| 995 | try value.dump(tree, writer, indent + 1); | 995 | try value.dump(tree, writer, indent + 1); |
| 996 | } | 996 | } |
| 997 | try writer.writeByteNTimes(' ', indent); | 997 | try writer.splatByteAll(' ', indent); |
| 998 | try writer.writeAll(block.begin_token.slice(tree.source)); | 998 | try writer.writeAll(block.begin_token.slice(tree.source)); |
| 999 | try writer.writeAll("\n"); | 999 | try writer.writeAll("\n"); |
| 1000 | for (block.children) |child| { | 1000 | for (block.children) |child| { |
| 1001 | try child.dump(tree, writer, indent + 1); | 1001 | try child.dump(tree, writer, indent + 1); |
| 1002 | } | 1002 | } |
| 1003 | try writer.writeByteNTimes(' ', indent); | 1003 | try writer.splatByteAll(' ', indent); |
| 1004 | try writer.writeAll(block.end_token.slice(tree.source)); | 1004 | try writer.writeAll(block.end_token.slice(tree.source)); |
| 1005 | try writer.writeAll("\n"); | 1005 | try writer.writeAll("\n"); |
| 1006 | }, | 1006 | }, |
| ... | @@ -1025,13 +1025,13 @@ pub const Node = struct { | ... | @@ -1025,13 +1025,13 @@ pub const Node = struct { |
| 1025 | for (string_table.optional_statements) |statement| { | 1025 | for (string_table.optional_statements) |statement| { |
| 1026 | try statement.dump(tree, writer, indent + 1); | 1026 | try statement.dump(tree, writer, indent + 1); |
| 1027 | } | 1027 | } |
| 1028 | try writer.writeByteNTimes(' ', indent); | 1028 | try writer.splatByteAll(' ', indent); |
| 1029 | try writer.writeAll(string_table.begin_token.slice(tree.source)); | 1029 | try writer.writeAll(string_table.begin_token.slice(tree.source)); |
| 1030 | try writer.writeAll("\n"); | 1030 | try writer.writeAll("\n"); |
| 1031 | for (string_table.strings) |string| { | 1031 | for (string_table.strings) |string| { |
| 1032 | try string.dump(tree, writer, indent + 1); | 1032 | try string.dump(tree, writer, indent + 1); |
| 1033 | } | 1033 | } |
| 1034 | try writer.writeByteNTimes(' ', indent); | 1034 | try writer.splatByteAll(' ', indent); |
| 1035 | try writer.writeAll(string_table.end_token.slice(tree.source)); | 1035 | try writer.writeAll(string_table.end_token.slice(tree.source)); |
| 1036 | try writer.writeAll("\n"); | 1036 | try writer.writeAll("\n"); |
| 1037 | }, | 1037 | }, |
| ... | @@ -1039,7 +1039,7 @@ pub const Node = struct { | ... | @@ -1039,7 +1039,7 @@ pub const Node = struct { |
| 1039 | try writer.writeAll("\n"); | 1039 | try writer.writeAll("\n"); |
| 1040 | const string: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node)); | 1040 | const string: *const Node.StringTableString = @alignCast(@fieldParentPtr("base", node)); |
| 1041 | try string.id.dump(tree, writer, indent + 1); | 1041 | try string.id.dump(tree, writer, indent + 1); |
| 1042 | try writer.writeByteNTimes(' ', indent + 1); | 1042 | try writer.splatByteAll(' ', indent + 1); |
| 1043 | try writer.print("{s}\n", .{string.string.slice(tree.source)}); | 1043 | try writer.print("{s}\n", .{string.string.slice(tree.source)}); |
| 1044 | }, | 1044 | }, |
| 1045 | .language_statement => { | 1045 | .language_statement => { |
| ... | @@ -1051,12 +1051,12 @@ pub const Node = struct { | ... | @@ -1051,12 +1051,12 @@ pub const Node = struct { |
| 1051 | .font_statement => { | 1051 | .font_statement => { |
| 1052 | const font: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node)); | 1052 | const font: *const Node.FontStatement = @alignCast(@fieldParentPtr("base", node)); |
| 1053 | try writer.print(" {s} typeface: {s}\n", .{ font.identifier.slice(tree.source), font.typeface.slice(tree.source) }); | 1053 | try writer.print(" {s} typeface: {s}\n", .{ font.identifier.slice(tree.source), font.typeface.slice(tree.source) }); |
| 1054 | try writer.writeByteNTimes(' ', indent + 1); | 1054 | try writer.splatByteAll(' ', indent + 1); |
| 1055 | try writer.writeAll("point_size:\n"); | 1055 | try writer.writeAll("point_size:\n"); |
| 1056 | try font.point_size.dump(tree, writer, indent + 2); | 1056 | try font.point_size.dump(tree, writer, indent + 2); |
| 1057 | inline for (.{ "weight", "italic", "char_set" }) |arg| { | 1057 | inline for (.{ "weight", "italic", "char_set" }) |arg| { |
| 1058 | if (@field(font, arg)) |arg_node| { | 1058 | if (@field(font, arg)) |arg_node| { |
| 1059 | try writer.writeByteNTimes(' ', indent + 1); | 1059 | try writer.splatByteAll(' ', indent + 1); |
| 1060 | try writer.writeAll(arg ++ ":\n"); | 1060 | try writer.writeAll(arg ++ ":\n"); |
| 1061 | try arg_node.dump(tree, writer, indent + 2); | 1061 | try arg_node.dump(tree, writer, indent + 2); |
| 1062 | } | 1062 | } |
| ... | @@ -1071,7 +1071,7 @@ pub const Node = struct { | ... | @@ -1071,7 +1071,7 @@ pub const Node = struct { |
| 1071 | const invalid: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node)); | 1071 | const invalid: *const Node.Invalid = @alignCast(@fieldParentPtr("base", node)); |
| 1072 | try writer.print(" context.len: {}\n", .{invalid.context.len}); | 1072 | try writer.print(" context.len: {}\n", .{invalid.context.len}); |
| 1073 | for (invalid.context) |context_token| { | 1073 | for (invalid.context) |context_token| { |
| 1074 | try writer.writeByteNTimes(' ', indent + 1); | 1074 | try writer.splatByteAll(' ', indent + 1); |
| 1075 | try writer.print("{s}:{s}", .{ @tagName(context_token.id), context_token.slice(tree.source) }); | 1075 | try writer.print("{s}:{s}", .{ @tagName(context_token.id), context_token.slice(tree.source) }); |
| 1076 | try writer.writeByte('\n'); | 1076 | try writer.writeByte('\n'); |
| 1077 | } | 1077 | } |
lib/compiler/resinator/bmp.zig+25-15| ... | @@ -27,6 +27,7 @@ pub const windows_format_id = std.mem.readInt(u16, "BM", native_endian); | ... | @@ -27,6 +27,7 @@ pub const windows_format_id = std.mem.readInt(u16, "BM", native_endian); |
| 27 | pub const file_header_len = 14; | 27 | pub const file_header_len = 14; |
| 28 | 28 | ||
| 29 | pub const ReadError = error{ | 29 | pub const ReadError = error{ |
| 30 | ReadFailed, | ||
| 30 | UnexpectedEOF, | 31 | UnexpectedEOF, |
| 31 | InvalidFileHeader, | 32 | InvalidFileHeader, |
| 32 | ImpossiblePixelDataOffset, | 33 | ImpossiblePixelDataOffset, |
| ... | @@ -94,9 +95,12 @@ pub const BitmapInfo = struct { | ... | @@ -94,9 +95,12 @@ pub const BitmapInfo = struct { |
| 94 | } | 95 | } |
| 95 | }; | 96 | }; |
| 96 | 97 | ||
| 97 | pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { | 98 | pub fn read(reader: *std.Io.Reader, max_size: u64) ReadError!BitmapInfo { |
| 98 | var bitmap_info: BitmapInfo = undefined; | 99 | var bitmap_info: BitmapInfo = undefined; |
| 99 | const file_header = reader.readBytesNoEof(file_header_len) catch return error.UnexpectedEOF; | 100 | const file_header = reader.takeArray(file_header_len) catch |err| switch (err) { |
| 101 | error.EndOfStream => return error.UnexpectedEOF, | ||
| 102 | else => |e| return e, | ||
| 103 | }; | ||
| 100 | 104 | ||
| 101 | const id = std.mem.readInt(u16, file_header[0..2], native_endian); | 105 | const id = std.mem.readInt(u16, file_header[0..2], native_endian); |
| 102 | if (id != windows_format_id) return error.InvalidFileHeader; | 106 | if (id != windows_format_id) return error.InvalidFileHeader; |
| ... | @@ -104,14 +108,17 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { | ... | @@ -104,14 +108,17 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { |
| 104 | bitmap_info.pixel_data_offset = std.mem.readInt(u32, file_header[10..14], .little); | 108 | bitmap_info.pixel_data_offset = std.mem.readInt(u32, file_header[10..14], .little); |
| 105 | if (bitmap_info.pixel_data_offset > max_size) return error.ImpossiblePixelDataOffset; | 109 | if (bitmap_info.pixel_data_offset > max_size) return error.ImpossiblePixelDataOffset; |
| 106 | 110 | ||
| 107 | bitmap_info.dib_header_size = reader.readInt(u32, .little) catch return error.UnexpectedEOF; | 111 | bitmap_info.dib_header_size = reader.takeInt(u32, .little) catch return error.UnexpectedEOF; |
| 108 | if (bitmap_info.pixel_data_offset < file_header_len + bitmap_info.dib_header_size) return error.ImpossiblePixelDataOffset; | 112 | if (bitmap_info.pixel_data_offset < file_header_len + bitmap_info.dib_header_size) return error.ImpossiblePixelDataOffset; |
| 109 | const dib_version = BitmapHeader.Version.get(bitmap_info.dib_header_size); | 113 | const dib_version = BitmapHeader.Version.get(bitmap_info.dib_header_size); |
| 110 | switch (dib_version) { | 114 | switch (dib_version) { |
| 111 | .@"nt3.1", .@"nt4.0", .@"nt5.0" => { | 115 | .@"nt3.1", .@"nt4.0", .@"nt5.0" => { |
| 112 | var dib_header_buf: [@sizeOf(BITMAPINFOHEADER)]u8 align(@alignOf(BITMAPINFOHEADER)) = undefined; | 116 | var dib_header_buf: [@sizeOf(BITMAPINFOHEADER)]u8 align(@alignOf(BITMAPINFOHEADER)) = undefined; |
| 113 | std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); | 117 | std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); |
| 114 | reader.readNoEof(dib_header_buf[4..]) catch return error.UnexpectedEOF; | 118 | reader.readSliceAll(dib_header_buf[4..]) catch |err| switch (err) { |
| 119 | error.EndOfStream => return error.UnexpectedEOF, | ||
| 120 | error.ReadFailed => |e| return e, | ||
| 121 | }; | ||
| 115 | var dib_header: *BITMAPINFOHEADER = @ptrCast(&dib_header_buf); | 122 | var dib_header: *BITMAPINFOHEADER = @ptrCast(&dib_header_buf); |
| 116 | structFieldsLittleToNative(BITMAPINFOHEADER, dib_header); | 123 | structFieldsLittleToNative(BITMAPINFOHEADER, dib_header); |
| 117 | 124 | ||
| ... | @@ -126,7 +133,10 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { | ... | @@ -126,7 +133,10 @@ pub fn read(reader: anytype, max_size: u64) ReadError!BitmapInfo { |
| 126 | .@"win2.0" => { | 133 | .@"win2.0" => { |
| 127 | var dib_header_buf: [@sizeOf(BITMAPCOREHEADER)]u8 align(@alignOf(BITMAPCOREHEADER)) = undefined; | 134 | var dib_header_buf: [@sizeOf(BITMAPCOREHEADER)]u8 align(@alignOf(BITMAPCOREHEADER)) = undefined; |
| 128 | std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); | 135 | std.mem.writeInt(u32, dib_header_buf[0..4], bitmap_info.dib_header_size, .little); |
| 129 | reader.readNoEof(dib_header_buf[4..]) catch return error.UnexpectedEOF; | 136 | reader.readSliceAll(dib_header_buf[4..]) catch |err| switch (err) { |
| 137 | error.EndOfStream => return error.UnexpectedEOF, | ||
| 138 | error.ReadFailed => |e| return e, | ||
| 139 | }; | ||
| 130 | const dib_header: *BITMAPCOREHEADER = @ptrCast(&dib_header_buf); | 140 | const dib_header: *BITMAPCOREHEADER = @ptrCast(&dib_header_buf); |
| 131 | structFieldsLittleToNative(BITMAPCOREHEADER, dib_header); | 141 | structFieldsLittleToNative(BITMAPCOREHEADER, dib_header); |
| 132 | 142 | ||
| ... | @@ -238,26 +248,26 @@ fn structFieldsLittleToNative(comptime T: type, x: *T) void { | ... | @@ -238,26 +248,26 @@ fn structFieldsLittleToNative(comptime T: type, x: *T) void { |
| 238 | 248 | ||
| 239 | test "read" { | 249 | test "read" { |
| 240 | var bmp_data = "BM<\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x10\x00\x00\x00\x00\x00\x06\x00\x00\x00\x12\x0b\x00\x00\x12\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x7f\x00\x00\x00\x00".*; | 250 | var bmp_data = "BM<\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x10\x00\x00\x00\x00\x00\x06\x00\x00\x00\x12\x0b\x00\x00\x12\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x7f\x00\x00\x00\x00".*; |
| 241 | var fbs = std.io.fixedBufferStream(&bmp_data); | 251 | var fbs: std.Io.Reader = .fixed(&bmp_data); |
| 242 | 252 | ||
| 243 | { | 253 | { |
| 244 | const bitmap = try read(fbs.reader(), bmp_data.len); | 254 | const bitmap = try read(&fbs, bmp_data.len); |
| 245 | try std.testing.expectEqual(@as(u32, BitmapHeader.Version.@"nt3.1".len()), bitmap.dib_header_size); | 255 | try std.testing.expectEqual(@as(u32, BitmapHeader.Version.@"nt3.1".len()), bitmap.dib_header_size); |
| 246 | } | 256 | } |
| 247 | 257 | ||
| 248 | { | 258 | { |
| 249 | fbs.reset(); | 259 | fbs.seek = 0; |
| 250 | bmp_data[file_header_len] = 11; | 260 | bmp_data[file_header_len] = 11; |
| 251 | try std.testing.expectError(error.UnknownBitmapVersion, read(fbs.reader(), bmp_data.len)); | 261 | try std.testing.expectError(error.UnknownBitmapVersion, read(&fbs, bmp_data.len)); |
| 252 | 262 | ||
| 253 | // restore | 263 | // restore |
| 254 | bmp_data[file_header_len] = BitmapHeader.Version.@"nt3.1".len(); | 264 | bmp_data[file_header_len] = BitmapHeader.Version.@"nt3.1".len(); |
| 255 | } | 265 | } |
| 256 | 266 | ||
| 257 | { | 267 | { |
| 258 | fbs.reset(); | 268 | fbs.seek = 0; |
| 259 | bmp_data[0] = 'b'; | 269 | bmp_data[0] = 'b'; |
| 260 | try std.testing.expectError(error.InvalidFileHeader, read(fbs.reader(), bmp_data.len)); | 270 | try std.testing.expectError(error.InvalidFileHeader, read(&fbs, bmp_data.len)); |
| 261 | 271 | ||
| 262 | // restore | 272 | // restore |
| 263 | bmp_data[0] = 'B'; | 273 | bmp_data[0] = 'B'; |
| ... | @@ -265,13 +275,13 @@ test "read" { | ... | @@ -265,13 +275,13 @@ test "read" { |
| 265 | 275 | ||
| 266 | { | 276 | { |
| 267 | const cutoff_len = file_header_len + BitmapHeader.Version.@"nt3.1".len() - 1; | 277 | const cutoff_len = file_header_len + BitmapHeader.Version.@"nt3.1".len() - 1; |
| 268 | var dib_cutoff_fbs = std.io.fixedBufferStream(bmp_data[0..cutoff_len]); | 278 | var dib_cutoff_fbs: std.Io.Reader = .fixed(bmp_data[0..cutoff_len]); |
| 269 | try std.testing.expectError(error.UnexpectedEOF, read(dib_cutoff_fbs.reader(), bmp_data.len)); | 279 | try std.testing.expectError(error.UnexpectedEOF, read(&dib_cutoff_fbs, bmp_data.len)); |
| 270 | } | 280 | } |
| 271 | 281 | ||
| 272 | { | 282 | { |
| 273 | const cutoff_len = file_header_len - 1; | 283 | const cutoff_len = file_header_len - 1; |
| 274 | var bmp_cutoff_fbs = std.io.fixedBufferStream(bmp_data[0..cutoff_len]); | 284 | var bmp_cutoff_fbs: std.Io.Reader = .fixed(bmp_data[0..cutoff_len]); |
| 275 | try std.testing.expectError(error.UnexpectedEOF, read(bmp_cutoff_fbs.reader(), bmp_data.len)); | 285 | try std.testing.expectError(error.UnexpectedEOF, read(&bmp_cutoff_fbs, bmp_data.len)); |
| 276 | } | 286 | } |
| 277 | } | 287 | } |
lib/compiler/resinator/cli.zig+13-13| ... | @@ -80,20 +80,20 @@ pub const usage_string_after_command_name = | ... | @@ -80,20 +80,20 @@ pub const usage_string_after_command_name = |
| 80 | \\ | 80 | \\ |
| 81 | ; | 81 | ; |
| 82 | 82 | ||
| 83 | pub fn writeUsage(writer: anytype, command_name: []const u8) !void { | 83 | pub fn writeUsage(writer: *std.Io.Writer, command_name: []const u8) !void { |
| 84 | try writer.writeAll("Usage: "); | 84 | try writer.writeAll("Usage: "); |
| 85 | try writer.writeAll(command_name); | 85 | try writer.writeAll(command_name); |
| 86 | try writer.writeAll(usage_string_after_command_name); | 86 | try writer.writeAll(usage_string_after_command_name); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | pub const Diagnostics = struct { | 89 | pub const Diagnostics = struct { |
| 90 | errors: std.ArrayListUnmanaged(ErrorDetails) = .empty, | 90 | errors: std.ArrayList(ErrorDetails) = .empty, |
| 91 | allocator: Allocator, | 91 | allocator: Allocator, |
| 92 | 92 | ||
| 93 | pub const ErrorDetails = struct { | 93 | pub const ErrorDetails = struct { |
| 94 | arg_index: usize, | 94 | arg_index: usize, |
| 95 | arg_span: ArgSpan = .{}, | 95 | arg_span: ArgSpan = .{}, |
| 96 | msg: std.ArrayListUnmanaged(u8) = .empty, | 96 | msg: std.ArrayList(u8) = .empty, |
| 97 | type: Type = .err, | 97 | type: Type = .err, |
| 98 | print_args: bool = true, | 98 | print_args: bool = true, |
| 99 | 99 | ||
| ... | @@ -148,7 +148,7 @@ pub const Options = struct { | ... | @@ -148,7 +148,7 @@ pub const Options = struct { |
| 148 | allocator: Allocator, | 148 | allocator: Allocator, |
| 149 | input_source: IoSource = .{ .filename = &[_]u8{} }, | 149 | input_source: IoSource = .{ .filename = &[_]u8{} }, |
| 150 | output_source: IoSource = .{ .filename = &[_]u8{} }, | 150 | output_source: IoSource = .{ .filename = &[_]u8{} }, |
| 151 | extra_include_paths: std.ArrayListUnmanaged([]const u8) = .empty, | 151 | extra_include_paths: std.ArrayList([]const u8) = .empty, |
| 152 | ignore_include_env_var: bool = false, | 152 | ignore_include_env_var: bool = false, |
| 153 | preprocess: Preprocess = .yes, | 153 | preprocess: Preprocess = .yes, |
| 154 | default_language_id: ?u16 = null, | 154 | default_language_id: ?u16 = null, |
| ... | @@ -295,7 +295,7 @@ pub const Options = struct { | ... | @@ -295,7 +295,7 @@ pub const Options = struct { |
| 295 | } | 295 | } |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | pub fn dumpVerbose(self: *const Options, writer: anytype) !void { | 298 | pub fn dumpVerbose(self: *const Options, writer: *std.Io.Writer) !void { |
| 299 | const input_source_name = switch (self.input_source) { | 299 | const input_source_name = switch (self.input_source) { |
| 300 | .stdio => "<stdin>", | 300 | .stdio => "<stdin>", |
| 301 | .filename => |filename| filename, | 301 | .filename => |filename| filename, |
| ... | @@ -1230,19 +1230,19 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn | ... | @@ -1230,19 +1230,19 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn |
| 1230 | } | 1230 | } |
| 1231 | 1231 | ||
| 1232 | pub fn filepathWithExtension(allocator: Allocator, path: []const u8, ext: []const u8) ![]const u8 { | 1232 | pub fn filepathWithExtension(allocator: Allocator, path: []const u8, ext: []const u8) ![]const u8 { |
| 1233 | var buf = std.array_list.Managed(u8).init(allocator); | 1233 | var buf: std.ArrayList(u8) = .empty; |
| 1234 | errdefer buf.deinit(); | 1234 | errdefer buf.deinit(allocator); |
| 1235 | if (std.fs.path.dirname(path)) |dirname| { | 1235 | if (std.fs.path.dirname(path)) |dirname| { |
| 1236 | var end_pos = dirname.len; | 1236 | var end_pos = dirname.len; |
| 1237 | // We want to ensure that we write a path separator at the end, so if the dirname | 1237 | // We want to ensure that we write a path separator at the end, so if the dirname |
| 1238 | // doesn't end with a path sep then include the char after the dirname | 1238 | // doesn't end with a path sep then include the char after the dirname |
| 1239 | // which must be a path sep. | 1239 | // which must be a path sep. |
| 1240 | if (!std.fs.path.isSep(dirname[dirname.len - 1])) end_pos += 1; | 1240 | if (!std.fs.path.isSep(dirname[dirname.len - 1])) end_pos += 1; |
| 1241 | try buf.appendSlice(path[0..end_pos]); | 1241 | try buf.appendSlice(allocator, path[0..end_pos]); |
| 1242 | } | 1242 | } |
| 1243 | try buf.appendSlice(std.fs.path.stem(path)); | 1243 | try buf.appendSlice(allocator, std.fs.path.stem(path)); |
| 1244 | try buf.appendSlice(ext); | 1244 | try buf.appendSlice(allocator, ext); |
| 1245 | return try buf.toOwnedSlice(); | 1245 | return try buf.toOwnedSlice(allocator); |
| 1246 | } | 1246 | } |
| 1247 | 1247 | ||
| 1248 | pub fn isSupportedInputExtension(ext: []const u8) bool { | 1248 | pub fn isSupportedInputExtension(ext: []const u8) bool { |
| ... | @@ -1476,7 +1476,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti | ... | @@ -1476,7 +1476,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti |
| 1476 | var options = parse(std.testing.allocator, args, &diagnostics) catch |err| switch (err) { | 1476 | var options = parse(std.testing.allocator, args, &diagnostics) catch |err| switch (err) { |
| 1477 | error.ParseError => { | 1477 | error.ParseError => { |
| 1478 | try diagnostics.renderToWriter(args, &output.writer, .no_color); | 1478 | try diagnostics.renderToWriter(args, &output.writer, .no_color); |
| 1479 | try std.testing.expectEqualStrings(expected_output, output.getWritten()); | 1479 | try std.testing.expectEqualStrings(expected_output, output.written()); |
| 1480 | return null; | 1480 | return null; |
| 1481 | }, | 1481 | }, |
| 1482 | else => |e| return e, | 1482 | else => |e| return e, |
| ... | @@ -1484,7 +1484,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti | ... | @@ -1484,7 +1484,7 @@ fn testParseOutput(args: []const []const u8, expected_output: []const u8) !?Opti |
| 1484 | errdefer options.deinit(); | 1484 | errdefer options.deinit(); |
| 1485 | 1485 | ||
| 1486 | try diagnostics.renderToWriter(args, &output.writer, .no_color); | 1486 | try diagnostics.renderToWriter(args, &output.writer, .no_color); |
| 1487 | try std.testing.expectEqualStrings(expected_output, output.getWritten()); | 1487 | try std.testing.expectEqualStrings(expected_output, output.written()); |
| 1488 | return options; | 1488 | return options; |
| 1489 | } | 1489 | } |
| 1490 | 1490 |
lib/compiler/resinator/compile.zig+189-221| ... | @@ -35,10 +35,7 @@ pub const CompileOptions = struct { | ... | @@ -35,10 +35,7 @@ pub const CompileOptions = struct { |
| 35 | diagnostics: *Diagnostics, | 35 | diagnostics: *Diagnostics, |
| 36 | source_mappings: ?*SourceMappings = null, | 36 | source_mappings: ?*SourceMappings = null, |
| 37 | /// List of paths (absolute or relative to `cwd`) for every file that the resources within the .rc file depend on. | 37 | /// List of paths (absolute or relative to `cwd`) for every file that the resources within the .rc file depend on. |
| 38 | /// Items within the list will be allocated using the allocator of the ArrayList and must be | 38 | dependencies: ?*Dependencies = null, |
| 39 | /// freed by the caller. | ||
| 40 | /// TODO: Maybe a dedicated struct for this purpose so that it's a bit nicer to work with. | ||
| 41 | dependencies_list: ?*std.array_list.Managed([]const u8) = null, | ||
| 42 | default_code_page: SupportedCodePage = .windows1252, | 39 | default_code_page: SupportedCodePage = .windows1252, |
| 43 | /// If true, the first #pragma code_page directive only sets the input code page, but not the output code page. | 40 | /// If true, the first #pragma code_page directive only sets the input code page, but not the output code page. |
| 44 | /// This check must be done before comments are removed from the file. | 41 | /// This check must be done before comments are removed from the file. |
| ... | @@ -61,6 +58,25 @@ pub const CompileOptions = struct { | ... | @@ -61,6 +58,25 @@ pub const CompileOptions = struct { |
| 61 | warn_instead_of_error_on_invalid_code_page: bool = false, | 58 | warn_instead_of_error_on_invalid_code_page: bool = false, |
| 62 | }; | 59 | }; |
| 63 | 60 | ||
| 61 | pub const Dependencies = struct { | ||
| 62 | list: std.ArrayList([]const u8), | ||
| 63 | allocator: Allocator, | ||
| 64 | |||
| 65 | pub fn init(allocator: Allocator) Dependencies { | ||
| 66 | return .{ | ||
| 67 | .list = .empty, | ||
| 68 | .allocator = allocator, | ||
| 69 | }; | ||
| 70 | } | ||
| 71 | |||
| 72 | pub fn deinit(self: *Dependencies) void { | ||
| 73 | for (self.list.items) |item| { | ||
| 74 | self.allocator.free(item); | ||
| 75 | } | ||
| 76 | self.list.deinit(self.allocator); | ||
| 77 | } | ||
| 78 | }; | ||
| 79 | |||
| 64 | pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void { | 80 | pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void { |
| 65 | var lexer = lex.Lexer.init(source, .{ | 81 | var lexer = lex.Lexer.init(source, .{ |
| 66 | .default_code_page = options.default_code_page, | 82 | .default_code_page = options.default_code_page, |
| ... | @@ -74,12 +90,12 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, | ... | @@ -74,12 +90,12 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, |
| 74 | var tree = try parser.parse(allocator, options.diagnostics); | 90 | var tree = try parser.parse(allocator, options.diagnostics); |
| 75 | defer tree.deinit(); | 91 | defer tree.deinit(); |
| 76 | 92 | ||
| 77 | var search_dirs = std.array_list.Managed(SearchDir).init(allocator); | 93 | var search_dirs: std.ArrayList(SearchDir) = .empty; |
| 78 | defer { | 94 | defer { |
| 79 | for (search_dirs.items) |*search_dir| { | 95 | for (search_dirs.items) |*search_dir| { |
| 80 | search_dir.deinit(allocator); | 96 | search_dir.deinit(allocator); |
| 81 | } | 97 | } |
| 82 | search_dirs.deinit(); | 98 | search_dirs.deinit(allocator); |
| 83 | } | 99 | } |
| 84 | 100 | ||
| 85 | if (options.source_mappings) |source_mappings| { | 101 | if (options.source_mappings) |source_mappings| { |
| ... | @@ -89,7 +105,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, | ... | @@ -89,7 +105,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, |
| 89 | if (std.fs.path.dirname(root_path)) |root_dir_path| { | 105 | if (std.fs.path.dirname(root_path)) |root_dir_path| { |
| 90 | var root_dir = try options.cwd.openDir(root_dir_path, .{}); | 106 | var root_dir = try options.cwd.openDir(root_dir_path, .{}); |
| 91 | errdefer root_dir.close(); | 107 | errdefer root_dir.close(); |
| 92 | try search_dirs.append(.{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); | 108 | try search_dirs.append(allocator, .{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) }); |
| 93 | } | 109 | } |
| 94 | } | 110 | } |
| 95 | // Re-open the passed in cwd since we want to be able to close it (std.fs.cwd() shouldn't be closed) | 111 | // Re-open the passed in cwd since we want to be able to close it (std.fs.cwd() shouldn't be closed) |
| ... | @@ -111,14 +127,14 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, | ... | @@ -111,14 +127,14 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, |
| 111 | }); | 127 | }); |
| 112 | return error.CompileError; | 128 | return error.CompileError; |
| 113 | }; | 129 | }; |
| 114 | try search_dirs.append(.{ .dir = cwd_dir, .path = null }); | 130 | try search_dirs.append(allocator, .{ .dir = cwd_dir, .path = null }); |
| 115 | for (options.extra_include_paths) |extra_include_path| { | 131 | for (options.extra_include_paths) |extra_include_path| { |
| 116 | var dir = openSearchPathDir(options.cwd, extra_include_path) catch { | 132 | var dir = openSearchPathDir(options.cwd, extra_include_path) catch { |
| 117 | // TODO: maybe a warning that the search path is skipped? | 133 | // TODO: maybe a warning that the search path is skipped? |
| 118 | continue; | 134 | continue; |
| 119 | }; | 135 | }; |
| 120 | errdefer dir.close(); | 136 | errdefer dir.close(); |
| 121 | try search_dirs.append(.{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) }); | 137 | try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) }); |
| 122 | } | 138 | } |
| 123 | for (options.system_include_paths) |system_include_path| { | 139 | for (options.system_include_paths) |system_include_path| { |
| 124 | var dir = openSearchPathDir(options.cwd, system_include_path) catch { | 140 | var dir = openSearchPathDir(options.cwd, system_include_path) catch { |
| ... | @@ -126,7 +142,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, | ... | @@ -126,7 +142,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, |
| 126 | continue; | 142 | continue; |
| 127 | }; | 143 | }; |
| 128 | errdefer dir.close(); | 144 | errdefer dir.close(); |
| 129 | try search_dirs.append(.{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) }); | 145 | try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) }); |
| 130 | } | 146 | } |
| 131 | if (!options.ignore_include_env_var) { | 147 | if (!options.ignore_include_env_var) { |
| 132 | const INCLUDE = std.process.getEnvVarOwned(allocator, "INCLUDE") catch ""; | 148 | const INCLUDE = std.process.getEnvVarOwned(allocator, "INCLUDE") catch ""; |
| ... | @@ -142,7 +158,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, | ... | @@ -142,7 +158,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, |
| 142 | while (it.next()) |search_path| { | 158 | while (it.next()) |search_path| { |
| 143 | var dir = openSearchPathDir(options.cwd, search_path) catch continue; | 159 | var dir = openSearchPathDir(options.cwd, search_path) catch continue; |
| 144 | errdefer dir.close(); | 160 | errdefer dir.close(); |
| 145 | try search_dirs.append(.{ .dir = dir, .path = try allocator.dupe(u8, search_path) }); | 161 | try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, search_path) }); |
| 146 | } | 162 | } |
| 147 | } | 163 | } |
| 148 | 164 | ||
| ... | @@ -156,7 +172,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, | ... | @@ -156,7 +172,7 @@ pub fn compile(allocator: Allocator, source: []const u8, writer: *std.Io.Writer, |
| 156 | .allocator = allocator, | 172 | .allocator = allocator, |
| 157 | .cwd = options.cwd, | 173 | .cwd = options.cwd, |
| 158 | .diagnostics = options.diagnostics, | 174 | .diagnostics = options.diagnostics, |
| 159 | .dependencies_list = options.dependencies_list, | 175 | .dependencies = options.dependencies, |
| 160 | .input_code_pages = &tree.input_code_pages, | 176 | .input_code_pages = &tree.input_code_pages, |
| 161 | .output_code_pages = &tree.output_code_pages, | 177 | .output_code_pages = &tree.output_code_pages, |
| 162 | // This is only safe because we know search_dirs won't be modified past this point | 178 | // This is only safe because we know search_dirs won't be modified past this point |
| ... | @@ -178,7 +194,7 @@ pub const Compiler = struct { | ... | @@ -178,7 +194,7 @@ pub const Compiler = struct { |
| 178 | cwd: std.fs.Dir, | 194 | cwd: std.fs.Dir, |
| 179 | state: State = .{}, | 195 | state: State = .{}, |
| 180 | diagnostics: *Diagnostics, | 196 | diagnostics: *Diagnostics, |
| 181 | dependencies_list: ?*std.array_list.Managed([]const u8), | 197 | dependencies: ?*Dependencies, |
| 182 | input_code_pages: *const CodePageLookup, | 198 | input_code_pages: *const CodePageLookup, |
| 183 | output_code_pages: *const CodePageLookup, | 199 | output_code_pages: *const CodePageLookup, |
| 184 | search_dirs: []SearchDir, | 200 | search_dirs: []SearchDir, |
| ... | @@ -279,32 +295,32 @@ pub const Compiler = struct { | ... | @@ -279,32 +295,32 @@ pub const Compiler = struct { |
| 279 | .literal, .number => { | 295 | .literal, .number => { |
| 280 | const slice = literal_node.token.slice(self.source); | 296 | const slice = literal_node.token.slice(self.source); |
| 281 | const code_page = self.input_code_pages.getForToken(literal_node.token); | 297 | const code_page = self.input_code_pages.getForToken(literal_node.token); |
| 282 | var buf = try std.array_list.Managed(u8).initCapacity(self.allocator, slice.len); | 298 | var buf = try std.ArrayList(u8).initCapacity(self.allocator, slice.len); |
| 283 | errdefer buf.deinit(); | 299 | errdefer buf.deinit(self.allocator); |
| 284 | 300 | ||
| 285 | var index: usize = 0; | 301 | var index: usize = 0; |
| 286 | while (code_page.codepointAt(index, slice)) |codepoint| : (index += codepoint.byte_len) { | 302 | while (code_page.codepointAt(index, slice)) |codepoint| : (index += codepoint.byte_len) { |
| 287 | const c = codepoint.value; | 303 | const c = codepoint.value; |
| 288 | if (c == code_pages.Codepoint.invalid) { | 304 | if (c == code_pages.Codepoint.invalid) { |
| 289 | try buf.appendSlice("�"); | 305 | try buf.appendSlice(self.allocator, "�"); |
| 290 | } else { | 306 | } else { |
| 291 | // Anything that is not returned as an invalid codepoint must be encodable as UTF-8. | 307 | // Anything that is not returned as an invalid codepoint must be encodable as UTF-8. |
| 292 | const utf8_len = std.unicode.utf8CodepointSequenceLength(c) catch unreachable; | 308 | const utf8_len = std.unicode.utf8CodepointSequenceLength(c) catch unreachable; |
| 293 | try buf.ensureUnusedCapacity(utf8_len); | 309 | try buf.ensureUnusedCapacity(self.allocator, utf8_len); |
| 294 | _ = std.unicode.utf8Encode(c, buf.unusedCapacitySlice()) catch unreachable; | 310 | _ = std.unicode.utf8Encode(c, buf.unusedCapacitySlice()) catch unreachable; |
| 295 | buf.items.len += utf8_len; | 311 | buf.items.len += utf8_len; |
| 296 | } | 312 | } |
| 297 | } | 313 | } |
| 298 | 314 | ||
| 299 | return buf.toOwnedSlice(); | 315 | return buf.toOwnedSlice(self.allocator); |
| 300 | }, | 316 | }, |
| 301 | .quoted_ascii_string, .quoted_wide_string => { | 317 | .quoted_ascii_string, .quoted_wide_string => { |
| 302 | const slice = literal_node.token.slice(self.source); | 318 | const slice = literal_node.token.slice(self.source); |
| 303 | const column = literal_node.token.calculateColumn(self.source, 8, null); | 319 | const column = literal_node.token.calculateColumn(self.source, 8, null); |
| 304 | const bytes = SourceBytes{ .slice = slice, .code_page = self.input_code_pages.getForToken(literal_node.token) }; | 320 | const bytes = SourceBytes{ .slice = slice, .code_page = self.input_code_pages.getForToken(literal_node.token) }; |
| 305 | 321 | ||
| 306 | var buf = std.array_list.Managed(u8).init(self.allocator); | 322 | var buf: std.ArrayList(u8) = .empty; |
| 307 | errdefer buf.deinit(); | 323 | errdefer buf.deinit(self.allocator); |
| 308 | 324 | ||
| 309 | // Filenames are sort-of parsed as if they were wide strings, but the max escape width of | 325 | // Filenames are sort-of parsed as if they were wide strings, but the max escape width of |
| 310 | // hex/octal escapes is still determined by the L prefix. Since we want to end up with | 326 | // hex/octal escapes is still determined by the L prefix. Since we want to end up with |
| ... | @@ -320,19 +336,19 @@ pub const Compiler = struct { | ... | @@ -320,19 +336,19 @@ pub const Compiler = struct { |
| 320 | while (try parser.nextUnchecked()) |parsed| { | 336 | while (try parser.nextUnchecked()) |parsed| { |
| 321 | const c = parsed.codepoint; | 337 | const c = parsed.codepoint; |
| 322 | if (c == code_pages.Codepoint.invalid) { | 338 | if (c == code_pages.Codepoint.invalid) { |
| 323 | try buf.appendSlice("�"); | 339 | try buf.appendSlice(self.allocator, "�"); |
| 324 | } else { | 340 | } else { |
| 325 | var codepoint_buf: [4]u8 = undefined; | 341 | var codepoint_buf: [4]u8 = undefined; |
| 326 | // If the codepoint cannot be encoded, we fall back to � | 342 | // If the codepoint cannot be encoded, we fall back to � |
| 327 | if (std.unicode.utf8Encode(c, &codepoint_buf)) |len| { | 343 | if (std.unicode.utf8Encode(c, &codepoint_buf)) |len| { |
| 328 | try buf.appendSlice(codepoint_buf[0..len]); | 344 | try buf.appendSlice(self.allocator, codepoint_buf[0..len]); |
| 329 | } else |_| { | 345 | } else |_| { |
| 330 | try buf.appendSlice("�"); | 346 | try buf.appendSlice(self.allocator, "�"); |
| 331 | } | 347 | } |
| 332 | } | 348 | } |
| 333 | } | 349 | } |
| 334 | 350 | ||
| 335 | return buf.toOwnedSlice(); | 351 | return buf.toOwnedSlice(self.allocator); |
| 336 | }, | 352 | }, |
| 337 | else => unreachable, // no other token types should be in a filename literal node | 353 | else => unreachable, // no other token types should be in a filename literal node |
| 338 | } | 354 | } |
| ... | @@ -386,10 +402,10 @@ pub const Compiler = struct { | ... | @@ -386,10 +402,10 @@ pub const Compiler = struct { |
| 386 | const file = try utils.openFileNotDir(std.fs.cwd(), path, .{}); | 402 | const file = try utils.openFileNotDir(std.fs.cwd(), path, .{}); |
| 387 | errdefer file.close(); | 403 | errdefer file.close(); |
| 388 | 404 | ||
| 389 | if (self.dependencies_list) |dependencies_list| { | 405 | if (self.dependencies) |dependencies| { |
| 390 | const duped_path = try dependencies_list.allocator.dupe(u8, path); | 406 | const duped_path = try dependencies.allocator.dupe(u8, path); |
| 391 | errdefer dependencies_list.allocator.free(duped_path); | 407 | errdefer dependencies.allocator.free(duped_path); |
| 392 | try dependencies_list.append(duped_path); | 408 | try dependencies.list.append(dependencies.allocator, duped_path); |
| 393 | } | 409 | } |
| 394 | } | 410 | } |
| 395 | 411 | ||
| ... | @@ -398,12 +414,12 @@ pub const Compiler = struct { | ... | @@ -398,12 +414,12 @@ pub const Compiler = struct { |
| 398 | if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| { | 414 | if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| { |
| 399 | errdefer file.close(); | 415 | errdefer file.close(); |
| 400 | 416 | ||
| 401 | if (self.dependencies_list) |dependencies_list| { | 417 | if (self.dependencies) |dependencies| { |
| 402 | const searched_file_path = try std.fs.path.join(dependencies_list.allocator, &.{ | 418 | const searched_file_path = try std.fs.path.join(dependencies.allocator, &.{ |
| 403 | search_dir.path orelse "", path, | 419 | search_dir.path orelse "", path, |
| 404 | }); | 420 | }); |
| 405 | errdefer dependencies_list.allocator.free(searched_file_path); | 421 | errdefer dependencies.allocator.free(searched_file_path); |
| 406 | try dependencies_list.append(searched_file_path); | 422 | try dependencies.list.append(dependencies.allocator, searched_file_path); |
| 407 | } | 423 | } |
| 408 | 424 | ||
| 409 | return file; | 425 | return file; |
| ... | @@ -421,8 +437,8 @@ pub const Compiler = struct { | ... | @@ -421,8 +437,8 @@ pub const Compiler = struct { |
| 421 | const bytes = self.sourceBytesForToken(token); | 437 | const bytes = self.sourceBytesForToken(token); |
| 422 | const output_code_page = self.output_code_pages.getForToken(token); | 438 | const output_code_page = self.output_code_pages.getForToken(token); |
| 423 | 439 | ||
| 424 | var buf = try std.array_list.Managed(u8).initCapacity(self.allocator, bytes.slice.len); | 440 | var buf = try std.ArrayList(u8).initCapacity(self.allocator, bytes.slice.len); |
| 425 | errdefer buf.deinit(); | 441 | errdefer buf.deinit(self.allocator); |
| 426 | 442 | ||
| 427 | var iterative_parser = literals.IterativeStringParser.init(bytes, .{ | 443 | var iterative_parser = literals.IterativeStringParser.init(bytes, .{ |
| 428 | .start_column = token.calculateColumn(self.source, 8, null), | 444 | .start_column = token.calculateColumn(self.source, 8, null), |
| ... | @@ -444,11 +460,11 @@ pub const Compiler = struct { | ... | @@ -444,11 +460,11 @@ pub const Compiler = struct { |
| 444 | switch (iterative_parser.declared_string_type) { | 460 | switch (iterative_parser.declared_string_type) { |
| 445 | .wide => { | 461 | .wide => { |
| 446 | if (windows1252.bestFitFromCodepoint(c)) |best_fit| { | 462 | if (windows1252.bestFitFromCodepoint(c)) |best_fit| { |
| 447 | try buf.append(best_fit); | 463 | try buf.append(self.allocator, best_fit); |
| 448 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid or parsed.escaped_surrogate_pair) { | 464 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid or parsed.escaped_surrogate_pair) { |
| 449 | try buf.append('?'); | 465 | try buf.append(self.allocator, '?'); |
| 450 | } else { | 466 | } else { |
| 451 | try buf.appendSlice("??"); | 467 | try buf.appendSlice(self.allocator, "??"); |
| 452 | } | 468 | } |
| 453 | }, | 469 | }, |
| 454 | .ascii => { | 470 | .ascii => { |
| ... | @@ -456,27 +472,27 @@ pub const Compiler = struct { | ... | @@ -456,27 +472,27 @@ pub const Compiler = struct { |
| 456 | const truncated: u8 = @truncate(c); | 472 | const truncated: u8 = @truncate(c); |
| 457 | switch (output_code_page) { | 473 | switch (output_code_page) { |
| 458 | .utf8 => switch (truncated) { | 474 | .utf8 => switch (truncated) { |
| 459 | 0...0x7F => try buf.append(truncated), | 475 | 0...0x7F => try buf.append(self.allocator, truncated), |
| 460 | else => try buf.append('?'), | 476 | else => try buf.append(self.allocator, '?'), |
| 461 | }, | 477 | }, |
| 462 | .windows1252 => { | 478 | .windows1252 => { |
| 463 | try buf.append(truncated); | 479 | try buf.append(self.allocator, truncated); |
| 464 | }, | 480 | }, |
| 465 | } | 481 | } |
| 466 | } else { | 482 | } else { |
| 467 | if (windows1252.bestFitFromCodepoint(c)) |best_fit| { | 483 | if (windows1252.bestFitFromCodepoint(c)) |best_fit| { |
| 468 | try buf.append(best_fit); | 484 | try buf.append(self.allocator, best_fit); |
| 469 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid) { | 485 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid) { |
| 470 | try buf.append('?'); | 486 | try buf.append(self.allocator, '?'); |
| 471 | } else { | 487 | } else { |
| 472 | try buf.appendSlice("??"); | 488 | try buf.appendSlice(self.allocator, "??"); |
| 473 | } | 489 | } |
| 474 | } | 490 | } |
| 475 | }, | 491 | }, |
| 476 | } | 492 | } |
| 477 | } | 493 | } |
| 478 | 494 | ||
| 479 | return buf.toOwnedSlice(); | 495 | return buf.toOwnedSlice(self.allocator); |
| 480 | } | 496 | } |
| 481 | 497 | ||
| 482 | pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: *std.Io.Writer) !void { | 498 | pub fn writeResourceExternal(self: *Compiler, node: *Node.ResourceExternal, writer: *std.Io.Writer) !void { |
| ... | @@ -572,7 +588,7 @@ pub const Compiler = struct { | ... | @@ -572,7 +588,7 @@ pub const Compiler = struct { |
| 572 | switch (predefined_type) { | 588 | switch (predefined_type) { |
| 573 | .GROUP_ICON, .GROUP_CURSOR => { | 589 | .GROUP_ICON, .GROUP_CURSOR => { |
| 574 | // Check for animated icon first | 590 | // Check for animated icon first |
| 575 | if (ani.isAnimatedIcon(file_reader.interface.adaptToOldInterface())) { | 591 | if (ani.isAnimatedIcon(&file_reader.interface)) { |
| 576 | // Animated icons are just put into the resource unmodified, | 592 | // Animated icons are just put into the resource unmodified, |
| 577 | // and the resource type changes to ANIICON/ANICURSOR | 593 | // and the resource type changes to ANIICON/ANICURSOR |
| 578 | 594 | ||
| ... | @@ -584,7 +600,12 @@ pub const Compiler = struct { | ... | @@ -584,7 +600,12 @@ pub const Compiler = struct { |
| 584 | header.type_value.ordinal = @intFromEnum(new_predefined_type); | 600 | header.type_value.ordinal = @intFromEnum(new_predefined_type); |
| 585 | header.memory_flags = MemoryFlags.defaults(new_predefined_type); | 601 | header.memory_flags = MemoryFlags.defaults(new_predefined_type); |
| 586 | header.applyMemoryFlags(node.common_resource_attributes, self.source); | 602 | header.applyMemoryFlags(node.common_resource_attributes, self.source); |
| 587 | header.data_size = @intCast(try file_reader.getSize()); | 603 | header.data_size = std.math.cast(u32, try file_reader.getSize()) orelse { |
| 604 | return self.addErrorDetailsAndFail(.{ | ||
| 605 | .err = .resource_data_size_exceeds_max, | ||
| 606 | .token = node.id, | ||
| 607 | }); | ||
| 608 | }; | ||
| 588 | 609 | ||
| 589 | try header.write(writer, self.errContext(node.id)); | 610 | try header.write(writer, self.errContext(node.id)); |
| 590 | try file_reader.seekTo(0); | 611 | try file_reader.seekTo(0); |
| ... | @@ -595,7 +616,7 @@ pub const Compiler = struct { | ... | @@ -595,7 +616,7 @@ pub const Compiler = struct { |
| 595 | // isAnimatedIcon moved the file cursor so reset to the start | 616 | // isAnimatedIcon moved the file cursor so reset to the start |
| 596 | try file_reader.seekTo(0); | 617 | try file_reader.seekTo(0); |
| 597 | 618 | ||
| 598 | const icon_dir = ico.read(self.allocator, file_reader.interface.adaptToOldInterface(), try file_reader.getSize()) catch |err| switch (err) { | 619 | const icon_dir = ico.read(self.allocator, &file_reader.interface, try file_reader.getSize()) catch |err| switch (err) { |
| 599 | error.OutOfMemory => |e| return e, | 620 | error.OutOfMemory => |e| return e, |
| 600 | else => |e| { | 621 | else => |e| { |
| 601 | return self.iconReadError( | 622 | return self.iconReadError( |
| ... | @@ -861,7 +882,7 @@ pub const Compiler = struct { | ... | @@ -861,7 +882,7 @@ pub const Compiler = struct { |
| 861 | header.applyMemoryFlags(node.common_resource_attributes, self.source); | 882 | header.applyMemoryFlags(node.common_resource_attributes, self.source); |
| 862 | const file_size = try file_reader.getSize(); | 883 | const file_size = try file_reader.getSize(); |
| 863 | 884 | ||
| 864 | const bitmap_info = bmp.read(file_reader.interface.adaptToOldInterface(), file_size) catch |err| { | 885 | const bitmap_info = bmp.read(&file_reader.interface, file_size) catch |err| { |
| 865 | const filename_string_index = try self.diagnostics.putString(filename_utf8); | 886 | const filename_string_index = try self.diagnostics.putString(filename_utf8); |
| 866 | return self.addErrorDetailsAndFail(.{ | 887 | return self.addErrorDetailsAndFail(.{ |
| 867 | .err = .bmp_read_error, | 888 | .err = .bmp_read_error, |
| ... | @@ -969,13 +990,19 @@ pub const Compiler = struct { | ... | @@ -969,13 +990,19 @@ pub const Compiler = struct { |
| 969 | header.data_size = @intCast(file_size); | 990 | header.data_size = @intCast(file_size); |
| 970 | try header.write(writer, self.errContext(node.id)); | 991 | try header.write(writer, self.errContext(node.id)); |
| 971 | 992 | ||
| 972 | var header_slurping_reader = headerSlurpingReader(148, file_reader.interface.adaptToOldInterface()); | 993 | // Slurp the first 148 bytes separately so we can store them in the FontDir |
| 973 | var adapter = header_slurping_reader.reader().adaptToNewApi(&.{}); | 994 | var font_dir_header_buf: [148]u8 = @splat(0); |
| 974 | try writeResourceData(writer, &adapter.new_interface, header.data_size); | 995 | const populated_len: u32 = @intCast(try file_reader.interface.readSliceShort(&font_dir_header_buf)); |
| 996 | |||
| 997 | // Write only the populated bytes slurped from the header | ||
| 998 | try writer.writeAll(font_dir_header_buf[0..populated_len]); | ||
| 999 | // Then write the rest of the bytes and the padding | ||
| 1000 | try writeResourceDataNoPadding(writer, &file_reader.interface, header.data_size - populated_len); | ||
| 1001 | try writeDataPadding(writer, header.data_size); | ||
| 975 | 1002 | ||
| 976 | try self.state.font_dir.add(self.arena, FontDir.Font{ | 1003 | try self.state.font_dir.add(self.arena, FontDir.Font{ |
| 977 | .id = header.name_value.ordinal, | 1004 | .id = header.name_value.ordinal, |
| 978 | .header_bytes = header_slurping_reader.slurped_header, | 1005 | .header_bytes = font_dir_header_buf, |
| 979 | }, node.id); | 1006 | }, node.id); |
| 980 | return; | 1007 | return; |
| 981 | }, | 1008 | }, |
| ... | @@ -1053,7 +1080,7 @@ pub const Compiler = struct { | ... | @@ -1053,7 +1080,7 @@ pub const Compiler = struct { |
| 1053 | } | 1080 | } |
| 1054 | } | 1081 | } |
| 1055 | 1082 | ||
| 1056 | pub fn write(self: Data, writer: anytype) !void { | 1083 | pub fn write(self: Data, writer: *std.Io.Writer) !void { |
| 1057 | switch (self) { | 1084 | switch (self) { |
| 1058 | .number => |number| switch (number.is_long) { | 1085 | .number => |number| switch (number.is_long) { |
| 1059 | false => try writer.writeInt(WORD, number.asWord(), .little), | 1086 | false => try writer.writeInt(WORD, number.asWord(), .little), |
| ... | @@ -1225,36 +1252,30 @@ pub const Compiler = struct { | ... | @@ -1225,36 +1252,30 @@ pub const Compiler = struct { |
| 1225 | } | 1252 | } |
| 1226 | } | 1253 | } |
| 1227 | 1254 | ||
| 1228 | pub fn writeResourceRawData(self: *Compiler, node: *Node.ResourceRawData, writer: anytype) !void { | 1255 | pub fn writeResourceRawData(self: *Compiler, node: *Node.ResourceRawData, writer: *std.Io.Writer) !void { |
| 1229 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | 1256 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); |
| 1230 | defer data_buffer.deinit(); | 1257 | defer data_buffer.deinit(); |
| 1231 | // The header's data length field is a u32 so limit the resource's data size so that | ||
| 1232 | // we know we can always specify the real size. | ||
| 1233 | const data_writer = &data_buffer.writer; | ||
| 1234 | 1258 | ||
| 1235 | for (node.raw_data) |expression| { | 1259 | for (node.raw_data) |expression| { |
| 1236 | const data = try self.evaluateDataExpression(expression); | 1260 | const data = try self.evaluateDataExpression(expression); |
| 1237 | defer data.deinit(self.allocator); | 1261 | defer data.deinit(self.allocator); |
| 1238 | data.write(data_writer) catch |err| switch (err) { | 1262 | try data.write(&data_buffer.writer); |
| 1239 | error.WriteFailed => { | ||
| 1240 | return self.addErrorDetailsAndFail(.{ | ||
| 1241 | .err = .resource_data_size_exceeds_max, | ||
| 1242 | .token = node.id, | ||
| 1243 | }); | ||
| 1244 | }, | ||
| 1245 | }; | ||
| 1246 | } | 1263 | } |
| 1247 | 1264 | ||
| 1248 | // This intCast can't fail because the limitedWriter above guarantees that | 1265 | // TODO: Limit data_buffer in some way to error when writing more than u32 max bytes |
| 1249 | // we will never write more than maxInt(u32) bytes. | 1266 | const data_len: u32 = std.math.cast(u32, data_buffer.written().len) orelse { |
| 1250 | const data_len: u32 = @intCast(data_buffer.written().len); | 1267 | return self.addErrorDetailsAndFail(.{ |
| 1268 | .err = .resource_data_size_exceeds_max, | ||
| 1269 | .token = node.id, | ||
| 1270 | }); | ||
| 1271 | }; | ||
| 1251 | try self.writeResourceHeader(writer, node.id, node.type, data_len, node.common_resource_attributes, self.state.language); | 1272 | try self.writeResourceHeader(writer, node.id, node.type, data_len, node.common_resource_attributes, self.state.language); |
| 1252 | 1273 | ||
| 1253 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); | 1274 | var data_fbs: std.Io.Reader = .fixed(data_buffer.written()); |
| 1254 | try writeResourceData(writer, &data_fbs, data_len); | 1275 | try writeResourceData(writer, &data_fbs, data_len); |
| 1255 | } | 1276 | } |
| 1256 | 1277 | ||
| 1257 | pub fn writeResourceHeader(self: *Compiler, writer: anytype, id_token: Token, type_token: Token, data_size: u32, common_resource_attributes: []Token, language: res.Language) !void { | 1278 | pub fn writeResourceHeader(self: *Compiler, writer: *std.Io.Writer, id_token: Token, type_token: Token, data_size: u32, common_resource_attributes: []Token, language: res.Language) !void { |
| 1258 | var header = try self.resourceHeader(id_token, type_token, .{ | 1279 | var header = try self.resourceHeader(id_token, type_token, .{ |
| 1259 | .language = language, | 1280 | .language = language, |
| 1260 | .data_size = data_size, | 1281 | .data_size = data_size, |
| ... | @@ -1270,7 +1291,7 @@ pub const Compiler = struct { | ... | @@ -1270,7 +1291,7 @@ pub const Compiler = struct { |
| 1270 | try data_reader.streamExact(writer, data_size); | 1291 | try data_reader.streamExact(writer, data_size); |
| 1271 | } | 1292 | } |
| 1272 | 1293 | ||
| 1273 | pub fn writeResourceData(writer: anytype, data_reader: *std.Io.Reader, data_size: u32) !void { | 1294 | pub fn writeResourceData(writer: *std.Io.Writer, data_reader: *std.Io.Reader, data_size: u32) !void { |
| 1274 | try writeResourceDataNoPadding(writer, data_reader, data_size); | 1295 | try writeResourceDataNoPadding(writer, data_reader, data_size); |
| 1275 | try writeDataPadding(writer, data_size); | 1296 | try writeDataPadding(writer, data_size); |
| 1276 | } | 1297 | } |
| ... | @@ -1303,27 +1324,19 @@ pub const Compiler = struct { | ... | @@ -1303,27 +1324,19 @@ pub const Compiler = struct { |
| 1303 | } | 1324 | } |
| 1304 | } | 1325 | } |
| 1305 | 1326 | ||
| 1306 | pub fn writeAccelerators(self: *Compiler, node: *Node.Accelerators, writer: anytype) !void { | 1327 | pub fn writeAccelerators(self: *Compiler, node: *Node.Accelerators, writer: *std.Io.Writer) !void { |
| 1307 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | 1328 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); |
| 1308 | defer data_buffer.deinit(); | 1329 | defer data_buffer.deinit(); |
| 1309 | 1330 | ||
| 1310 | // The header's data length field is a u32 so limit the resource's data size so that | 1331 | try self.writeAcceleratorsData(node, &data_buffer.writer); |
| 1311 | // we know we can always specify the real size. | ||
| 1312 | const data_writer = &data_buffer.writer; | ||
| 1313 | 1332 | ||
| 1314 | self.writeAcceleratorsData(node, data_writer) catch |err| switch (err) { | 1333 | // TODO: Limit data_buffer in some way to error when writing more than u32 max bytes |
| 1315 | error.WriteFailed => { | 1334 | const data_size: u32 = std.math.cast(u32, data_buffer.written().len) orelse { |
| 1316 | return self.addErrorDetailsAndFail(.{ | 1335 | return self.addErrorDetailsAndFail(.{ |
| 1317 | .err = .resource_data_size_exceeds_max, | 1336 | .err = .resource_data_size_exceeds_max, |
| 1318 | .token = node.id, | 1337 | .token = node.id, |
| 1319 | }); | 1338 | }); |
| 1320 | }, | ||
| 1321 | else => |e| return e, | ||
| 1322 | }; | 1339 | }; |
| 1323 | |||
| 1324 | // This intCast can't fail because the limitedWriter above guarantees that | ||
| 1325 | // we will never write more than maxInt(u32) bytes. | ||
| 1326 | const data_size: u32 = @intCast(data_buffer.written().len); | ||
| 1327 | var header = try self.resourceHeader(node.id, node.type, .{ | 1340 | var header = try self.resourceHeader(node.id, node.type, .{ |
| 1328 | .data_size = data_size, | 1341 | .data_size = data_size, |
| 1329 | }); | 1342 | }); |
| ... | @@ -1340,7 +1353,7 @@ pub const Compiler = struct { | ... | @@ -1340,7 +1353,7 @@ pub const Compiler = struct { |
| 1340 | 1353 | ||
| 1341 | /// Expects `data_writer` to be a LimitedWriter limited to u32, meaning all writes to | 1354 | /// Expects `data_writer` to be a LimitedWriter limited to u32, meaning all writes to |
| 1342 | /// the writer within this function could return error.NoSpaceLeft | 1355 | /// the writer within this function could return error.NoSpaceLeft |
| 1343 | pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: anytype) !void { | 1356 | pub fn writeAcceleratorsData(self: *Compiler, node: *Node.Accelerators, data_writer: *std.Io.Writer) !void { |
| 1344 | for (node.accelerators, 0..) |accel_node, i| { | 1357 | for (node.accelerators, 0..) |accel_node, i| { |
| 1345 | const accelerator: *Node.Accelerator = @alignCast(@fieldParentPtr("base", accel_node)); | 1358 | const accelerator: *Node.Accelerator = @alignCast(@fieldParentPtr("base", accel_node)); |
| 1346 | var modifiers = res.AcceleratorModifiers{}; | 1359 | var modifiers = res.AcceleratorModifiers{}; |
| ... | @@ -1401,12 +1414,9 @@ pub const Compiler = struct { | ... | @@ -1401,12 +1414,9 @@ pub const Compiler = struct { |
| 1401 | caption: ?Token = null, | 1414 | caption: ?Token = null, |
| 1402 | }; | 1415 | }; |
| 1403 | 1416 | ||
| 1404 | pub fn writeDialog(self: *Compiler, node: *Node.Dialog, writer: anytype) !void { | 1417 | pub fn writeDialog(self: *Compiler, node: *Node.Dialog, writer: *std.Io.Writer) !void { |
| 1405 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | 1418 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); |
| 1406 | defer data_buffer.deinit(); | 1419 | defer data_buffer.deinit(); |
| 1407 | // The header's data length field is a u32 so limit the resource's data size so that | ||
| 1408 | // we know we can always specify the real size. | ||
| 1409 | const data_writer = &data_buffer.writer; | ||
| 1410 | 1420 | ||
| 1411 | const resource = ResourceType.fromString(.{ | 1421 | const resource = ResourceType.fromString(.{ |
| 1412 | .slice = node.type.slice(self.source), | 1422 | .slice = node.type.slice(self.source), |
| ... | @@ -1667,21 +1677,18 @@ pub const Compiler = struct { | ... | @@ -1667,21 +1677,18 @@ pub const Compiler = struct { |
| 1667 | optional_statement_values.style |= res.WS.CAPTION; | 1677 | optional_statement_values.style |= res.WS.CAPTION; |
| 1668 | } | 1678 | } |
| 1669 | 1679 | ||
| 1670 | self.writeDialogHeaderAndStrings( | 1680 | // NOTE: Dialog header and menu/class/title strings can never exceed u32 bytes |
| 1681 | // on their own. | ||
| 1682 | try self.writeDialogHeaderAndStrings( | ||
| 1671 | node, | 1683 | node, |
| 1672 | data_writer, | 1684 | &data_buffer.writer, |
| 1673 | resource, | 1685 | resource, |
| 1674 | &optional_statement_values, | 1686 | &optional_statement_values, |
| 1675 | x, | 1687 | x, |
| 1676 | y, | 1688 | y, |
| 1677 | width, | 1689 | width, |
| 1678 | height, | 1690 | height, |
| 1679 | ) catch |err| switch (err) { | 1691 | ); |
| 1680 | // Dialog header and menu/class/title strings can never exceed u32 bytes | ||
| 1681 | // on their own, so this error is unreachable. | ||
| 1682 | error.WriteFailed => unreachable, | ||
| 1683 | else => |e| return e, | ||
| 1684 | }; | ||
| 1685 | 1692 | ||
| 1686 | var controls_by_id = std.AutoHashMap(u32, *const Node.ControlStatement).init(self.allocator); | 1693 | var controls_by_id = std.AutoHashMap(u32, *const Node.ControlStatement).init(self.allocator); |
| 1687 | // Number of controls are guaranteed by the parser to be within maxInt(u16). | 1694 | // Number of controls are guaranteed by the parser to be within maxInt(u16). |
| ... | @@ -1691,27 +1698,26 @@ pub const Compiler = struct { | ... | @@ -1691,27 +1698,26 @@ pub const Compiler = struct { |
| 1691 | for (node.controls) |control_node| { | 1698 | for (node.controls) |control_node| { |
| 1692 | const control: *Node.ControlStatement = @alignCast(@fieldParentPtr("base", control_node)); | 1699 | const control: *Node.ControlStatement = @alignCast(@fieldParentPtr("base", control_node)); |
| 1693 | 1700 | ||
| 1694 | self.writeDialogControl( | 1701 | try self.writeDialogControl( |
| 1695 | control, | 1702 | control, |
| 1696 | data_writer, | 1703 | &data_buffer.writer, |
| 1697 | resource, | 1704 | resource, |
| 1698 | // We know the data_buffer len is limited to u32 max. | 1705 | // We know the data_buffer len is limited to u32 max. |
| 1699 | @intCast(data_buffer.written().len), | 1706 | @intCast(data_buffer.written().len), |
| 1700 | &controls_by_id, | 1707 | &controls_by_id, |
| 1701 | ) catch |err| switch (err) { | 1708 | ); |
| 1702 | error.WriteFailed => { | 1709 | |
| 1703 | try self.addErrorDetails(.{ | 1710 | if (data_buffer.written().len > std.math.maxInt(u32)) { |
| 1704 | .err = .resource_data_size_exceeds_max, | 1711 | try self.addErrorDetails(.{ |
| 1705 | .token = node.id, | 1712 | .err = .resource_data_size_exceeds_max, |
| 1706 | }); | 1713 | .token = node.id, |
| 1707 | return self.addErrorDetailsAndFail(.{ | 1714 | }); |
| 1708 | .err = .resource_data_size_exceeds_max, | 1715 | return self.addErrorDetailsAndFail(.{ |
| 1709 | .type = .note, | 1716 | .err = .resource_data_size_exceeds_max, |
| 1710 | .token = control.type, | 1717 | .type = .note, |
| 1711 | }); | 1718 | .token = control.type, |
| 1712 | }, | 1719 | }); |
| 1713 | else => |e| return e, | 1720 | } |
| 1714 | }; | ||
| 1715 | } | 1721 | } |
| 1716 | 1722 | ||
| 1717 | // We know the data_buffer len is limited to u32 max. | 1723 | // We know the data_buffer len is limited to u32 max. |
| ... | @@ -1733,7 +1739,7 @@ pub const Compiler = struct { | ... | @@ -1733,7 +1739,7 @@ pub const Compiler = struct { |
| 1733 | fn writeDialogHeaderAndStrings( | 1739 | fn writeDialogHeaderAndStrings( |
| 1734 | self: *Compiler, | 1740 | self: *Compiler, |
| 1735 | node: *Node.Dialog, | 1741 | node: *Node.Dialog, |
| 1736 | data_writer: anytype, | 1742 | data_writer: *std.Io.Writer, |
| 1737 | resource: ResourceType, | 1743 | resource: ResourceType, |
| 1738 | optional_statement_values: *const DialogOptionalStatementValues, | 1744 | optional_statement_values: *const DialogOptionalStatementValues, |
| 1739 | x: Number, | 1745 | x: Number, |
| ... | @@ -1793,7 +1799,7 @@ pub const Compiler = struct { | ... | @@ -1793,7 +1799,7 @@ pub const Compiler = struct { |
| 1793 | fn writeDialogControl( | 1799 | fn writeDialogControl( |
| 1794 | self: *Compiler, | 1800 | self: *Compiler, |
| 1795 | control: *Node.ControlStatement, | 1801 | control: *Node.ControlStatement, |
| 1796 | data_writer: anytype, | 1802 | data_writer: *std.Io.Writer, |
| 1797 | resource: ResourceType, | 1803 | resource: ResourceType, |
| 1798 | bytes_written_so_far: u32, | 1804 | bytes_written_so_far: u32, |
| 1799 | controls_by_id: *std.AutoHashMap(u32, *const Node.ControlStatement), | 1805 | controls_by_id: *std.AutoHashMap(u32, *const Node.ControlStatement), |
| ... | @@ -1969,28 +1975,26 @@ pub const Compiler = struct { | ... | @@ -1969,28 +1975,26 @@ pub const Compiler = struct { |
| 1969 | try NameOrOrdinal.writeEmpty(data_writer); | 1975 | try NameOrOrdinal.writeEmpty(data_writer); |
| 1970 | } | 1976 | } |
| 1971 | 1977 | ||
| 1978 | // The extra data byte length must be able to fit within a u16. | ||
| 1972 | var extra_data_buf: std.Io.Writer.Allocating = .init(self.allocator); | 1979 | var extra_data_buf: std.Io.Writer.Allocating = .init(self.allocator); |
| 1973 | defer extra_data_buf.deinit(); | 1980 | defer extra_data_buf.deinit(); |
| 1974 | // The extra data byte length must be able to fit within a u16. | ||
| 1975 | const extra_data_writer = &extra_data_buf.writer; | ||
| 1976 | for (control.extra_data) |data_expression| { | 1981 | for (control.extra_data) |data_expression| { |
| 1977 | const data = try self.evaluateDataExpression(data_expression); | 1982 | const data = try self.evaluateDataExpression(data_expression); |
| 1978 | defer data.deinit(self.allocator); | 1983 | defer data.deinit(self.allocator); |
| 1979 | data.write(extra_data_writer) catch |err| switch (err) { | 1984 | try data.write(&extra_data_buf.writer); |
| 1980 | error.WriteFailed => { | 1985 | |
| 1981 | try self.addErrorDetails(.{ | 1986 | if (extra_data_buf.written().len > std.math.maxInt(u16)) { |
| 1982 | .err = .control_extra_data_size_exceeds_max, | 1987 | try self.addErrorDetails(.{ |
| 1983 | .token = control.type, | 1988 | .err = .control_extra_data_size_exceeds_max, |
| 1984 | }); | 1989 | .token = control.type, |
| 1985 | return self.addErrorDetailsAndFail(.{ | 1990 | }); |
| 1986 | .err = .control_extra_data_size_exceeds_max, | 1991 | return self.addErrorDetailsAndFail(.{ |
| 1987 | .type = .note, | 1992 | .err = .control_extra_data_size_exceeds_max, |
| 1988 | .token = data_expression.getFirstToken(), | 1993 | .type = .note, |
| 1989 | .token_span_end = data_expression.getLastToken(), | 1994 | .token = data_expression.getFirstToken(), |
| 1990 | }); | 1995 | .token_span_end = data_expression.getLastToken(), |
| 1991 | }, | 1996 | }); |
| 1992 | else => |e| return e, | 1997 | } |
| 1993 | }; | ||
| 1994 | } | 1998 | } |
| 1995 | // We know the extra_data_buf size fits within a u16. | 1999 | // We know the extra_data_buf size fits within a u16. |
| 1996 | const extra_data_size: u16 = @intCast(extra_data_buf.written().len); | 2000 | const extra_data_size: u16 = @intCast(extra_data_buf.written().len); |
| ... | @@ -1998,7 +2002,7 @@ pub const Compiler = struct { | ... | @@ -1998,7 +2002,7 @@ pub const Compiler = struct { |
| 1998 | try data_writer.writeAll(extra_data_buf.written()); | 2002 | try data_writer.writeAll(extra_data_buf.written()); |
| 1999 | } | 2003 | } |
| 2000 | 2004 | ||
| 2001 | pub fn writeToolbar(self: *Compiler, node: *Node.Toolbar, writer: anytype) !void { | 2005 | pub fn writeToolbar(self: *Compiler, node: *Node.Toolbar, writer: *std.Io.Writer) !void { |
| 2002 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | 2006 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); |
| 2003 | defer data_buffer.deinit(); | 2007 | defer data_buffer.deinit(); |
| 2004 | const data_writer = &data_buffer.writer; | 2008 | const data_writer = &data_buffer.writer; |
| ... | @@ -2051,7 +2055,7 @@ pub const Compiler = struct { | ... | @@ -2051,7 +2055,7 @@ pub const Compiler = struct { |
| 2051 | node: *Node.FontStatement, | 2055 | node: *Node.FontStatement, |
| 2052 | }; | 2056 | }; |
| 2053 | 2057 | ||
| 2054 | pub fn writeDialogFont(self: *Compiler, resource: ResourceType, values: FontStatementValues, writer: anytype) !void { | 2058 | pub fn writeDialogFont(self: *Compiler, resource: ResourceType, values: FontStatementValues, writer: *std.Io.Writer) !void { |
| 2055 | const node = values.node; | 2059 | const node = values.node; |
| 2056 | const point_size = evaluateNumberExpression(node.point_size, self.source, self.input_code_pages); | 2060 | const point_size = evaluateNumberExpression(node.point_size, self.source, self.input_code_pages); |
| 2057 | try writer.writeInt(u16, point_size.asWord(), .little); | 2061 | try writer.writeInt(u16, point_size.asWord(), .little); |
| ... | @@ -2076,12 +2080,9 @@ pub const Compiler = struct { | ... | @@ -2076,12 +2080,9 @@ pub const Compiler = struct { |
| 2076 | try writer.writeAll(std.mem.sliceAsBytes(typeface[0 .. typeface.len + 1])); | 2080 | try writer.writeAll(std.mem.sliceAsBytes(typeface[0 .. typeface.len + 1])); |
| 2077 | } | 2081 | } |
| 2078 | 2082 | ||
| 2079 | pub fn writeMenu(self: *Compiler, node: *Node.Menu, writer: anytype) !void { | 2083 | pub fn writeMenu(self: *Compiler, node: *Node.Menu, writer: *std.Io.Writer) !void { |
| 2080 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | 2084 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); |
| 2081 | defer data_buffer.deinit(); | 2085 | defer data_buffer.deinit(); |
| 2082 | // The header's data length field is a u32 so limit the resource's data size so that | ||
| 2083 | // we know we can always specify the real size. | ||
| 2084 | const data_writer = &data_buffer.writer; | ||
| 2085 | 2086 | ||
| 2086 | const type_bytes = SourceBytes{ | 2087 | const type_bytes = SourceBytes{ |
| 2087 | .slice = node.type.slice(self.source), | 2088 | .slice = node.type.slice(self.source), |
| ... | @@ -2090,19 +2091,15 @@ pub const Compiler = struct { | ... | @@ -2090,19 +2091,15 @@ pub const Compiler = struct { |
| 2090 | const resource = ResourceType.fromString(type_bytes); | 2091 | const resource = ResourceType.fromString(type_bytes); |
| 2091 | std.debug.assert(resource == .menu or resource == .menuex); | 2092 | std.debug.assert(resource == .menu or resource == .menuex); |
| 2092 | 2093 | ||
| 2093 | self.writeMenuData(node, data_writer, resource) catch |err| switch (err) { | 2094 | try self.writeMenuData(node, &data_buffer.writer, resource); |
| 2094 | error.WriteFailed => { | ||
| 2095 | return self.addErrorDetailsAndFail(.{ | ||
| 2096 | .err = .resource_data_size_exceeds_max, | ||
| 2097 | .token = node.id, | ||
| 2098 | }); | ||
| 2099 | }, | ||
| 2100 | else => |e| return e, | ||
| 2101 | }; | ||
| 2102 | 2095 | ||
| 2103 | // This intCast can't fail because the limitedWriter above guarantees that | 2096 | // TODO: Limit data_buffer in some way to error when writing more than u32 max bytes |
| 2104 | // we will never write more than maxInt(u32) bytes. | 2097 | const data_size: u32 = std.math.cast(u32, data_buffer.written().len) orelse { |
| 2105 | const data_size: u32 = @intCast(data_buffer.written().len); | 2098 | return self.addErrorDetailsAndFail(.{ |
| 2099 | .err = .resource_data_size_exceeds_max, | ||
| 2100 | .token = node.id, | ||
| 2101 | }); | ||
| 2102 | }; | ||
| 2106 | var header = try self.resourceHeader(node.id, node.type, .{ | 2103 | var header = try self.resourceHeader(node.id, node.type, .{ |
| 2107 | .data_size = data_size, | 2104 | .data_size = data_size, |
| 2108 | }); | 2105 | }); |
| ... | @@ -2256,11 +2253,10 @@ pub const Compiler = struct { | ... | @@ -2256,11 +2253,10 @@ pub const Compiler = struct { |
| 2256 | } | 2253 | } |
| 2257 | } | 2254 | } |
| 2258 | 2255 | ||
| 2259 | pub fn writeVersionInfo(self: *Compiler, node: *Node.VersionInfo, writer: anytype) !void { | 2256 | pub fn writeVersionInfo(self: *Compiler, node: *Node.VersionInfo, writer: *std.Io.Writer) !void { |
| 2257 | // NOTE: The node's length field (which is inclusive of the length of all of its children) is a u16 | ||
| 2260 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); | 2258 | var data_buffer: std.Io.Writer.Allocating = .init(self.allocator); |
| 2261 | defer data_buffer.deinit(); | 2259 | defer data_buffer.deinit(); |
| 2262 | // The node's length field (which is inclusive of the length of all of its children) is a u16 | ||
| 2263 | // so limit the node's data size so that we know we can always specify the real size. | ||
| 2264 | const data_writer = &data_buffer.writer; | 2260 | const data_writer = &data_buffer.writer; |
| 2265 | 2261 | ||
| 2266 | try data_writer.writeInt(u16, 0, .little); // placeholder size | 2262 | try data_writer.writeInt(u16, 0, .little); // placeholder size |
| ... | @@ -2345,25 +2341,29 @@ pub const Compiler = struct { | ... | @@ -2345,25 +2341,29 @@ pub const Compiler = struct { |
| 2345 | try fixed_file_info.write(data_writer); | 2341 | try fixed_file_info.write(data_writer); |
| 2346 | 2342 | ||
| 2347 | for (node.block_statements) |statement| { | 2343 | for (node.block_statements) |statement| { |
| 2348 | self.writeVersionNode(statement, data_writer, &data_buffer) catch |err| switch (err) { | 2344 | var overflow = false; |
| 2349 | error.WriteFailed => { | 2345 | self.writeVersionNode(statement, data_writer) catch |err| switch (err) { |
| 2350 | try self.addErrorDetails(.{ | 2346 | error.NoSpaceLeft => { |
| 2351 | .err = .version_node_size_exceeds_max, | 2347 | overflow = true; |
| 2352 | .token = node.id, | ||
| 2353 | }); | ||
| 2354 | return self.addErrorDetailsAndFail(.{ | ||
| 2355 | .err = .version_node_size_exceeds_max, | ||
| 2356 | .type = .note, | ||
| 2357 | .token = statement.getFirstToken(), | ||
| 2358 | .token_span_end = statement.getLastToken(), | ||
| 2359 | }); | ||
| 2360 | }, | 2348 | }, |
| 2361 | else => |e| return e, | 2349 | else => |e| return e, |
| 2362 | }; | 2350 | }; |
| 2351 | if (overflow or data_buffer.written().len > std.math.maxInt(u16)) { | ||
| 2352 | try self.addErrorDetails(.{ | ||
| 2353 | .err = .version_node_size_exceeds_max, | ||
| 2354 | .token = node.id, | ||
| 2355 | }); | ||
| 2356 | return self.addErrorDetailsAndFail(.{ | ||
| 2357 | .err = .version_node_size_exceeds_max, | ||
| 2358 | .type = .note, | ||
| 2359 | .token = statement.getFirstToken(), | ||
| 2360 | .token_span_end = statement.getLastToken(), | ||
| 2361 | }); | ||
| 2362 | } | ||
| 2363 | } | 2363 | } |
| 2364 | 2364 | ||
| 2365 | // We know that data_buffer.items.len is within the limits of a u16, since we | 2365 | // We know that data_buffer len is within the limits of a u16, since we check in the block |
| 2366 | // limited the writer to maxInt(u16) | 2366 | // statements loop above which is the only place it can overflow. |
| 2367 | const data_size: u16 = @intCast(data_buffer.written().len); | 2367 | const data_size: u16 = @intCast(data_buffer.written().len); |
| 2368 | // And now that we know the full size of this node (including its children), set its size | 2368 | // And now that we know the full size of this node (including its children), set its size |
| 2369 | std.mem.writeInt(u16, data_buffer.written()[0..2], data_size, .little); | 2369 | std.mem.writeInt(u16, data_buffer.written()[0..2], data_size, .little); |
| ... | @@ -2381,18 +2381,17 @@ pub const Compiler = struct { | ... | @@ -2381,18 +2381,17 @@ pub const Compiler = struct { |
| 2381 | try writeResourceData(writer, &data_fbs, data_size); | 2381 | try writeResourceData(writer, &data_fbs, data_size); |
| 2382 | } | 2382 | } |
| 2383 | 2383 | ||
| 2384 | /// Expects writer to be a LimitedWriter limited to u16, meaning all writes to | 2384 | /// Assumes that writer is Writer.Allocating (specifically, that buffered() gets the entire data) |
| 2385 | /// the writer within this function could return error.NoSpaceLeft, and that buf.items.len | 2385 | /// TODO: This function could be nicer if writer was guaranteed to fail if it wrote more than u16 max bytes |
| 2386 | /// will never be able to exceed maxInt(u16). | 2386 | pub fn writeVersionNode(self: *Compiler, node: *Node, writer: *std.Io.Writer) !void { |
| 2387 | pub fn writeVersionNode(self: *Compiler, node: *Node, writer: *std.Io.Writer, buf: *std.Io.Writer.Allocating) !void { | ||
| 2388 | // We can assume that buf.items.len will never be able to exceed the limits of a u16 | 2387 | // We can assume that buf.items.len will never be able to exceed the limits of a u16 |
| 2389 | try writeDataPadding(writer, @as(u16, @intCast(buf.written().len))); | 2388 | try writeDataPadding(writer, std.math.cast(u16, writer.buffered().len) orelse return error.NoSpaceLeft); |
| 2390 | 2389 | ||
| 2391 | const node_and_children_size_offset = buf.written().len; | 2390 | const node_and_children_size_offset = writer.buffered().len; |
| 2392 | try writer.writeInt(u16, 0, .little); // placeholder for size | 2391 | try writer.writeInt(u16, 0, .little); // placeholder for size |
| 2393 | const data_size_offset = buf.written().len; | 2392 | const data_size_offset = writer.buffered().len; |
| 2394 | try writer.writeInt(u16, 0, .little); // placeholder for data size | 2393 | try writer.writeInt(u16, 0, .little); // placeholder for data size |
| 2395 | const data_type_offset = buf.written().len; | 2394 | const data_type_offset = writer.buffered().len; |
| 2396 | // Data type is string unless the node contains values that are numbers. | 2395 | // Data type is string unless the node contains values that are numbers. |
| 2397 | try writer.writeInt(u16, res.VersionNode.type_string, .little); | 2396 | try writer.writeInt(u16, res.VersionNode.type_string, .little); |
| 2398 | 2397 | ||
| ... | @@ -2422,7 +2421,7 @@ pub const Compiler = struct { | ... | @@ -2422,7 +2421,7 @@ pub const Compiler = struct { |
| 2422 | // during parsing, so we can just do the correct thing here. | 2421 | // during parsing, so we can just do the correct thing here. |
| 2423 | var values_size: usize = 0; | 2422 | var values_size: usize = 0; |
| 2424 | 2423 | ||
| 2425 | try writeDataPadding(writer, @intCast(buf.written().len)); | 2424 | try writeDataPadding(writer, std.math.cast(u16, writer.buffered().len) orelse return error.NoSpaceLeft); |
| 2426 | 2425 | ||
| 2427 | for (block_or_value.values, 0..) |value_value_node_uncasted, i| { | 2426 | for (block_or_value.values, 0..) |value_value_node_uncasted, i| { |
| 2428 | const value_value_node = value_value_node_uncasted.cast(.block_value_value).?; | 2427 | const value_value_node = value_value_node_uncasted.cast(.block_value_value).?; |
| ... | @@ -2461,26 +2460,26 @@ pub const Compiler = struct { | ... | @@ -2461,26 +2460,26 @@ pub const Compiler = struct { |
| 2461 | } | 2460 | } |
| 2462 | } | 2461 | } |
| 2463 | } | 2462 | } |
| 2464 | var data_size_slice = buf.written()[data_size_offset..]; | 2463 | var data_size_slice = writer.buffered()[data_size_offset..]; |
| 2465 | std.mem.writeInt(u16, data_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(values_size)), .little); | 2464 | std.mem.writeInt(u16, data_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(values_size)), .little); |
| 2466 | 2465 | ||
| 2467 | if (has_number_value) { | 2466 | if (has_number_value) { |
| 2468 | const data_type_slice = buf.written()[data_type_offset..]; | 2467 | const data_type_slice = writer.buffered()[data_type_offset..]; |
| 2469 | std.mem.writeInt(u16, data_type_slice[0..@sizeOf(u16)], res.VersionNode.type_binary, .little); | 2468 | std.mem.writeInt(u16, data_type_slice[0..@sizeOf(u16)], res.VersionNode.type_binary, .little); |
| 2470 | } | 2469 | } |
| 2471 | 2470 | ||
| 2472 | if (node_type == .block) { | 2471 | if (node_type == .block) { |
| 2473 | const block = block_or_value; | 2472 | const block = block_or_value; |
| 2474 | for (block.children) |child| { | 2473 | for (block.children) |child| { |
| 2475 | try self.writeVersionNode(child, writer, buf); | 2474 | try self.writeVersionNode(child, writer); |
| 2476 | } | 2475 | } |
| 2477 | } | 2476 | } |
| 2478 | }, | 2477 | }, |
| 2479 | else => unreachable, | 2478 | else => unreachable, |
| 2480 | } | 2479 | } |
| 2481 | 2480 | ||
| 2482 | const node_and_children_size = buf.written().len - node_and_children_size_offset; | 2481 | const node_and_children_size = writer.buffered().len - node_and_children_size_offset; |
| 2483 | const node_and_children_size_slice = buf.written()[node_and_children_size_offset..]; | 2482 | const node_and_children_size_slice = writer.buffered()[node_and_children_size_offset..]; |
| 2484 | std.mem.writeInt(u16, node_and_children_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(node_and_children_size)), .little); | 2483 | std.mem.writeInt(u16, node_and_children_size_slice[0..@sizeOf(u16)], @as(u16, @intCast(node_and_children_size)), .little); |
| 2485 | } | 2484 | } |
| 2486 | 2485 | ||
| ... | @@ -2673,11 +2672,11 @@ pub const Compiler = struct { | ... | @@ -2673,11 +2672,11 @@ pub const Compiler = struct { |
| 2673 | return .{ .bytes = header_size, .padding_after_name = padding_after_name }; | 2672 | return .{ .bytes = header_size, .padding_after_name = padding_after_name }; |
| 2674 | } | 2673 | } |
| 2675 | 2674 | ||
| 2676 | pub fn writeAssertNoOverflow(self: ResourceHeader, writer: anytype) !void { | 2675 | pub fn writeAssertNoOverflow(self: ResourceHeader, writer: *std.Io.Writer) !void { |
| 2677 | return self.writeSizeInfo(writer, self.calcSize() catch unreachable); | 2676 | return self.writeSizeInfo(writer, self.calcSize() catch unreachable); |
| 2678 | } | 2677 | } |
| 2679 | 2678 | ||
| 2680 | pub fn write(self: ResourceHeader, writer: anytype, err_ctx: errors.DiagnosticsContext) !void { | 2679 | pub fn write(self: ResourceHeader, writer: *std.Io.Writer, err_ctx: errors.DiagnosticsContext) !void { |
| 2681 | const size_info = self.calcSize() catch { | 2680 | const size_info = self.calcSize() catch { |
| 2682 | try err_ctx.diagnostics.append(.{ | 2681 | try err_ctx.diagnostics.append(.{ |
| 2683 | .err = .resource_data_size_exceeds_max, | 2682 | .err = .resource_data_size_exceeds_max, |
| ... | @@ -2815,7 +2814,7 @@ pub const Compiler = struct { | ... | @@ -2815,7 +2814,7 @@ pub const Compiler = struct { |
| 2815 | return null; | 2814 | return null; |
| 2816 | } | 2815 | } |
| 2817 | 2816 | ||
| 2818 | pub fn writeEmptyResource(writer: anytype) !void { | 2817 | pub fn writeEmptyResource(writer: *std.Io.Writer) !void { |
| 2819 | const header = ResourceHeader{ | 2818 | const header = ResourceHeader{ |
| 2820 | .name_value = .{ .ordinal = 0 }, | 2819 | .name_value = .{ .ordinal = 0 }, |
| 2821 | .type_value = .{ .ordinal = 0 }, | 2820 | .type_value = .{ .ordinal = 0 }, |
| ... | @@ -2932,39 +2931,8 @@ pub const SearchDir = struct { | ... | @@ -2932,39 +2931,8 @@ pub const SearchDir = struct { |
| 2932 | } | 2931 | } |
| 2933 | }; | 2932 | }; |
| 2934 | 2933 | ||
| 2935 | /// Slurps the first `size` bytes read into `slurped_header` | ||
| 2936 | pub fn HeaderSlurpingReader(comptime size: usize, comptime ReaderType: anytype) type { | ||
| 2937 | return struct { | ||
| 2938 | child_reader: ReaderType, | ||
| 2939 | bytes_read: usize = 0, | ||
| 2940 | slurped_header: [size]u8 = [_]u8{0x00} ** size, | ||
| 2941 | |||
| 2942 | pub const Error = ReaderType.Error; | ||
| 2943 | pub const Reader = std.io.GenericReader(*@This(), Error, read); | ||
| 2944 | |||
| 2945 | pub fn read(self: *@This(), buf: []u8) Error!usize { | ||
| 2946 | const amt = try self.child_reader.read(buf); | ||
| 2947 | if (self.bytes_read < size) { | ||
| 2948 | const bytes_to_add = @min(amt, size - self.bytes_read); | ||
| 2949 | const end_index = self.bytes_read + bytes_to_add; | ||
| 2950 | @memcpy(self.slurped_header[self.bytes_read..end_index], buf[0..bytes_to_add]); | ||
| 2951 | } | ||
| 2952 | self.bytes_read +|= amt; | ||
| 2953 | return amt; | ||
| 2954 | } | ||
| 2955 | |||
| 2956 | pub fn reader(self: *@This()) Reader { | ||
| 2957 | return .{ .context = self }; | ||
| 2958 | } | ||
| 2959 | }; | ||
| 2960 | } | ||
| 2961 | |||
| 2962 | pub fn headerSlurpingReader(comptime size: usize, reader: anytype) HeaderSlurpingReader(size, @TypeOf(reader)) { | ||
| 2963 | return .{ .child_reader = reader }; | ||
| 2964 | } | ||
| 2965 | |||
| 2966 | pub const FontDir = struct { | 2934 | pub const FontDir = struct { |
| 2967 | fonts: std.ArrayListUnmanaged(Font) = .empty, | 2935 | fonts: std.ArrayList(Font) = .empty, |
| 2968 | /// To keep track of which ids are set and where they were set from | 2936 | /// To keep track of which ids are set and where they were set from |
| 2969 | ids: std.AutoHashMapUnmanaged(u16, Token) = .empty, | 2937 | ids: std.AutoHashMapUnmanaged(u16, Token) = .empty, |
| 2970 | 2938 | ||
| ... | @@ -2982,7 +2950,7 @@ pub const FontDir = struct { | ... | @@ -2982,7 +2950,7 @@ pub const FontDir = struct { |
| 2982 | try self.fonts.append(allocator, font); | 2950 | try self.fonts.append(allocator, font); |
| 2983 | } | 2951 | } |
| 2984 | 2952 | ||
| 2985 | pub fn writeResData(self: *FontDir, compiler: *Compiler, writer: anytype) !void { | 2953 | pub fn writeResData(self: *FontDir, compiler: *Compiler, writer: *std.Io.Writer) !void { |
| 2986 | if (self.fonts.items.len == 0) return; | 2954 | if (self.fonts.items.len == 0) return; |
| 2987 | 2955 | ||
| 2988 | // We know the number of fonts is limited to maxInt(u16) because fonts | 2956 | // We know the number of fonts is limited to maxInt(u16) because fonts |
| ... | @@ -3106,7 +3074,7 @@ pub const StringTable = struct { | ... | @@ -3106,7 +3074,7 @@ pub const StringTable = struct { |
| 3106 | blocks: std.AutoArrayHashMapUnmanaged(u16, Block) = .empty, | 3074 | blocks: std.AutoArrayHashMapUnmanaged(u16, Block) = .empty, |
| 3107 | 3075 | ||
| 3108 | pub const Block = struct { | 3076 | pub const Block = struct { |
| 3109 | strings: std.ArrayListUnmanaged(Token) = .empty, | 3077 | strings: std.ArrayList(Token) = .empty, |
| 3110 | set_indexes: std.bit_set.IntegerBitSet(16) = .{ .mask = 0 }, | 3078 | set_indexes: std.bit_set.IntegerBitSet(16) = .{ .mask = 0 }, |
| 3111 | memory_flags: MemoryFlags = MemoryFlags.defaults(res.RT.STRING), | 3079 | memory_flags: MemoryFlags = MemoryFlags.defaults(res.RT.STRING), |
| 3112 | characteristics: u32, | 3080 | characteristics: u32, |
| ... | @@ -3187,7 +3155,7 @@ pub const StringTable = struct { | ... | @@ -3187,7 +3155,7 @@ pub const StringTable = struct { |
| 3187 | try std.testing.expectEqualStrings("a", trimToDoubleNUL(u8, "a\x00\x00b")); | 3155 | try std.testing.expectEqualStrings("a", trimToDoubleNUL(u8, "a\x00\x00b")); |
| 3188 | } | 3156 | } |
| 3189 | 3157 | ||
| 3190 | pub fn writeResData(self: *Block, compiler: *Compiler, language: res.Language, block_id: u16, writer: anytype) !void { | 3158 | pub fn writeResData(self: *Block, compiler: *Compiler, language: res.Language, block_id: u16, writer: *std.Io.Writer) !void { |
| 3191 | var data_buffer: std.Io.Writer.Allocating = .init(compiler.allocator); | 3159 | var data_buffer: std.Io.Writer.Allocating = .init(compiler.allocator); |
| 3192 | defer data_buffer.deinit(); | 3160 | defer data_buffer.deinit(); |
| 3193 | const data_writer = &data_buffer.writer; | 3161 | const data_writer = &data_buffer.writer; |
lib/compiler/resinator/cvtres.zig+12-12| ... | @@ -43,7 +43,7 @@ pub const Resource = struct { | ... | @@ -43,7 +43,7 @@ pub const Resource = struct { |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | pub const ParsedResources = struct { | 45 | pub const ParsedResources = struct { |
| 46 | list: std.ArrayListUnmanaged(Resource) = .empty, | 46 | list: std.ArrayList(Resource) = .empty, |
| 47 | allocator: Allocator, | 47 | allocator: Allocator, |
| 48 | 48 | ||
| 49 | pub fn init(allocator: Allocator) ParsedResources { | 49 | pub fn init(allocator: Allocator) ParsedResources { |
| ... | @@ -157,7 +157,7 @@ pub fn parseNameOrOrdinal(allocator: Allocator, reader: *std.Io.Reader) !NameOrO | ... | @@ -157,7 +157,7 @@ pub fn parseNameOrOrdinal(allocator: Allocator, reader: *std.Io.Reader) !NameOrO |
| 157 | const ordinal_value = try reader.takeInt(u16, .little); | 157 | const ordinal_value = try reader.takeInt(u16, .little); |
| 158 | return .{ .ordinal = ordinal_value }; | 158 | return .{ .ordinal = ordinal_value }; |
| 159 | } | 159 | } |
| 160 | var name_buf = try std.ArrayListUnmanaged(u16).initCapacity(allocator, 16); | 160 | var name_buf = try std.ArrayList(u16).initCapacity(allocator, 16); |
| 161 | errdefer name_buf.deinit(allocator); | 161 | errdefer name_buf.deinit(allocator); |
| 162 | var code_unit = first_code_unit; | 162 | var code_unit = first_code_unit; |
| 163 | while (code_unit != 0) { | 163 | while (code_unit != 0) { |
| ... | @@ -373,7 +373,7 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons | ... | @@ -373,7 +373,7 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons |
| 373 | try writer.writeAll(string_table.bytes.items); | 373 | try writer.writeAll(string_table.bytes.items); |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | fn writeSymbol(writer: anytype, symbol: std.coff.Symbol) !void { | 376 | fn writeSymbol(writer: *std.Io.Writer, symbol: std.coff.Symbol) !void { |
| 377 | try writer.writeAll(&symbol.name); | 377 | try writer.writeAll(&symbol.name); |
| 378 | try writer.writeInt(u32, symbol.value, .little); | 378 | try writer.writeInt(u32, symbol.value, .little); |
| 379 | try writer.writeInt(u16, @intFromEnum(symbol.section_number), .little); | 379 | try writer.writeInt(u16, @intFromEnum(symbol.section_number), .little); |
| ... | @@ -383,7 +383,7 @@ fn writeSymbol(writer: anytype, symbol: std.coff.Symbol) !void { | ... | @@ -383,7 +383,7 @@ fn writeSymbol(writer: anytype, symbol: std.coff.Symbol) !void { |
| 383 | try writer.writeInt(u8, symbol.number_of_aux_symbols, .little); | 383 | try writer.writeInt(u8, symbol.number_of_aux_symbols, .little); |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | fn writeSectionDefinition(writer: anytype, def: std.coff.SectionDefinition) !void { | 386 | fn writeSectionDefinition(writer: *std.Io.Writer, def: std.coff.SectionDefinition) !void { |
| 387 | try writer.writeInt(u32, def.length, .little); | 387 | try writer.writeInt(u32, def.length, .little); |
| 388 | try writer.writeInt(u16, def.number_of_relocations, .little); | 388 | try writer.writeInt(u16, def.number_of_relocations, .little); |
| 389 | try writer.writeInt(u16, def.number_of_linenumbers, .little); | 389 | try writer.writeInt(u16, def.number_of_linenumbers, .little); |
| ... | @@ -417,7 +417,7 @@ pub const ResourceDirectoryEntry = extern struct { | ... | @@ -417,7 +417,7 @@ pub const ResourceDirectoryEntry = extern struct { |
| 417 | to_subdirectory: bool, | 417 | to_subdirectory: bool, |
| 418 | }, | 418 | }, |
| 419 | 419 | ||
| 420 | pub fn writeCoff(self: ResourceDirectoryEntry, writer: anytype) !void { | 420 | pub fn writeCoff(self: ResourceDirectoryEntry, writer: *std.Io.Writer) !void { |
| 421 | try writer.writeInt(u32, @bitCast(self.entry), .little); | 421 | try writer.writeInt(u32, @bitCast(self.entry), .little); |
| 422 | try writer.writeInt(u32, @bitCast(self.offset), .little); | 422 | try writer.writeInt(u32, @bitCast(self.offset), .little); |
| 423 | } | 423 | } |
| ... | @@ -435,7 +435,7 @@ const ResourceTree = struct { | ... | @@ -435,7 +435,7 @@ const ResourceTree = struct { |
| 435 | type_to_name_map: std.ArrayHashMapUnmanaged(NameOrOrdinal, NameToLanguageMap, NameOrOrdinalHashContext, true), | 435 | type_to_name_map: std.ArrayHashMapUnmanaged(NameOrOrdinal, NameToLanguageMap, NameOrOrdinalHashContext, true), |
| 436 | rsrc_string_table: std.ArrayHashMapUnmanaged(NameOrOrdinal, void, NameOrOrdinalHashContext, true), | 436 | rsrc_string_table: std.ArrayHashMapUnmanaged(NameOrOrdinal, void, NameOrOrdinalHashContext, true), |
| 437 | deduplicated_data: std.StringArrayHashMapUnmanaged(u32), | 437 | deduplicated_data: std.StringArrayHashMapUnmanaged(u32), |
| 438 | data_offsets: std.ArrayListUnmanaged(u32), | 438 | data_offsets: std.ArrayList(u32), |
| 439 | rsrc02_len: u32, | 439 | rsrc02_len: u32, |
| 440 | coff_options: CoffOptions, | 440 | coff_options: CoffOptions, |
| 441 | allocator: Allocator, | 441 | allocator: Allocator, |
| ... | @@ -675,13 +675,13 @@ const ResourceTree = struct { | ... | @@ -675,13 +675,13 @@ const ResourceTree = struct { |
| 675 | return &.{}; | 675 | return &.{}; |
| 676 | } | 676 | } |
| 677 | 677 | ||
| 678 | var level2_list: std.ArrayListUnmanaged(*const NameToLanguageMap) = .empty; | 678 | var level2_list: std.ArrayList(*const NameToLanguageMap) = .empty; |
| 679 | defer level2_list.deinit(allocator); | 679 | defer level2_list.deinit(allocator); |
| 680 | 680 | ||
| 681 | var level3_list: std.ArrayListUnmanaged(*const LanguageToResourceMap) = .empty; | 681 | var level3_list: std.ArrayList(*const LanguageToResourceMap) = .empty; |
| 682 | defer level3_list.deinit(allocator); | 682 | defer level3_list.deinit(allocator); |
| 683 | 683 | ||
| 684 | var resources_list: std.ArrayListUnmanaged(*const RelocatableResource) = .empty; | 684 | var resources_list: std.ArrayList(*const RelocatableResource) = .empty; |
| 685 | defer resources_list.deinit(allocator); | 685 | defer resources_list.deinit(allocator); |
| 686 | 686 | ||
| 687 | var relocations = Relocations.init(allocator); | 687 | var relocations = Relocations.init(allocator); |
| ... | @@ -896,7 +896,7 @@ const ResourceTree = struct { | ... | @@ -896,7 +896,7 @@ const ResourceTree = struct { |
| 896 | return symbols; | 896 | return symbols; |
| 897 | } | 897 | } |
| 898 | 898 | ||
| 899 | fn writeRelocation(writer: anytype, relocation: std.coff.Relocation) !void { | 899 | fn writeRelocation(writer: *std.Io.Writer, relocation: std.coff.Relocation) !void { |
| 900 | try writer.writeInt(u32, relocation.virtual_address, .little); | 900 | try writer.writeInt(u32, relocation.virtual_address, .little); |
| 901 | try writer.writeInt(u32, relocation.symbol_table_index, .little); | 901 | try writer.writeInt(u32, relocation.symbol_table_index, .little); |
| 902 | try writer.writeInt(u16, relocation.type, .little); | 902 | try writer.writeInt(u16, relocation.type, .little); |
| ... | @@ -928,7 +928,7 @@ const Relocation = struct { | ... | @@ -928,7 +928,7 @@ const Relocation = struct { |
| 928 | 928 | ||
| 929 | const Relocations = struct { | 929 | const Relocations = struct { |
| 930 | allocator: Allocator, | 930 | allocator: Allocator, |
| 931 | list: std.ArrayListUnmanaged(Relocation) = .empty, | 931 | list: std.ArrayList(Relocation) = .empty, |
| 932 | cur_symbol_index: u32 = 5, | 932 | cur_symbol_index: u32 = 5, |
| 933 | 933 | ||
| 934 | pub fn init(allocator: Allocator) Relocations { | 934 | pub fn init(allocator: Allocator) Relocations { |
| ... | @@ -952,7 +952,7 @@ const Relocations = struct { | ... | @@ -952,7 +952,7 @@ const Relocations = struct { |
| 952 | /// Does not do deduplication (only because there's no chance of duplicate strings in this | 952 | /// Does not do deduplication (only because there's no chance of duplicate strings in this |
| 953 | /// instance). | 953 | /// instance). |
| 954 | const StringTable = struct { | 954 | const StringTable = struct { |
| 955 | bytes: std.ArrayListUnmanaged(u8) = .empty, | 955 | bytes: std.ArrayList(u8) = .empty, |
| 956 | 956 | ||
| 957 | pub fn deinit(self: *StringTable, allocator: Allocator) void { | 957 | pub fn deinit(self: *StringTable, allocator: Allocator) void { |
| 958 | self.bytes.deinit(allocator); | 958 | self.bytes.deinit(allocator); |
lib/compiler/resinator/errors.zig+25-26| ... | @@ -15,10 +15,10 @@ const builtin = @import("builtin"); | ... | @@ -15,10 +15,10 @@ const builtin = @import("builtin"); |
| 15 | const native_endian = builtin.cpu.arch.endian(); | 15 | const native_endian = builtin.cpu.arch.endian(); |
| 16 | 16 | ||
| 17 | pub const Diagnostics = struct { | 17 | pub const Diagnostics = struct { |
| 18 | errors: std.ArrayListUnmanaged(ErrorDetails) = .empty, | 18 | errors: std.ArrayList(ErrorDetails) = .empty, |
| 19 | /// Append-only, cannot handle removing strings. | 19 | /// Append-only, cannot handle removing strings. |
| 20 | /// Expects to own all strings within the list. | 20 | /// Expects to own all strings within the list. |
| 21 | strings: std.ArrayListUnmanaged([]const u8) = .empty, | 21 | strings: std.ArrayList([]const u8) = .empty, |
| 22 | allocator: std.mem.Allocator, | 22 | allocator: std.mem.Allocator, |
| 23 | 23 | ||
| 24 | pub fn init(allocator: std.mem.Allocator) Diagnostics { | 24 | pub fn init(allocator: std.mem.Allocator) Diagnostics { |
| ... | @@ -256,7 +256,7 @@ pub const ErrorDetails = struct { | ... | @@ -256,7 +256,7 @@ pub const ErrorDetails = struct { |
| 256 | .{ "literal", "unquoted literal" }, | 256 | .{ "literal", "unquoted literal" }, |
| 257 | }); | 257 | }); |
| 258 | 258 | ||
| 259 | pub fn writeCommaSeparated(self: ExpectedTypes, writer: anytype) !void { | 259 | pub fn writeCommaSeparated(self: ExpectedTypes, writer: *std.Io.Writer) !void { |
| 260 | const struct_info = @typeInfo(ExpectedTypes).@"struct"; | 260 | const struct_info = @typeInfo(ExpectedTypes).@"struct"; |
| 261 | const num_real_fields = struct_info.fields.len - 1; | 261 | const num_real_fields = struct_info.fields.len - 1; |
| 262 | const num_padding_bits = @bitSizeOf(ExpectedTypes) - num_real_fields; | 262 | const num_padding_bits = @bitSizeOf(ExpectedTypes) - num_real_fields; |
| ... | @@ -441,7 +441,7 @@ pub const ErrorDetails = struct { | ... | @@ -441,7 +441,7 @@ pub const ErrorDetails = struct { |
| 441 | } }; | 441 | } }; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | pub fn render(self: ErrorDetails, writer: anytype, source: []const u8, strings: []const []const u8) !void { | 444 | pub fn render(self: ErrorDetails, writer: *std.Io.Writer, source: []const u8, strings: []const []const u8) !void { |
| 445 | switch (self.err) { | 445 | switch (self.err) { |
| 446 | .unfinished_string_literal => { | 446 | .unfinished_string_literal => { |
| 447 | return writer.print("unfinished string literal at '{f}', expected closing '\"'", .{self.fmtToken(source)}); | 447 | return writer.print("unfinished string literal at '{f}', expected closing '\"'", .{self.fmtToken(source)}); |
| ... | @@ -987,12 +987,14 @@ pub fn renderErrorMessage(writer: *std.io.Writer, tty_config: std.io.tty.Config, | ... | @@ -987,12 +987,14 @@ pub fn renderErrorMessage(writer: *std.io.Writer, tty_config: std.io.tty.Config, |
| 987 | if (corresponding_span != null and corresponding_file != null) { | 987 | if (corresponding_span != null and corresponding_file != null) { |
| 988 | var worth_printing_lines: bool = true; | 988 | var worth_printing_lines: bool = true; |
| 989 | var initial_lines_err: ?anyerror = null; | 989 | var initial_lines_err: ?anyerror = null; |
| 990 | var file_reader_buf: [max_source_line_bytes * 2]u8 = undefined; | ||
| 990 | var corresponding_lines: ?CorrespondingLines = CorrespondingLines.init( | 991 | var corresponding_lines: ?CorrespondingLines = CorrespondingLines.init( |
| 991 | cwd, | 992 | cwd, |
| 992 | err_details, | 993 | err_details, |
| 993 | source_line_for_display.line, | 994 | source_line_for_display.line, |
| 994 | corresponding_span.?, | 995 | corresponding_span.?, |
| 995 | corresponding_file.?, | 996 | corresponding_file.?, |
| 997 | &file_reader_buf, | ||
| 996 | ) catch |err| switch (err) { | 998 | ) catch |err| switch (err) { |
| 997 | error.NotWorthPrintingLines => blk: { | 999 | error.NotWorthPrintingLines => blk: { |
| 998 | worth_printing_lines = false; | 1000 | worth_printing_lines = false; |
| ... | @@ -1078,10 +1080,17 @@ const CorrespondingLines = struct { | ... | @@ -1078,10 +1080,17 @@ const CorrespondingLines = struct { |
| 1078 | at_eof: bool = false, | 1080 | at_eof: bool = false, |
| 1079 | span: SourceMappings.CorrespondingSpan, | 1081 | span: SourceMappings.CorrespondingSpan, |
| 1080 | file: std.fs.File, | 1082 | file: std.fs.File, |
| 1081 | buffered_reader: std.fs.File.Reader, | 1083 | file_reader: std.fs.File.Reader, |
| 1082 | code_page: SupportedCodePage, | 1084 | code_page: SupportedCodePage, |
| 1083 | 1085 | ||
| 1084 | pub fn init(cwd: std.fs.Dir, err_details: ErrorDetails, line_for_comparison: []const u8, corresponding_span: SourceMappings.CorrespondingSpan, corresponding_file: []const u8) !CorrespondingLines { | 1086 | pub fn init( |
| 1087 | cwd: std.fs.Dir, | ||
| 1088 | err_details: ErrorDetails, | ||
| 1089 | line_for_comparison: []const u8, | ||
| 1090 | corresponding_span: SourceMappings.CorrespondingSpan, | ||
| 1091 | corresponding_file: []const u8, | ||
| 1092 | file_reader_buf: []u8, | ||
| 1093 | ) !CorrespondingLines { | ||
| 1085 | // We don't do line comparison for this error, so don't print the note if the line | 1094 | // We don't do line comparison for this error, so don't print the note if the line |
| 1086 | // number is different | 1095 | // number is different |
| 1087 | if (err_details.err == .string_literal_too_long and err_details.token.line_number != corresponding_span.start_line) { | 1096 | if (err_details.err == .string_literal_too_long and err_details.token.line_number != corresponding_span.start_line) { |
| ... | @@ -1096,17 +1105,14 @@ const CorrespondingLines = struct { | ... | @@ -1096,17 +1105,14 @@ const CorrespondingLines = struct { |
| 1096 | var corresponding_lines = CorrespondingLines{ | 1105 | var corresponding_lines = CorrespondingLines{ |
| 1097 | .span = corresponding_span, | 1106 | .span = corresponding_span, |
| 1098 | .file = try utils.openFileNotDir(cwd, corresponding_file, .{}), | 1107 | .file = try utils.openFileNotDir(cwd, corresponding_file, .{}), |
| 1099 | .buffered_reader = undefined, | ||
| 1100 | .code_page = err_details.code_page, | 1108 | .code_page = err_details.code_page, |
| 1109 | .file_reader = undefined, | ||
| 1101 | }; | 1110 | }; |
| 1102 | corresponding_lines.buffered_reader = corresponding_lines.file.reader(&.{}); | 1111 | corresponding_lines.file_reader = corresponding_lines.file.reader(file_reader_buf); |
| 1103 | errdefer corresponding_lines.deinit(); | 1112 | errdefer corresponding_lines.deinit(); |
| 1104 | 1113 | ||
| 1105 | var writer: std.Io.Writer = .fixed(&corresponding_lines.line_buf); | ||
| 1106 | |||
| 1107 | try corresponding_lines.writeLineFromStreamVerbatim( | 1114 | try corresponding_lines.writeLineFromStreamVerbatim( |
| 1108 | &writer, | 1115 | &corresponding_lines.file_reader.interface, |
| 1109 | corresponding_lines.buffered_reader.interface.adaptToOldInterface(), | ||
| 1110 | corresponding_span.start_line, | 1116 | corresponding_span.start_line, |
| 1111 | ); | 1117 | ); |
| 1112 | 1118 | ||
| ... | @@ -1144,11 +1150,8 @@ const CorrespondingLines = struct { | ... | @@ -1144,11 +1150,8 @@ const CorrespondingLines = struct { |
| 1144 | self.line_len = 0; | 1150 | self.line_len = 0; |
| 1145 | self.visual_line_len = 0; | 1151 | self.visual_line_len = 0; |
| 1146 | 1152 | ||
| 1147 | var writer: std.Io.Writer = .fixed(&self.line_buf); | ||
| 1148 | |||
| 1149 | try self.writeLineFromStreamVerbatim( | 1153 | try self.writeLineFromStreamVerbatim( |
| 1150 | &writer, | 1154 | &self.file_reader.interface, |
| 1151 | self.buffered_reader.interface.adaptToOldInterface(), | ||
| 1152 | self.line_num, | 1155 | self.line_num, |
| 1153 | ); | 1156 | ); |
| 1154 | 1157 | ||
| ... | @@ -1162,7 +1165,7 @@ const CorrespondingLines = struct { | ... | @@ -1162,7 +1165,7 @@ const CorrespondingLines = struct { |
| 1162 | return visual_line; | 1165 | return visual_line; |
| 1163 | } | 1166 | } |
| 1164 | 1167 | ||
| 1165 | fn writeLineFromStreamVerbatim(self: *CorrespondingLines, writer: *std.Io.Writer, input: anytype, line_num: usize) !void { | 1168 | fn writeLineFromStreamVerbatim(self: *CorrespondingLines, input: *std.Io.Reader, line_num: usize) !void { |
| 1166 | while (try readByteOrEof(input)) |byte| { | 1169 | while (try readByteOrEof(input)) |byte| { |
| 1167 | switch (byte) { | 1170 | switch (byte) { |
| 1168 | '\n', '\r' => { | 1171 | '\n', '\r' => { |
| ... | @@ -1182,13 +1185,9 @@ const CorrespondingLines = struct { | ... | @@ -1182,13 +1185,9 @@ const CorrespondingLines = struct { |
| 1182 | } | 1185 | } |
| 1183 | }, | 1186 | }, |
| 1184 | else => { | 1187 | else => { |
| 1185 | if (self.line_num == line_num) { | 1188 | if (self.line_num == line_num and self.line_len < self.line_buf.len) { |
| 1186 | if (writer.writeByte(byte)) { | 1189 | self.line_buf[self.line_len] = byte; |
| 1187 | self.line_len += 1; | 1190 | self.line_len += 1; |
| 1188 | } else |err| switch (err) { | ||
| 1189 | error.WriteFailed => {}, | ||
| 1190 | else => |e| return e, | ||
| 1191 | } | ||
| 1192 | } | 1191 | } |
| 1193 | }, | 1192 | }, |
| 1194 | } | 1193 | } |
| ... | @@ -1199,8 +1198,8 @@ const CorrespondingLines = struct { | ... | @@ -1199,8 +1198,8 @@ const CorrespondingLines = struct { |
| 1199 | self.line_num += 1; | 1198 | self.line_num += 1; |
| 1200 | } | 1199 | } |
| 1201 | 1200 | ||
| 1202 | fn readByteOrEof(reader: anytype) !?u8 { | 1201 | fn readByteOrEof(reader: *std.Io.Reader) !?u8 { |
| 1203 | return reader.readByte() catch |err| switch (err) { | 1202 | return reader.takeByte() catch |err| switch (err) { |
| 1204 | error.EndOfStream => return null, | 1203 | error.EndOfStream => return null, |
| 1205 | else => |e| return e, | 1204 | else => |e| return e, |
| 1206 | }; | 1205 | }; |
lib/compiler/resinator/ico.zig+43-57| ... | @@ -8,80 +8,66 @@ const std = @import("std"); | ... | @@ -8,80 +8,66 @@ const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 9 | const native_endian = builtin.cpu.arch.endian(); | 9 | const native_endian = builtin.cpu.arch.endian(); |
| 10 | 10 | ||
| 11 | pub const ReadError = std.mem.Allocator.Error || error{ InvalidHeader, InvalidImageType, ImpossibleDataSize, UnexpectedEOF, ReadError }; | 11 | pub const ReadError = std.mem.Allocator.Error || error{ InvalidHeader, InvalidImageType, ImpossibleDataSize, UnexpectedEOF, ReadFailed }; |
| 12 | 12 | ||
| 13 | pub fn read(allocator: std.mem.Allocator, reader: anytype, max_size: u64) ReadError!IconDir { | 13 | pub fn read(allocator: std.mem.Allocator, reader: *std.Io.Reader, max_size: u64) ReadError!IconDir { |
| 14 | // Some Reader implementations have an empty ReadError error set which would | 14 | return readInner(allocator, reader, max_size) catch |err| switch (err) { |
| 15 | // cause 'unreachable else' if we tried to use an else in the switch, so we | 15 | error.OutOfMemory, |
| 16 | // need to detect this case and not try to translate to ReadError | 16 | error.InvalidHeader, |
| 17 | const anyerror_reader_errorset = @TypeOf(reader).Error == anyerror; | 17 | error.InvalidImageType, |
| 18 | const empty_reader_errorset = @typeInfo(@TypeOf(reader).Error).error_set == null or @typeInfo(@TypeOf(reader).Error).error_set.?.len == 0; | 18 | error.ImpossibleDataSize, |
| 19 | if (empty_reader_errorset and !anyerror_reader_errorset) { | 19 | error.ReadFailed, |
| 20 | return readAnyError(allocator, reader, max_size) catch |err| switch (err) { | 20 | => |e| return e, |
| 21 | error.EndOfStream => error.UnexpectedEOF, | 21 | error.EndOfStream => error.UnexpectedEOF, |
| 22 | else => |e| return e, | 22 | }; |
| 23 | }; | ||
| 24 | } else { | ||
| 25 | return readAnyError(allocator, reader, max_size) catch |err| switch (err) { | ||
| 26 | error.OutOfMemory, | ||
| 27 | error.InvalidHeader, | ||
| 28 | error.InvalidImageType, | ||
| 29 | error.ImpossibleDataSize, | ||
| 30 | => |e| return e, | ||
| 31 | error.EndOfStream => error.UnexpectedEOF, | ||
| 32 | // The remaining errors are dependent on the `reader`, so | ||
| 33 | // we just translate them all to generic ReadError | ||
| 34 | else => error.ReadError, | ||
| 35 | }; | ||
| 36 | } | ||
| 37 | } | 23 | } |
| 38 | 24 | ||
| 39 | // TODO: This seems like a somewhat strange pattern, could be a better way | 25 | // TODO: This seems like a somewhat strange pattern, could be a better way |
| 40 | // to do this. Maybe it makes more sense to handle the translation | 26 | // to do this. Maybe it makes more sense to handle the translation |
| 41 | // at the call site instead of having a helper function here. | 27 | // at the call site instead of having a helper function here. |
| 42 | pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64) !IconDir { | 28 | fn readInner(allocator: std.mem.Allocator, reader: *std.Io.Reader, max_size: u64) !IconDir { |
| 43 | const reserved = try reader.readInt(u16, .little); | 29 | const reserved = try reader.takeInt(u16, .little); |
| 44 | if (reserved != 0) { | 30 | if (reserved != 0) { |
| 45 | return error.InvalidHeader; | 31 | return error.InvalidHeader; |
| 46 | } | 32 | } |
| 47 | 33 | ||
| 48 | const image_type = reader.readEnum(ImageType, .little) catch |err| switch (err) { | 34 | const image_type = reader.takeEnum(ImageType, .little) catch |err| switch (err) { |
| 49 | error.InvalidValue => return error.InvalidImageType, | 35 | error.InvalidEnumTag => return error.InvalidImageType, |
| 50 | else => |e| return e, | 36 | else => |e| return e, |
| 51 | }; | 37 | }; |
| 52 | 38 | ||
| 53 | const num_images = try reader.readInt(u16, .little); | 39 | const num_images = try reader.takeInt(u16, .little); |
| 54 | 40 | ||
| 55 | // To avoid over-allocation in the case of a file that says it has way more | 41 | // To avoid over-allocation in the case of a file that says it has way more |
| 56 | // entries than it actually does, we use an ArrayList with a conservatively | 42 | // entries than it actually does, we use an ArrayList with a conservatively |
| 57 | // limited initial capacity instead of allocating the entire slice at once. | 43 | // limited initial capacity instead of allocating the entire slice at once. |
| 58 | const initial_capacity = @min(num_images, 8); | 44 | const initial_capacity = @min(num_images, 8); |
| 59 | var entries = try std.array_list.Managed(Entry).initCapacity(allocator, initial_capacity); | 45 | var entries = try std.ArrayList(Entry).initCapacity(allocator, initial_capacity); |
| 60 | errdefer entries.deinit(); | 46 | errdefer entries.deinit(allocator); |
| 61 | 47 | ||
| 62 | var i: usize = 0; | 48 | var i: usize = 0; |
| 63 | while (i < num_images) : (i += 1) { | 49 | while (i < num_images) : (i += 1) { |
| 64 | var entry: Entry = undefined; | 50 | var entry: Entry = undefined; |
| 65 | entry.width = try reader.readByte(); | 51 | entry.width = try reader.takeByte(); |
| 66 | entry.height = try reader.readByte(); | 52 | entry.height = try reader.takeByte(); |
| 67 | entry.num_colors = try reader.readByte(); | 53 | entry.num_colors = try reader.takeByte(); |
| 68 | entry.reserved = try reader.readByte(); | 54 | entry.reserved = try reader.takeByte(); |
| 69 | switch (image_type) { | 55 | switch (image_type) { |
| 70 | .icon => { | 56 | .icon => { |
| 71 | entry.type_specific_data = .{ .icon = .{ | 57 | entry.type_specific_data = .{ .icon = .{ |
| 72 | .color_planes = try reader.readInt(u16, .little), | 58 | .color_planes = try reader.takeInt(u16, .little), |
| 73 | .bits_per_pixel = try reader.readInt(u16, .little), | 59 | .bits_per_pixel = try reader.takeInt(u16, .little), |
| 74 | } }; | 60 | } }; |
| 75 | }, | 61 | }, |
| 76 | .cursor => { | 62 | .cursor => { |
| 77 | entry.type_specific_data = .{ .cursor = .{ | 63 | entry.type_specific_data = .{ .cursor = .{ |
| 78 | .hotspot_x = try reader.readInt(u16, .little), | 64 | .hotspot_x = try reader.takeInt(u16, .little), |
| 79 | .hotspot_y = try reader.readInt(u16, .little), | 65 | .hotspot_y = try reader.takeInt(u16, .little), |
| 80 | } }; | 66 | } }; |
| 81 | }, | 67 | }, |
| 82 | } | 68 | } |
| 83 | entry.data_size_in_bytes = try reader.readInt(u32, .little); | 69 | entry.data_size_in_bytes = try reader.takeInt(u32, .little); |
| 84 | entry.data_offset_from_start_of_file = try reader.readInt(u32, .little); | 70 | entry.data_offset_from_start_of_file = try reader.takeInt(u32, .little); |
| 85 | // Validate that the offset/data size is feasible | 71 | // Validate that the offset/data size is feasible |
| 86 | if (@as(u64, entry.data_offset_from_start_of_file) + entry.data_size_in_bytes > max_size) { | 72 | if (@as(u64, entry.data_offset_from_start_of_file) + entry.data_size_in_bytes > max_size) { |
| 87 | return error.ImpossibleDataSize; | 73 | return error.ImpossibleDataSize; |
| ... | @@ -101,12 +87,12 @@ pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64 | ... | @@ -101,12 +87,12 @@ pub fn readAnyError(allocator: std.mem.Allocator, reader: anytype, max_size: u64 |
| 101 | if (entry.data_size_in_bytes < 16) { | 87 | if (entry.data_size_in_bytes < 16) { |
| 102 | return error.ImpossibleDataSize; | 88 | return error.ImpossibleDataSize; |
| 103 | } | 89 | } |
| 104 | try entries.append(entry); | 90 | try entries.append(allocator, entry); |
| 105 | } | 91 | } |
| 106 | 92 | ||
| 107 | return .{ | 93 | return .{ |
| 108 | .image_type = image_type, | 94 | .image_type = image_type, |
| 109 | .entries = try entries.toOwnedSlice(), | 95 | .entries = try entries.toOwnedSlice(allocator), |
| 110 | .allocator = allocator, | 96 | .allocator = allocator, |
| 111 | }; | 97 | }; |
| 112 | } | 98 | } |
| ... | @@ -135,7 +121,7 @@ pub const IconDir = struct { | ... | @@ -135,7 +121,7 @@ pub const IconDir = struct { |
| 135 | return @intCast(IconDir.res_header_byte_len + self.entries.len * Entry.res_byte_len); | 121 | return @intCast(IconDir.res_header_byte_len + self.entries.len * Entry.res_byte_len); |
| 136 | } | 122 | } |
| 137 | 123 | ||
| 138 | pub fn writeResData(self: IconDir, writer: anytype, first_image_id: u16) !void { | 124 | pub fn writeResData(self: IconDir, writer: *std.Io.Writer, first_image_id: u16) !void { |
| 139 | try writer.writeInt(u16, 0, .little); | 125 | try writer.writeInt(u16, 0, .little); |
| 140 | try writer.writeInt(u16, @intFromEnum(self.image_type), .little); | 126 | try writer.writeInt(u16, @intFromEnum(self.image_type), .little); |
| 141 | // We know that entries.len must fit into a u16 | 127 | // We know that entries.len must fit into a u16 |
| ... | @@ -173,7 +159,7 @@ pub const Entry = struct { | ... | @@ -173,7 +159,7 @@ pub const Entry = struct { |
| 173 | 159 | ||
| 174 | pub const res_byte_len = 14; | 160 | pub const res_byte_len = 14; |
| 175 | 161 | ||
| 176 | pub fn writeResData(self: Entry, writer: anytype, id: u16) !void { | 162 | pub fn writeResData(self: Entry, writer: *std.Io.Writer, id: u16) !void { |
| 177 | switch (self.type_specific_data) { | 163 | switch (self.type_specific_data) { |
| 178 | .icon => |icon_data| { | 164 | .icon => |icon_data| { |
| 179 | try writer.writeInt(u8, @as(u8, @truncate(self.width)), .little); | 165 | try writer.writeInt(u8, @as(u8, @truncate(self.width)), .little); |
| ... | @@ -198,8 +184,8 @@ pub const Entry = struct { | ... | @@ -198,8 +184,8 @@ pub const Entry = struct { |
| 198 | 184 | ||
| 199 | test "icon" { | 185 | test "icon" { |
| 200 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; | 186 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 201 | var fbs = std.io.fixedBufferStream(data); | 187 | var fbs: std.Io.Reader = .fixed(data); |
| 202 | const icon = try read(std.testing.allocator, fbs.reader(), data.len); | 188 | const icon = try read(std.testing.allocator, &fbs, data.len); |
| 203 | defer icon.deinit(); | 189 | defer icon.deinit(); |
| 204 | 190 | ||
| 205 | try std.testing.expectEqual(ImageType.icon, icon.image_type); | 191 | try std.testing.expectEqual(ImageType.icon, icon.image_type); |
| ... | @@ -211,26 +197,26 @@ test "icon too many images" { | ... | @@ -211,26 +197,26 @@ test "icon too many images" { |
| 211 | // it's not possible to hit EOF when looking for more RESDIR structures, since they are | 197 | // it's not possible to hit EOF when looking for more RESDIR structures, since they are |
| 212 | // themselves 16 bytes long, so we'll always hit ImpossibleDataSize instead. | 198 | // themselves 16 bytes long, so we'll always hit ImpossibleDataSize instead. |
| 213 | const data = "\x00\x00\x01\x00\x02\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; | 199 | const data = "\x00\x00\x01\x00\x02\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 214 | var fbs = std.io.fixedBufferStream(data); | 200 | var fbs: std.Io.Reader = .fixed(data); |
| 215 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | 201 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); |
| 216 | } | 202 | } |
| 217 | 203 | ||
| 218 | test "icon data size past EOF" { | 204 | test "icon data size past EOF" { |
| 219 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x01\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; | 205 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x01\x00\x00\x16\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 220 | var fbs = std.io.fixedBufferStream(data); | 206 | var fbs: std.Io.Reader = .fixed(data); |
| 221 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | 207 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); |
| 222 | } | 208 | } |
| 223 | 209 | ||
| 224 | test "icon data offset past EOF" { | 210 | test "icon data offset past EOF" { |
| 225 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x17\x00\x00\x00" ++ [_]u8{0} ** 16; | 211 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x10\x00\x00\x00\x17\x00\x00\x00" ++ [_]u8{0} ** 16; |
| 226 | var fbs = std.io.fixedBufferStream(data); | 212 | var fbs: std.Io.Reader = .fixed(data); |
| 227 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | 213 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); |
| 228 | } | 214 | } |
| 229 | 215 | ||
| 230 | test "icon data size too small" { | 216 | test "icon data size too small" { |
| 231 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x0F\x00\x00\x00\x16\x00\x00\x00"; | 217 | const data = "\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x10\x00\x0F\x00\x00\x00\x16\x00\x00\x00"; |
| 232 | var fbs = std.io.fixedBufferStream(data); | 218 | var fbs: std.Io.Reader = .fixed(data); |
| 233 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, fbs.reader(), data.len)); | 219 | try std.testing.expectError(error.ImpossibleDataSize, read(std.testing.allocator, &fbs, data.len)); |
| 234 | } | 220 | } |
| 235 | 221 | ||
| 236 | pub const ImageFormat = enum(u2) { | 222 | pub const ImageFormat = enum(u2) { |
lib/compiler/resinator/lang.zig+6-5| ... | @@ -119,6 +119,7 @@ test tagToId { | ... | @@ -119,6 +119,7 @@ test tagToId { |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | test "exhaustive tagToId" { | 121 | test "exhaustive tagToId" { |
| 122 | @setEvalBranchQuota(2000); | ||
| 122 | inline for (@typeInfo(LanguageId).@"enum".fields) |field| { | 123 | inline for (@typeInfo(LanguageId).@"enum".fields) |field| { |
| 123 | const id = tagToId(field.name) catch |err| { | 124 | const id = tagToId(field.name) catch |err| { |
| 124 | std.debug.print("tag: {s}\n", .{field.name}); | 125 | std.debug.print("tag: {s}\n", .{field.name}); |
| ... | @@ -131,8 +132,8 @@ test "exhaustive tagToId" { | ... | @@ -131,8 +132,8 @@ test "exhaustive tagToId" { |
| 131 | } | 132 | } |
| 132 | var buf: [32]u8 = undefined; | 133 | var buf: [32]u8 = undefined; |
| 133 | inline for (valid_alternate_sorts) |parsed_sort| { | 134 | inline for (valid_alternate_sorts) |parsed_sort| { |
| 134 | var fbs = std.io.fixedBufferStream(&buf); | 135 | var fbs: std.Io.Writer = .fixed(&buf); |
| 135 | const writer = fbs.writer(); | 136 | const writer = &fbs; |
| 136 | writer.writeAll(parsed_sort.language_code) catch unreachable; | 137 | writer.writeAll(parsed_sort.language_code) catch unreachable; |
| 137 | writer.writeAll("-") catch unreachable; | 138 | writer.writeAll("-") catch unreachable; |
| 138 | writer.writeAll(parsed_sort.country_code.?) catch unreachable; | 139 | writer.writeAll(parsed_sort.country_code.?) catch unreachable; |
| ... | @@ -146,12 +147,12 @@ test "exhaustive tagToId" { | ... | @@ -146,12 +147,12 @@ test "exhaustive tagToId" { |
| 146 | break :field name_buf; | 147 | break :field name_buf; |
| 147 | }; | 148 | }; |
| 148 | const expected = @field(LanguageId, &expected_field_name); | 149 | const expected = @field(LanguageId, &expected_field_name); |
| 149 | const id = tagToId(fbs.getWritten()) catch |err| { | 150 | const id = tagToId(fbs.buffered()) catch |err| { |
| 150 | std.debug.print("tag: {s}\n", .{fbs.getWritten()}); | 151 | std.debug.print("tag: {s}\n", .{fbs.buffered()}); |
| 151 | return err; | 152 | return err; |
| 152 | }; | 153 | }; |
| 153 | try std.testing.expectEqual(expected, id orelse { | 154 | try std.testing.expectEqual(expected, id orelse { |
| 154 | std.debug.print("tag: {s}, expected: {}, got null\n", .{ fbs.getWritten(), expected }); | 155 | std.debug.print("tag: {s}, expected: {}, got null\n", .{ fbs.buffered(), expected }); |
| 155 | return error.TestExpectedEqual; | 156 | return error.TestExpectedEqual; |
| 156 | }); | 157 | }); |
| 157 | } | 158 | } |
lib/compiler/resinator/literals.zig+22-22| ... | @@ -469,8 +469,8 @@ pub fn parseQuotedString( | ... | @@ -469,8 +469,8 @@ pub fn parseQuotedString( |
| 469 | const T = if (literal_type == .ascii) u8 else u16; | 469 | const T = if (literal_type == .ascii) u8 else u16; |
| 470 | std.debug.assert(bytes.slice.len >= 2); // must at least have 2 double quote chars | 470 | std.debug.assert(bytes.slice.len >= 2); // must at least have 2 double quote chars |
| 471 | 471 | ||
| 472 | var buf = try std.array_list.Managed(T).initCapacity(allocator, bytes.slice.len); | 472 | var buf = try std.ArrayList(T).initCapacity(allocator, bytes.slice.len); |
| 473 | errdefer buf.deinit(); | 473 | errdefer buf.deinit(allocator); |
| 474 | 474 | ||
| 475 | var iterative_parser = IterativeStringParser.init(bytes, options); | 475 | var iterative_parser = IterativeStringParser.init(bytes, options); |
| 476 | 476 | ||
| ... | @@ -480,13 +480,13 @@ pub fn parseQuotedString( | ... | @@ -480,13 +480,13 @@ pub fn parseQuotedString( |
| 480 | .ascii => switch (options.output_code_page) { | 480 | .ascii => switch (options.output_code_page) { |
| 481 | .windows1252 => { | 481 | .windows1252 => { |
| 482 | if (parsed.from_escaped_integer) { | 482 | if (parsed.from_escaped_integer) { |
| 483 | try buf.append(@truncate(c)); | 483 | try buf.append(allocator, @truncate(c)); |
| 484 | } else if (windows1252.bestFitFromCodepoint(c)) |best_fit| { | 484 | } else if (windows1252.bestFitFromCodepoint(c)) |best_fit| { |
| 485 | try buf.append(best_fit); | 485 | try buf.append(allocator, best_fit); |
| 486 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid) { | 486 | } else if (c < 0x10000 or c == code_pages.Codepoint.invalid) { |
| 487 | try buf.append('?'); | 487 | try buf.append(allocator, '?'); |
| 488 | } else { | 488 | } else { |
| 489 | try buf.appendSlice("??"); | 489 | try buf.appendSlice(allocator, "??"); |
| 490 | } | 490 | } |
| 491 | }, | 491 | }, |
| 492 | .utf8 => { | 492 | .utf8 => { |
| ... | @@ -500,35 +500,35 @@ pub fn parseQuotedString( | ... | @@ -500,35 +500,35 @@ pub fn parseQuotedString( |
| 500 | } | 500 | } |
| 501 | var utf8_buf: [4]u8 = undefined; | 501 | var utf8_buf: [4]u8 = undefined; |
| 502 | const utf8_len = std.unicode.utf8Encode(codepoint_to_encode, &utf8_buf) catch unreachable; | 502 | const utf8_len = std.unicode.utf8Encode(codepoint_to_encode, &utf8_buf) catch unreachable; |
| 503 | try buf.appendSlice(utf8_buf[0..utf8_len]); | 503 | try buf.appendSlice(allocator, utf8_buf[0..utf8_len]); |
| 504 | }, | 504 | }, |
| 505 | }, | 505 | }, |
| 506 | .wide => { | 506 | .wide => { |
| 507 | // Parsing any string type as a wide string is handled separately, see parseQuotedStringAsWideString | 507 | // Parsing any string type as a wide string is handled separately, see parseQuotedStringAsWideString |
| 508 | std.debug.assert(iterative_parser.declared_string_type == .wide); | 508 | std.debug.assert(iterative_parser.declared_string_type == .wide); |
| 509 | if (parsed.from_escaped_integer) { | 509 | if (parsed.from_escaped_integer) { |
| 510 | try buf.append(std.mem.nativeToLittle(u16, @truncate(c))); | 510 | try buf.append(allocator, std.mem.nativeToLittle(u16, @truncate(c))); |
| 511 | } else if (c == code_pages.Codepoint.invalid) { | 511 | } else if (c == code_pages.Codepoint.invalid) { |
| 512 | try buf.append(std.mem.nativeToLittle(u16, '�')); | 512 | try buf.append(allocator, std.mem.nativeToLittle(u16, '�')); |
| 513 | } else if (c < 0x10000) { | 513 | } else if (c < 0x10000) { |
| 514 | const short: u16 = @intCast(c); | 514 | const short: u16 = @intCast(c); |
| 515 | try buf.append(std.mem.nativeToLittle(u16, short)); | 515 | try buf.append(allocator, std.mem.nativeToLittle(u16, short)); |
| 516 | } else { | 516 | } else { |
| 517 | if (!parsed.escaped_surrogate_pair) { | 517 | if (!parsed.escaped_surrogate_pair) { |
| 518 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; | 518 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; |
| 519 | try buf.append(std.mem.nativeToLittle(u16, high)); | 519 | try buf.append(allocator, std.mem.nativeToLittle(u16, high)); |
| 520 | } | 520 | } |
| 521 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; | 521 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; |
| 522 | try buf.append(std.mem.nativeToLittle(u16, low)); | 522 | try buf.append(allocator, std.mem.nativeToLittle(u16, low)); |
| 523 | } | 523 | } |
| 524 | }, | 524 | }, |
| 525 | } | 525 | } |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | if (literal_type == .wide) { | 528 | if (literal_type == .wide) { |
| 529 | return buf.toOwnedSliceSentinel(0); | 529 | return buf.toOwnedSliceSentinel(allocator, 0); |
| 530 | } else { | 530 | } else { |
| 531 | return buf.toOwnedSlice(); | 531 | return buf.toOwnedSlice(allocator); |
| 532 | } | 532 | } |
| 533 | } | 533 | } |
| 534 | 534 | ||
| ... | @@ -564,8 +564,8 @@ pub fn parseQuotedStringAsWideString(allocator: std.mem.Allocator, bytes: Source | ... | @@ -564,8 +564,8 @@ pub fn parseQuotedStringAsWideString(allocator: std.mem.Allocator, bytes: Source |
| 564 | // Note: We're only handling the case of parsing an ASCII string into a wide string from here on out. | 564 | // Note: We're only handling the case of parsing an ASCII string into a wide string from here on out. |
| 565 | // TODO: The logic below is similar to that in AcceleratorKeyCodepointTranslator, might be worth merging the two | 565 | // TODO: The logic below is similar to that in AcceleratorKeyCodepointTranslator, might be worth merging the two |
| 566 | 566 | ||
| 567 | var buf = try std.array_list.Managed(u16).initCapacity(allocator, bytes.slice.len); | 567 | var buf = try std.ArrayList(u16).initCapacity(allocator, bytes.slice.len); |
| 568 | errdefer buf.deinit(); | 568 | errdefer buf.deinit(allocator); |
| 569 | 569 | ||
| 570 | var iterative_parser = IterativeStringParser.init(bytes, options); | 570 | var iterative_parser = IterativeStringParser.init(bytes, options); |
| 571 | 571 | ||
| ... | @@ -578,23 +578,23 @@ pub fn parseQuotedStringAsWideString(allocator: std.mem.Allocator, bytes: Source | ... | @@ -578,23 +578,23 @@ pub fn parseQuotedStringAsWideString(allocator: std.mem.Allocator, bytes: Source |
| 578 | .windows1252 => windows1252.toCodepoint(byte_to_interpret), | 578 | .windows1252 => windows1252.toCodepoint(byte_to_interpret), |
| 579 | .utf8 => if (byte_to_interpret > 0x7F) '�' else byte_to_interpret, | 579 | .utf8 => if (byte_to_interpret > 0x7F) '�' else byte_to_interpret, |
| 580 | }; | 580 | }; |
| 581 | try buf.append(std.mem.nativeToLittle(u16, code_unit_to_encode)); | 581 | try buf.append(allocator, std.mem.nativeToLittle(u16, code_unit_to_encode)); |
| 582 | } else if (c == code_pages.Codepoint.invalid) { | 582 | } else if (c == code_pages.Codepoint.invalid) { |
| 583 | try buf.append(std.mem.nativeToLittle(u16, '�')); | 583 | try buf.append(allocator, std.mem.nativeToLittle(u16, '�')); |
| 584 | } else if (c < 0x10000) { | 584 | } else if (c < 0x10000) { |
| 585 | const short: u16 = @intCast(c); | 585 | const short: u16 = @intCast(c); |
| 586 | try buf.append(std.mem.nativeToLittle(u16, short)); | 586 | try buf.append(allocator, std.mem.nativeToLittle(u16, short)); |
| 587 | } else { | 587 | } else { |
| 588 | if (!parsed.escaped_surrogate_pair) { | 588 | if (!parsed.escaped_surrogate_pair) { |
| 589 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; | 589 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; |
| 590 | try buf.append(std.mem.nativeToLittle(u16, high)); | 590 | try buf.append(allocator, std.mem.nativeToLittle(u16, high)); |
| 591 | } | 591 | } |
| 592 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; | 592 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; |
| 593 | try buf.append(std.mem.nativeToLittle(u16, low)); | 593 | try buf.append(allocator, std.mem.nativeToLittle(u16, low)); |
| 594 | } | 594 | } |
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | return buf.toOwnedSliceSentinel(0); | 597 | return buf.toOwnedSliceSentinel(allocator, 0); |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | test "parse quoted ascii string" { | 600 | test "parse quoted ascii string" { |
lib/compiler/resinator/main.zig+23-27| ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const removeComments = @import("comments.zig").removeComments; | 3 | const removeComments = @import("comments.zig").removeComments; |
| 4 | const parseAndRemoveLineCommands = @import("source_mapping.zig").parseAndRemoveLineCommands; | 4 | const parseAndRemoveLineCommands = @import("source_mapping.zig").parseAndRemoveLineCommands; |
| 5 | const compile = @import("compile.zig").compile; | 5 | const compile = @import("compile.zig").compile; |
| 6 | const Dependencies = @import("compile.zig").Dependencies; | ||
| 6 | const Diagnostics = @import("errors.zig").Diagnostics; | 7 | const Diagnostics = @import("errors.zig").Diagnostics; |
| 7 | const cli = @import("cli.zig"); | 8 | const cli = @import("cli.zig"); |
| 8 | const preprocess = @import("preprocess.zig"); | 9 | const preprocess = @import("preprocess.zig"); |
| ... | @@ -13,8 +14,6 @@ const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePag | ... | @@ -13,8 +14,6 @@ const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePag |
| 13 | const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType; | 14 | const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType; |
| 14 | const aro = @import("aro"); | 15 | const aro = @import("aro"); |
| 15 | 16 | ||
| 16 | var stdout_buffer: [1024]u8 = undefined; | ||
| 17 | |||
| 18 | pub fn main() !void { | 17 | pub fn main() !void { |
| 19 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; | 18 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; |
| 20 | defer std.debug.assert(gpa.deinit() == .ok); | 19 | defer std.debug.assert(gpa.deinit() == .ok); |
| ... | @@ -43,11 +42,13 @@ pub fn main() !void { | ... | @@ -43,11 +42,13 @@ pub fn main() !void { |
| 43 | cli_args = args[3..]; | 42 | cli_args = args[3..]; |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 45 | var stdout_buffer: [1024]u8 = undefined; | ||
| 46 | var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); | 46 | var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); |
| 47 | const stdout = &stdout_writer.interface; | ||
| 47 | var error_handler: ErrorHandler = switch (zig_integration) { | 48 | var error_handler: ErrorHandler = switch (zig_integration) { |
| 48 | true => .{ | 49 | true => .{ |
| 49 | .server = .{ | 50 | .server = .{ |
| 50 | .out = &stdout_writer.interface, | 51 | .out = stdout, |
| 51 | .in = undefined, // won't be receiving messages | 52 | .in = undefined, // won't be receiving messages |
| 52 | }, | 53 | }, |
| 53 | }, | 54 | }, |
| ... | @@ -83,8 +84,8 @@ pub fn main() !void { | ... | @@ -83,8 +84,8 @@ pub fn main() !void { |
| 83 | defer options.deinit(); | 84 | defer options.deinit(); |
| 84 | 85 | ||
| 85 | if (options.print_help_and_exit) { | 86 | if (options.print_help_and_exit) { |
| 86 | try cli.writeUsage(&stdout_writer.interface, "zig rc"); | 87 | try cli.writeUsage(stdout, "zig rc"); |
| 87 | try stdout_writer.interface.flush(); | 88 | try stdout.flush(); |
| 88 | return; | 89 | return; |
| 89 | } | 90 | } |
| 90 | 91 | ||
| ... | @@ -92,19 +93,14 @@ pub fn main() !void { | ... | @@ -92,19 +93,14 @@ pub fn main() !void { |
| 92 | options.verbose = false; | 93 | options.verbose = false; |
| 93 | 94 | ||
| 94 | if (options.verbose) { | 95 | if (options.verbose) { |
| 95 | try options.dumpVerbose(&stdout_writer.interface); | 96 | try options.dumpVerbose(stdout); |
| 96 | try stdout_writer.interface.writeByte('\n'); | 97 | try stdout.writeByte('\n'); |
| 97 | try stdout_writer.interface.flush(); | 98 | try stdout.flush(); |
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | var dependencies_list = std.array_list.Managed([]const u8).init(allocator); | 101 | var dependencies = Dependencies.init(allocator); |
| 101 | defer { | 102 | defer dependencies.deinit(); |
| 102 | for (dependencies_list.items) |item| { | 103 | const maybe_dependencies: ?*Dependencies = if (options.depfile_path != null) &dependencies else null; |
| 103 | allocator.free(item); | ||
| 104 | } | ||
| 105 | dependencies_list.deinit(); | ||
| 106 | } | ||
| 107 | const maybe_dependencies_list: ?*std.array_list.Managed([]const u8) = if (options.depfile_path != null) &dependencies_list else null; | ||
| 108 | 104 | ||
| 109 | var include_paths = LazyIncludePaths{ | 105 | var include_paths = LazyIncludePaths{ |
| 110 | .arena = arena, | 106 | .arena = arena, |
| ... | @@ -127,27 +123,27 @@ pub fn main() !void { | ... | @@ -127,27 +123,27 @@ pub fn main() !void { |
| 127 | var comp = aro.Compilation.init(aro_arena, std.fs.cwd()); | 123 | var comp = aro.Compilation.init(aro_arena, std.fs.cwd()); |
| 128 | defer comp.deinit(); | 124 | defer comp.deinit(); |
| 129 | 125 | ||
| 130 | var argv = std.array_list.Managed([]const u8).init(comp.gpa); | 126 | var argv: std.ArrayList([]const u8) = .empty; |
| 131 | defer argv.deinit(); | 127 | defer argv.deinit(aro_arena); |
| 132 | 128 | ||
| 133 | try argv.append("arocc"); // dummy command name | 129 | try argv.append(aro_arena, "arocc"); // dummy command name |
| 134 | const resolved_include_paths = try include_paths.get(&error_handler); | 130 | const resolved_include_paths = try include_paths.get(&error_handler); |
| 135 | try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths); | 131 | try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths); |
| 136 | try argv.append(switch (options.input_source) { | 132 | try argv.append(aro_arena, switch (options.input_source) { |
| 137 | .stdio => "-", | 133 | .stdio => "-", |
| 138 | .filename => |filename| filename, | 134 | .filename => |filename| filename, |
| 139 | }); | 135 | }); |
| 140 | 136 | ||
| 141 | if (options.verbose) { | 137 | if (options.verbose) { |
| 142 | try stdout_writer.interface.writeAll("Preprocessor: arocc (built-in)\n"); | 138 | try stdout.writeAll("Preprocessor: arocc (built-in)\n"); |
| 143 | for (argv.items[0 .. argv.items.len - 1]) |arg| { | 139 | for (argv.items[0 .. argv.items.len - 1]) |arg| { |
| 144 | try stdout_writer.interface.print("{s} ", .{arg}); | 140 | try stdout.print("{s} ", .{arg}); |
| 145 | } | 141 | } |
| 146 | try stdout_writer.interface.print("{s}\n\n", .{argv.items[argv.items.len - 1]}); | 142 | try stdout.print("{s}\n\n", .{argv.items[argv.items.len - 1]}); |
| 147 | try stdout_writer.interface.flush(); | 143 | try stdout.flush(); |
| 148 | } | 144 | } |
| 149 | 145 | ||
| 150 | preprocess.preprocess(&comp, &preprocessed_buf.writer, argv.items, maybe_dependencies_list) catch |err| switch (err) { | 146 | preprocess.preprocess(&comp, &preprocessed_buf.writer, argv.items, maybe_dependencies) catch |err| switch (err) { |
| 151 | error.GeneratedSourceError => { | 147 | error.GeneratedSourceError => { |
| 152 | try error_handler.emitAroDiagnostics(allocator, "failed during preprocessor setup (this is always a bug):", &comp); | 148 | try error_handler.emitAroDiagnostics(allocator, "failed during preprocessor setup (this is always a bug):", &comp); |
| 153 | std.process.exit(1); | 149 | std.process.exit(1); |
| ... | @@ -258,7 +254,7 @@ pub fn main() !void { | ... | @@ -258,7 +254,7 @@ pub fn main() !void { |
| 258 | .cwd = std.fs.cwd(), | 254 | .cwd = std.fs.cwd(), |
| 259 | .diagnostics = &diagnostics, | 255 | .diagnostics = &diagnostics, |
| 260 | .source_mappings = &mapping_results.mappings, | 256 | .source_mappings = &mapping_results.mappings, |
| 261 | .dependencies_list = maybe_dependencies_list, | 257 | .dependencies = maybe_dependencies, |
| 262 | .ignore_include_env_var = options.ignore_include_env_var, | 258 | .ignore_include_env_var = options.ignore_include_env_var, |
| 263 | .extra_include_paths = options.extra_include_paths.items, | 259 | .extra_include_paths = options.extra_include_paths.items, |
| 264 | .system_include_paths = try include_paths.get(&error_handler), | 260 | .system_include_paths = try include_paths.get(&error_handler), |
| ... | @@ -305,7 +301,7 @@ pub fn main() !void { | ... | @@ -305,7 +301,7 @@ pub fn main() !void { |
| 305 | }; | 301 | }; |
| 306 | 302 | ||
| 307 | try write_stream.beginArray(); | 303 | try write_stream.beginArray(); |
| 308 | for (dependencies_list.items) |dep_path| { | 304 | for (dependencies.list.items) |dep_path| { |
| 309 | try write_stream.write(dep_path); | 305 | try write_stream.write(dep_path); |
| 310 | } | 306 | } |
| 311 | try write_stream.endArray(); | 307 | try write_stream.endArray(); |
lib/compiler/resinator/parse.zig+26-26| ... | @@ -82,8 +82,8 @@ pub const Parser = struct { | ... | @@ -82,8 +82,8 @@ pub const Parser = struct { |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | fn parseRoot(self: *Self) Error!*Node { | 84 | fn parseRoot(self: *Self) Error!*Node { |
| 85 | var statements = std.array_list.Managed(*Node).init(self.state.allocator); | 85 | var statements: std.ArrayList(*Node) = .empty; |
| 86 | defer statements.deinit(); | 86 | defer statements.deinit(self.state.allocator); |
| 87 | 87 | ||
| 88 | try self.parseStatements(&statements); | 88 | try self.parseStatements(&statements); |
| 89 | try self.check(.eof); | 89 | try self.check(.eof); |
| ... | @@ -95,7 +95,7 @@ pub const Parser = struct { | ... | @@ -95,7 +95,7 @@ pub const Parser = struct { |
| 95 | return &node.base; | 95 | return &node.base; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | fn parseStatements(self: *Self, statements: *std.array_list.Managed(*Node)) Error!void { | 98 | fn parseStatements(self: *Self, statements: *std.ArrayList(*Node)) Error!void { |
| 99 | while (true) { | 99 | while (true) { |
| 100 | try self.nextToken(.whitespace_delimiter_only); | 100 | try self.nextToken(.whitespace_delimiter_only); |
| 101 | if (self.state.token.id == .eof) break; | 101 | if (self.state.token.id == .eof) break; |
| ... | @@ -105,7 +105,7 @@ pub const Parser = struct { | ... | @@ -105,7 +105,7 @@ pub const Parser = struct { |
| 105 | // (usually it will end up with bogus things like 'file | 105 | // (usually it will end up with bogus things like 'file |
| 106 | // not found: {') | 106 | // not found: {') |
| 107 | const statement = try self.parseStatement(); | 107 | const statement = try self.parseStatement(); |
| 108 | try statements.append(statement); | 108 | try statements.append(self.state.allocator, statement); |
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | 111 | ||
| ... | @@ -115,7 +115,7 @@ pub const Parser = struct { | ... | @@ -115,7 +115,7 @@ pub const Parser = struct { |
| 115 | /// current token is unchanged. | 115 | /// current token is unchanged. |
| 116 | /// The returned slice is allocated by the parser's arena | 116 | /// The returned slice is allocated by the parser's arena |
| 117 | fn parseCommonResourceAttributes(self: *Self) ![]Token { | 117 | fn parseCommonResourceAttributes(self: *Self) ![]Token { |
| 118 | var common_resource_attributes: std.ArrayListUnmanaged(Token) = .empty; | 118 | var common_resource_attributes: std.ArrayList(Token) = .empty; |
| 119 | while (true) { | 119 | while (true) { |
| 120 | const maybe_common_resource_attribute = try self.lookaheadToken(.normal); | 120 | const maybe_common_resource_attribute = try self.lookaheadToken(.normal); |
| 121 | if (maybe_common_resource_attribute.id == .literal and rc.CommonResourceAttributes.map.has(maybe_common_resource_attribute.slice(self.lexer.buffer))) { | 121 | if (maybe_common_resource_attribute.id == .literal and rc.CommonResourceAttributes.map.has(maybe_common_resource_attribute.slice(self.lexer.buffer))) { |
| ... | @@ -135,7 +135,7 @@ pub const Parser = struct { | ... | @@ -135,7 +135,7 @@ pub const Parser = struct { |
| 135 | /// current token is unchanged. | 135 | /// current token is unchanged. |
| 136 | /// The returned slice is allocated by the parser's arena | 136 | /// The returned slice is allocated by the parser's arena |
| 137 | fn parseOptionalStatements(self: *Self, resource: ResourceType) ![]*Node { | 137 | fn parseOptionalStatements(self: *Self, resource: ResourceType) ![]*Node { |
| 138 | var optional_statements: std.ArrayListUnmanaged(*Node) = .empty; | 138 | var optional_statements: std.ArrayList(*Node) = .empty; |
| 139 | 139 | ||
| 140 | const num_statement_types = @typeInfo(rc.OptionalStatements).@"enum".fields.len; | 140 | const num_statement_types = @typeInfo(rc.OptionalStatements).@"enum".fields.len; |
| 141 | var statement_type_has_duplicates = [_]bool{false} ** num_statement_types; | 141 | var statement_type_has_duplicates = [_]bool{false} ** num_statement_types; |
| ... | @@ -355,8 +355,8 @@ pub const Parser = struct { | ... | @@ -355,8 +355,8 @@ pub const Parser = struct { |
| 355 | const begin_token = self.state.token; | 355 | const begin_token = self.state.token; |
| 356 | try self.check(.begin); | 356 | try self.check(.begin); |
| 357 | 357 | ||
| 358 | var strings = std.array_list.Managed(*Node).init(self.state.allocator); | 358 | var strings: std.ArrayList(*Node) = .empty; |
| 359 | defer strings.deinit(); | 359 | defer strings.deinit(self.state.allocator); |
| 360 | while (true) { | 360 | while (true) { |
| 361 | const maybe_end_token = try self.lookaheadToken(.normal); | 361 | const maybe_end_token = try self.lookaheadToken(.normal); |
| 362 | switch (maybe_end_token.id) { | 362 | switch (maybe_end_token.id) { |
| ... | @@ -392,7 +392,7 @@ pub const Parser = struct { | ... | @@ -392,7 +392,7 @@ pub const Parser = struct { |
| 392 | .maybe_comma = comma_token, | 392 | .maybe_comma = comma_token, |
| 393 | .string = self.state.token, | 393 | .string = self.state.token, |
| 394 | }; | 394 | }; |
| 395 | try strings.append(&string_node.base); | 395 | try strings.append(self.state.allocator, &string_node.base); |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | if (strings.items.len == 0) { | 398 | if (strings.items.len == 0) { |
| ... | @@ -501,7 +501,7 @@ pub const Parser = struct { | ... | @@ -501,7 +501,7 @@ pub const Parser = struct { |
| 501 | const begin_token = self.state.token; | 501 | const begin_token = self.state.token; |
| 502 | try self.check(.begin); | 502 | try self.check(.begin); |
| 503 | 503 | ||
| 504 | var accelerators: std.ArrayListUnmanaged(*Node) = .empty; | 504 | var accelerators: std.ArrayList(*Node) = .empty; |
| 505 | 505 | ||
| 506 | while (true) { | 506 | while (true) { |
| 507 | const lookahead = try self.lookaheadToken(.normal); | 507 | const lookahead = try self.lookaheadToken(.normal); |
| ... | @@ -519,7 +519,7 @@ pub const Parser = struct { | ... | @@ -519,7 +519,7 @@ pub const Parser = struct { |
| 519 | 519 | ||
| 520 | const idvalue = try self.parseExpression(.{ .allowed_types = .{ .number = true } }); | 520 | const idvalue = try self.parseExpression(.{ .allowed_types = .{ .number = true } }); |
| 521 | 521 | ||
| 522 | var type_and_options: std.ArrayListUnmanaged(Token) = .empty; | 522 | var type_and_options: std.ArrayList(Token) = .empty; |
| 523 | while (true) { | 523 | while (true) { |
| 524 | if (!(try self.parseOptionalToken(.comma))) break; | 524 | if (!(try self.parseOptionalToken(.comma))) break; |
| 525 | 525 | ||
| ... | @@ -584,7 +584,7 @@ pub const Parser = struct { | ... | @@ -584,7 +584,7 @@ pub const Parser = struct { |
| 584 | const begin_token = self.state.token; | 584 | const begin_token = self.state.token; |
| 585 | try self.check(.begin); | 585 | try self.check(.begin); |
| 586 | 586 | ||
| 587 | var controls: std.ArrayListUnmanaged(*Node) = .empty; | 587 | var controls: std.ArrayList(*Node) = .empty; |
| 588 | defer controls.deinit(self.state.allocator); | 588 | defer controls.deinit(self.state.allocator); |
| 589 | while (try self.parseControlStatement(resource)) |control_node| { | 589 | while (try self.parseControlStatement(resource)) |control_node| { |
| 590 | // The number of controls must fit in a u16 in order for it to | 590 | // The number of controls must fit in a u16 in order for it to |
| ... | @@ -643,7 +643,7 @@ pub const Parser = struct { | ... | @@ -643,7 +643,7 @@ pub const Parser = struct { |
| 643 | const begin_token = self.state.token; | 643 | const begin_token = self.state.token; |
| 644 | try self.check(.begin); | 644 | try self.check(.begin); |
| 645 | 645 | ||
| 646 | var buttons: std.ArrayListUnmanaged(*Node) = .empty; | 646 | var buttons: std.ArrayList(*Node) = .empty; |
| 647 | defer buttons.deinit(self.state.allocator); | 647 | defer buttons.deinit(self.state.allocator); |
| 648 | while (try self.parseToolbarButtonStatement()) |button_node| { | 648 | while (try self.parseToolbarButtonStatement()) |button_node| { |
| 649 | // The number of buttons must fit in a u16 in order for it to | 649 | // The number of buttons must fit in a u16 in order for it to |
| ... | @@ -701,7 +701,7 @@ pub const Parser = struct { | ... | @@ -701,7 +701,7 @@ pub const Parser = struct { |
| 701 | const begin_token = self.state.token; | 701 | const begin_token = self.state.token; |
| 702 | try self.check(.begin); | 702 | try self.check(.begin); |
| 703 | 703 | ||
| 704 | var items: std.ArrayListUnmanaged(*Node) = .empty; | 704 | var items: std.ArrayList(*Node) = .empty; |
| 705 | defer items.deinit(self.state.allocator); | 705 | defer items.deinit(self.state.allocator); |
| 706 | while (try self.parseMenuItemStatement(resource, id_token, 1)) |item_node| { | 706 | while (try self.parseMenuItemStatement(resource, id_token, 1)) |item_node| { |
| 707 | try items.append(self.state.allocator, item_node); | 707 | try items.append(self.state.allocator, item_node); |
| ... | @@ -735,7 +735,7 @@ pub const Parser = struct { | ... | @@ -735,7 +735,7 @@ pub const Parser = struct { |
| 735 | // common resource attributes must all be contiguous and come before optional-statements | 735 | // common resource attributes must all be contiguous and come before optional-statements |
| 736 | const common_resource_attributes = try self.parseCommonResourceAttributes(); | 736 | const common_resource_attributes = try self.parseCommonResourceAttributes(); |
| 737 | 737 | ||
| 738 | var fixed_info: std.ArrayListUnmanaged(*Node) = .empty; | 738 | var fixed_info: std.ArrayList(*Node) = .empty; |
| 739 | while (try self.parseVersionStatement()) |version_statement| { | 739 | while (try self.parseVersionStatement()) |version_statement| { |
| 740 | try fixed_info.append(self.state.arena, version_statement); | 740 | try fixed_info.append(self.state.arena, version_statement); |
| 741 | } | 741 | } |
| ... | @@ -744,7 +744,7 @@ pub const Parser = struct { | ... | @@ -744,7 +744,7 @@ pub const Parser = struct { |
| 744 | const begin_token = self.state.token; | 744 | const begin_token = self.state.token; |
| 745 | try self.check(.begin); | 745 | try self.check(.begin); |
| 746 | 746 | ||
| 747 | var block_statements: std.ArrayListUnmanaged(*Node) = .empty; | 747 | var block_statements: std.ArrayList(*Node) = .empty; |
| 748 | while (try self.parseVersionBlockOrValue(id_token, 1)) |block_node| { | 748 | while (try self.parseVersionBlockOrValue(id_token, 1)) |block_node| { |
| 749 | try block_statements.append(self.state.arena, block_node); | 749 | try block_statements.append(self.state.arena, block_node); |
| 750 | } | 750 | } |
| ... | @@ -852,8 +852,8 @@ pub const Parser = struct { | ... | @@ -852,8 +852,8 @@ pub const Parser = struct { |
| 852 | /// Expects the current token to be a begin token. | 852 | /// Expects the current token to be a begin token. |
| 853 | /// After return, the current token will be the end token. | 853 | /// After return, the current token will be the end token. |
| 854 | fn parseRawDataBlock(self: *Self) Error![]*Node { | 854 | fn parseRawDataBlock(self: *Self) Error![]*Node { |
| 855 | var raw_data = std.array_list.Managed(*Node).init(self.state.allocator); | 855 | var raw_data: std.ArrayList(*Node) = .empty; |
| 856 | defer raw_data.deinit(); | 856 | defer raw_data.deinit(self.state.allocator); |
| 857 | while (true) { | 857 | while (true) { |
| 858 | const maybe_end_token = try self.lookaheadToken(.normal); | 858 | const maybe_end_token = try self.lookaheadToken(.normal); |
| 859 | switch (maybe_end_token.id) { | 859 | switch (maybe_end_token.id) { |
| ... | @@ -888,7 +888,7 @@ pub const Parser = struct { | ... | @@ -888,7 +888,7 @@ pub const Parser = struct { |
| 888 | else => {}, | 888 | else => {}, |
| 889 | } | 889 | } |
| 890 | const expression = try self.parseExpression(.{ .allowed_types = .{ .number = true, .string = true } }); | 890 | const expression = try self.parseExpression(.{ .allowed_types = .{ .number = true, .string = true } }); |
| 891 | try raw_data.append(expression); | 891 | try raw_data.append(self.state.allocator, expression); |
| 892 | 892 | ||
| 893 | if (expression.isNumberExpression()) { | 893 | if (expression.isNumberExpression()) { |
| 894 | const maybe_close_paren = try self.lookaheadToken(.normal); | 894 | const maybe_close_paren = try self.lookaheadToken(.normal); |
| ... | @@ -1125,7 +1125,7 @@ pub const Parser = struct { | ... | @@ -1125,7 +1125,7 @@ pub const Parser = struct { |
| 1125 | 1125 | ||
| 1126 | _ = try self.parseOptionalToken(.comma); | 1126 | _ = try self.parseOptionalToken(.comma); |
| 1127 | 1127 | ||
| 1128 | var options: std.ArrayListUnmanaged(Token) = .empty; | 1128 | var options: std.ArrayList(Token) = .empty; |
| 1129 | while (true) { | 1129 | while (true) { |
| 1130 | const option_token = try self.lookaheadToken(.normal); | 1130 | const option_token = try self.lookaheadToken(.normal); |
| 1131 | if (!rc.MenuItem.Option.map.has(option_token.slice(self.lexer.buffer))) { | 1131 | if (!rc.MenuItem.Option.map.has(option_token.slice(self.lexer.buffer))) { |
| ... | @@ -1160,7 +1160,7 @@ pub const Parser = struct { | ... | @@ -1160,7 +1160,7 @@ pub const Parser = struct { |
| 1160 | } | 1160 | } |
| 1161 | try self.skipAnyCommas(); | 1161 | try self.skipAnyCommas(); |
| 1162 | 1162 | ||
| 1163 | var options: std.ArrayListUnmanaged(Token) = .empty; | 1163 | var options: std.ArrayList(Token) = .empty; |
| 1164 | while (true) { | 1164 | while (true) { |
| 1165 | const option_token = try self.lookaheadToken(.normal); | 1165 | const option_token = try self.lookaheadToken(.normal); |
| 1166 | if (!rc.MenuItem.Option.map.has(option_token.slice(self.lexer.buffer))) { | 1166 | if (!rc.MenuItem.Option.map.has(option_token.slice(self.lexer.buffer))) { |
| ... | @@ -1175,7 +1175,7 @@ pub const Parser = struct { | ... | @@ -1175,7 +1175,7 @@ pub const Parser = struct { |
| 1175 | const begin_token = self.state.token; | 1175 | const begin_token = self.state.token; |
| 1176 | try self.check(.begin); | 1176 | try self.check(.begin); |
| 1177 | 1177 | ||
| 1178 | var items: std.ArrayListUnmanaged(*Node) = .empty; | 1178 | var items: std.ArrayList(*Node) = .empty; |
| 1179 | while (try self.parseMenuItemStatement(resource, top_level_menu_id_token, nesting_level + 1)) |item_node| { | 1179 | while (try self.parseMenuItemStatement(resource, top_level_menu_id_token, nesting_level + 1)) |item_node| { |
| 1180 | try items.append(self.state.arena, item_node); | 1180 | try items.append(self.state.arena, item_node); |
| 1181 | } | 1181 | } |
| ... | @@ -1245,7 +1245,7 @@ pub const Parser = struct { | ... | @@ -1245,7 +1245,7 @@ pub const Parser = struct { |
| 1245 | const begin_token = self.state.token; | 1245 | const begin_token = self.state.token; |
| 1246 | try self.check(.begin); | 1246 | try self.check(.begin); |
| 1247 | 1247 | ||
| 1248 | var items: std.ArrayListUnmanaged(*Node) = .empty; | 1248 | var items: std.ArrayList(*Node) = .empty; |
| 1249 | while (try self.parseMenuItemStatement(resource, top_level_menu_id_token, nesting_level + 1)) |item_node| { | 1249 | while (try self.parseMenuItemStatement(resource, top_level_menu_id_token, nesting_level + 1)) |item_node| { |
| 1250 | try items.append(self.state.arena, item_node); | 1250 | try items.append(self.state.arena, item_node); |
| 1251 | } | 1251 | } |
| ... | @@ -1322,7 +1322,7 @@ pub const Parser = struct { | ... | @@ -1322,7 +1322,7 @@ pub const Parser = struct { |
| 1322 | switch (statement_type) { | 1322 | switch (statement_type) { |
| 1323 | .file_version, .product_version => { | 1323 | .file_version, .product_version => { |
| 1324 | var parts_buffer: [4]*Node = undefined; | 1324 | var parts_buffer: [4]*Node = undefined; |
| 1325 | var parts = std.ArrayListUnmanaged(*Node).initBuffer(&parts_buffer); | 1325 | var parts = std.ArrayList(*Node).initBuffer(&parts_buffer); |
| 1326 | 1326 | ||
| 1327 | while (true) { | 1327 | while (true) { |
| 1328 | const value = try self.parseExpression(.{ .allowed_types = .{ .number = true } }); | 1328 | const value = try self.parseExpression(.{ .allowed_types = .{ .number = true } }); |
| ... | @@ -1402,7 +1402,7 @@ pub const Parser = struct { | ... | @@ -1402,7 +1402,7 @@ pub const Parser = struct { |
| 1402 | const begin_token = self.state.token; | 1402 | const begin_token = self.state.token; |
| 1403 | try self.check(.begin); | 1403 | try self.check(.begin); |
| 1404 | 1404 | ||
| 1405 | var children: std.ArrayListUnmanaged(*Node) = .empty; | 1405 | var children: std.ArrayList(*Node) = .empty; |
| 1406 | while (try self.parseVersionBlockOrValue(top_level_version_id_token, nesting_level + 1)) |value_node| { | 1406 | while (try self.parseVersionBlockOrValue(top_level_version_id_token, nesting_level + 1)) |value_node| { |
| 1407 | try children.append(self.state.arena, value_node); | 1407 | try children.append(self.state.arena, value_node); |
| 1408 | } | 1408 | } |
| ... | @@ -1435,7 +1435,7 @@ pub const Parser = struct { | ... | @@ -1435,7 +1435,7 @@ pub const Parser = struct { |
| 1435 | } | 1435 | } |
| 1436 | 1436 | ||
| 1437 | fn parseBlockValuesList(self: *Self, had_comma_before_first_value: bool) Error![]*Node { | 1437 | fn parseBlockValuesList(self: *Self, had_comma_before_first_value: bool) Error![]*Node { |
| 1438 | var values: std.ArrayListUnmanaged(*Node) = .empty; | 1438 | var values: std.ArrayList(*Node) = .empty; |
| 1439 | var seen_number: bool = false; | 1439 | var seen_number: bool = false; |
| 1440 | var first_string_value: ?*Node = null; | 1440 | var first_string_value: ?*Node = null; |
| 1441 | while (true) { | 1441 | while (true) { |
lib/compiler/resinator/preprocess.zig+19-18| ... | @@ -2,16 +2,17 @@ const std = @import("std"); | ... | @@ -2,16 +2,17 @@ const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const Allocator = std.mem.Allocator; | 3 | const Allocator = std.mem.Allocator; |
| 4 | const cli = @import("cli.zig"); | 4 | const cli = @import("cli.zig"); |
| 5 | const Dependencies = @import("compile.zig").Dependencies; | ||
| 5 | const aro = @import("aro"); | 6 | const aro = @import("aro"); |
| 6 | 7 | ||
| 7 | const PreprocessError = error{ ArgError, GeneratedSourceError, PreprocessError, StreamTooLong, OutOfMemory }; | 8 | const PreprocessError = error{ ArgError, GeneratedSourceError, PreprocessError, StreamTooLong, OutOfMemory }; |
| 8 | 9 | ||
| 9 | pub fn preprocess( | 10 | pub fn preprocess( |
| 10 | comp: *aro.Compilation, | 11 | comp: *aro.Compilation, |
| 11 | writer: anytype, | 12 | writer: *std.Io.Writer, |
| 12 | /// Expects argv[0] to be the command name | 13 | /// Expects argv[0] to be the command name |
| 13 | argv: []const []const u8, | 14 | argv: []const []const u8, |
| 14 | maybe_dependencies_list: ?*std.array_list.Managed([]const u8), | 15 | maybe_dependencies: ?*Dependencies, |
| 15 | ) PreprocessError!void { | 16 | ) PreprocessError!void { |
| 16 | try comp.addDefaultPragmaHandlers(); | 17 | try comp.addDefaultPragmaHandlers(); |
| 17 | 18 | ||
| ... | @@ -66,13 +67,13 @@ pub fn preprocess( | ... | @@ -66,13 +67,13 @@ pub fn preprocess( |
| 66 | error.WriteFailed => return error.OutOfMemory, | 67 | error.WriteFailed => return error.OutOfMemory, |
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 69 | if (maybe_dependencies_list) |dependencies_list| { | 70 | if (maybe_dependencies) |dependencies| { |
| 70 | for (comp.sources.values()) |comp_source| { | 71 | for (comp.sources.values()) |comp_source| { |
| 71 | if (comp_source.id == builtin_macros.id or comp_source.id == user_macros.id) continue; | 72 | if (comp_source.id == builtin_macros.id or comp_source.id == user_macros.id) continue; |
| 72 | if (comp_source.id == .unused or comp_source.id == .generated) continue; | 73 | if (comp_source.id == .unused or comp_source.id == .generated) continue; |
| 73 | const duped_path = try dependencies_list.allocator.dupe(u8, comp_source.path); | 74 | const duped_path = try dependencies.allocator.dupe(u8, comp_source.path); |
| 74 | errdefer dependencies_list.allocator.free(duped_path); | 75 | errdefer dependencies.allocator.free(duped_path); |
| 75 | try dependencies_list.append(duped_path); | 76 | try dependencies.list.append(dependencies.allocator, duped_path); |
| 76 | } | 77 | } |
| 77 | } | 78 | } |
| 78 | } | 79 | } |
| ... | @@ -92,8 +93,8 @@ fn hasAnyErrors(comp: *aro.Compilation) bool { | ... | @@ -92,8 +93,8 @@ fn hasAnyErrors(comp: *aro.Compilation) bool { |
| 92 | 93 | ||
| 93 | /// `arena` is used for temporary -D argument strings and the INCLUDE environment variable. | 94 | /// `arena` is used for temporary -D argument strings and the INCLUDE environment variable. |
| 94 | /// The arena should be kept alive at least as long as `argv`. | 95 | /// The arena should be kept alive at least as long as `argv`. |
| 95 | pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8), options: cli.Options, system_include_paths: []const []const u8) !void { | 96 | pub fn appendAroArgs(arena: Allocator, argv: *std.ArrayList([]const u8), options: cli.Options, system_include_paths: []const []const u8) !void { |
| 96 | try argv.appendSlice(&.{ | 97 | try argv.appendSlice(arena, &.{ |
| 97 | "-E", | 98 | "-E", |
| 98 | "--comments", | 99 | "--comments", |
| 99 | "-fuse-line-directives", | 100 | "-fuse-line-directives", |
| ... | @@ -104,13 +105,13 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) | ... | @@ -104,13 +105,13 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) |
| 104 | "-D_WIN32", // undocumented, but defined by default | 105 | "-D_WIN32", // undocumented, but defined by default |
| 105 | }); | 106 | }); |
| 106 | for (options.extra_include_paths.items) |extra_include_path| { | 107 | for (options.extra_include_paths.items) |extra_include_path| { |
| 107 | try argv.append("-I"); | 108 | try argv.append(arena, "-I"); |
| 108 | try argv.append(extra_include_path); | 109 | try argv.append(arena, extra_include_path); |
| 109 | } | 110 | } |
| 110 | 111 | ||
| 111 | for (system_include_paths) |include_path| { | 112 | for (system_include_paths) |include_path| { |
| 112 | try argv.append("-isystem"); | 113 | try argv.append(arena, "-isystem"); |
| 113 | try argv.append(include_path); | 114 | try argv.append(arena, include_path); |
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | if (!options.ignore_include_env_var) { | 117 | if (!options.ignore_include_env_var) { |
| ... | @@ -124,8 +125,8 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) | ... | @@ -124,8 +125,8 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) |
| 124 | }; | 125 | }; |
| 125 | var it = std.mem.tokenizeScalar(u8, INCLUDE, delimiter); | 126 | var it = std.mem.tokenizeScalar(u8, INCLUDE, delimiter); |
| 126 | while (it.next()) |include_path| { | 127 | while (it.next()) |include_path| { |
| 127 | try argv.append("-isystem"); | 128 | try argv.append(arena, "-isystem"); |
| 128 | try argv.append(include_path); | 129 | try argv.append(arena, include_path); |
| 129 | } | 130 | } |
| 130 | } | 131 | } |
| 131 | 132 | ||
| ... | @@ -133,13 +134,13 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) | ... | @@ -133,13 +134,13 @@ pub fn appendAroArgs(arena: Allocator, argv: *std.array_list.Managed([]const u8) |
| 133 | while (symbol_it.next()) |entry| { | 134 | while (symbol_it.next()) |entry| { |
| 134 | switch (entry.value_ptr.*) { | 135 | switch (entry.value_ptr.*) { |
| 135 | .define => |value| { | 136 | .define => |value| { |
| 136 | try argv.append("-D"); | 137 | try argv.append(arena, "-D"); |
| 137 | const define_arg = try std.fmt.allocPrint(arena, "{s}={s}", .{ entry.key_ptr.*, value }); | 138 | const define_arg = try std.fmt.allocPrint(arena, "{s}={s}", .{ entry.key_ptr.*, value }); |
| 138 | try argv.append(define_arg); | 139 | try argv.append(arena, define_arg); |
| 139 | }, | 140 | }, |
| 140 | .undefine => { | 141 | .undefine => { |
| 141 | try argv.append("-U"); | 142 | try argv.append(arena, "-U"); |
| 142 | try argv.append(entry.key_ptr.*); | 143 | try argv.append(arena, entry.key_ptr.*); |
| 143 | }, | 144 | }, |
| 144 | } | 145 | } |
| 145 | } | 146 | } |
lib/compiler/resinator/res.zig+11-11| ... | @@ -258,7 +258,7 @@ pub const NameOrOrdinal = union(enum) { | ... | @@ -258,7 +258,7 @@ pub const NameOrOrdinal = union(enum) { |
| 258 | } | 258 | } |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | pub fn write(self: NameOrOrdinal, writer: anytype) !void { | 261 | pub fn write(self: NameOrOrdinal, writer: *std.Io.Writer) !void { |
| 262 | switch (self) { | 262 | switch (self) { |
| 263 | .name => |name| { | 263 | .name => |name| { |
| 264 | try writer.writeAll(std.mem.sliceAsBytes(name[0 .. name.len + 1])); | 264 | try writer.writeAll(std.mem.sliceAsBytes(name[0 .. name.len + 1])); |
| ... | @@ -270,7 +270,7 @@ pub const NameOrOrdinal = union(enum) { | ... | @@ -270,7 +270,7 @@ pub const NameOrOrdinal = union(enum) { |
| 270 | } | 270 | } |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | pub fn writeEmpty(writer: anytype) !void { | 273 | pub fn writeEmpty(writer: *std.Io.Writer) !void { |
| 274 | try writer.writeInt(u16, 0, .little); | 274 | try writer.writeInt(u16, 0, .little); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| ... | @@ -283,8 +283,8 @@ pub const NameOrOrdinal = union(enum) { | ... | @@ -283,8 +283,8 @@ pub const NameOrOrdinal = union(enum) { |
| 283 | 283 | ||
| 284 | pub fn nameFromString(allocator: Allocator, bytes: SourceBytes) !NameOrOrdinal { | 284 | pub fn nameFromString(allocator: Allocator, bytes: SourceBytes) !NameOrOrdinal { |
| 285 | // Names have a limit of 256 UTF-16 code units + null terminator | 285 | // Names have a limit of 256 UTF-16 code units + null terminator |
| 286 | var buf = try std.array_list.Managed(u16).initCapacity(allocator, @min(257, bytes.slice.len)); | 286 | var buf = try std.ArrayList(u16).initCapacity(allocator, @min(257, bytes.slice.len)); |
| 287 | errdefer buf.deinit(); | 287 | errdefer buf.deinit(allocator); |
| 288 | 288 | ||
| 289 | var i: usize = 0; | 289 | var i: usize = 0; |
| 290 | while (bytes.code_page.codepointAt(i, bytes.slice)) |codepoint| : (i += codepoint.byte_len) { | 290 | while (bytes.code_page.codepointAt(i, bytes.slice)) |codepoint| : (i += codepoint.byte_len) { |
| ... | @@ -292,27 +292,27 @@ pub const NameOrOrdinal = union(enum) { | ... | @@ -292,27 +292,27 @@ pub const NameOrOrdinal = union(enum) { |
| 292 | 292 | ||
| 293 | const c = codepoint.value; | 293 | const c = codepoint.value; |
| 294 | if (c == Codepoint.invalid) { | 294 | if (c == Codepoint.invalid) { |
| 295 | try buf.append(std.mem.nativeToLittle(u16, '�')); | 295 | try buf.append(allocator, std.mem.nativeToLittle(u16, '�')); |
| 296 | } else if (c < 0x7F) { | 296 | } else if (c < 0x7F) { |
| 297 | // ASCII chars in names are always converted to uppercase | 297 | // ASCII chars in names are always converted to uppercase |
| 298 | try buf.append(std.mem.nativeToLittle(u16, std.ascii.toUpper(@intCast(c)))); | 298 | try buf.append(allocator, std.mem.nativeToLittle(u16, std.ascii.toUpper(@intCast(c)))); |
| 299 | } else if (c < 0x10000) { | 299 | } else if (c < 0x10000) { |
| 300 | const short: u16 = @intCast(c); | 300 | const short: u16 = @intCast(c); |
| 301 | try buf.append(std.mem.nativeToLittle(u16, short)); | 301 | try buf.append(allocator, std.mem.nativeToLittle(u16, short)); |
| 302 | } else { | 302 | } else { |
| 303 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; | 303 | const high = @as(u16, @intCast((c - 0x10000) >> 10)) + 0xD800; |
| 304 | try buf.append(std.mem.nativeToLittle(u16, high)); | 304 | try buf.append(allocator, std.mem.nativeToLittle(u16, high)); |
| 305 | 305 | ||
| 306 | // Note: This can cut-off in the middle of a UTF-16 surrogate pair, | 306 | // Note: This can cut-off in the middle of a UTF-16 surrogate pair, |
| 307 | // i.e. it can make the string end with an unpaired high surrogate | 307 | // i.e. it can make the string end with an unpaired high surrogate |
| 308 | if (buf.items.len == 256) break; | 308 | if (buf.items.len == 256) break; |
| 309 | 309 | ||
| 310 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; | 310 | const low = @as(u16, @intCast(c & 0x3FF)) + 0xDC00; |
| 311 | try buf.append(std.mem.nativeToLittle(u16, low)); | 311 | try buf.append(allocator, std.mem.nativeToLittle(u16, low)); |
| 312 | } | 312 | } |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | return NameOrOrdinal{ .name = try buf.toOwnedSliceSentinel(0) }; | 315 | return NameOrOrdinal{ .name = try buf.toOwnedSliceSentinel(allocator, 0) }; |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | /// Returns `null` if the bytes do not form a valid number. | 318 | /// Returns `null` if the bytes do not form a valid number. |
| ... | @@ -1079,7 +1079,7 @@ pub const FixedFileInfo = struct { | ... | @@ -1079,7 +1079,7 @@ pub const FixedFileInfo = struct { |
| 1079 | } | 1079 | } |
| 1080 | }; | 1080 | }; |
| 1081 | 1081 | ||
| 1082 | pub fn write(self: FixedFileInfo, writer: anytype) !void { | 1082 | pub fn write(self: FixedFileInfo, writer: *std.Io.Writer) !void { |
| 1083 | try writer.writeInt(u32, signature, .little); | 1083 | try writer.writeInt(u32, signature, .little); |
| 1084 | try writer.writeInt(u32, version, .little); | 1084 | try writer.writeInt(u32, version, .little); |
| 1085 | try writer.writeInt(u32, self.file_version.mostSignificantCombinedParts(), .little); | 1085 | try writer.writeInt(u32, self.file_version.mostSignificantCombinedParts(), .little); |
lib/compiler/resinator/source_mapping.zig+5-5| ... | @@ -10,7 +10,7 @@ pub const ParseLineCommandsResult = struct { | ... | @@ -10,7 +10,7 @@ pub const ParseLineCommandsResult = struct { |
| 10 | 10 | ||
| 11 | const CurrentMapping = struct { | 11 | const CurrentMapping = struct { |
| 12 | line_num: usize = 1, | 12 | line_num: usize = 1, |
| 13 | filename: std.ArrayListUnmanaged(u8) = .empty, | 13 | filename: std.ArrayList(u8) = .empty, |
| 14 | pending: bool = true, | 14 | pending: bool = true, |
| 15 | ignore_contents: bool = false, | 15 | ignore_contents: bool = false, |
| 16 | }; | 16 | }; |
| ... | @@ -574,8 +574,8 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva | ... | @@ -574,8 +574,8 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva |
| 574 | escape_u, | 574 | escape_u, |
| 575 | }; | 575 | }; |
| 576 | 576 | ||
| 577 | var filename = try std.array_list.Managed(u8).initCapacity(allocator, str.len); | 577 | var filename = try std.ArrayList(u8).initCapacity(allocator, str.len); |
| 578 | errdefer filename.deinit(); | 578 | errdefer filename.deinit(allocator); |
| 579 | var state: State = .string; | 579 | var state: State = .string; |
| 580 | var index: usize = 0; | 580 | var index: usize = 0; |
| 581 | var escape_len: usize = undefined; | 581 | var escape_len: usize = undefined; |
| ... | @@ -693,7 +693,7 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva | ... | @@ -693,7 +693,7 @@ fn parseFilename(allocator: Allocator, str: []const u8) error{ OutOfMemory, Inva |
| 693 | } | 693 | } |
| 694 | } | 694 | } |
| 695 | 695 | ||
| 696 | return filename.toOwnedSlice(); | 696 | return filename.toOwnedSlice(allocator); |
| 697 | } | 697 | } |
| 698 | 698 | ||
| 699 | fn testParseFilename(expected: []const u8, input: []const u8) !void { | 699 | fn testParseFilename(expected: []const u8, input: []const u8) !void { |
| ... | @@ -927,7 +927,7 @@ test "SourceMappings collapse" { | ... | @@ -927,7 +927,7 @@ test "SourceMappings collapse" { |
| 927 | 927 | ||
| 928 | /// Same thing as StringTable in Zig's src/Wasm.zig | 928 | /// Same thing as StringTable in Zig's src/Wasm.zig |
| 929 | pub const StringTable = struct { | 929 | pub const StringTable = struct { |
| 930 | data: std.ArrayListUnmanaged(u8) = .empty, | 930 | data: std.ArrayList(u8) = .empty, |
| 931 | map: std.HashMapUnmanaged(u32, void, std.hash_map.StringIndexContext, std.hash_map.default_max_load_percentage) = .empty, | 931 | map: std.HashMapUnmanaged(u32, void, std.hash_map.StringIndexContext, std.hash_map.default_max_load_percentage) = .empty, |
| 932 | 932 | ||
| 933 | pub fn deinit(self: *StringTable, allocator: Allocator) void { | 933 | pub fn deinit(self: *StringTable, allocator: Allocator) void { |
lib/compiler/resinator/windows1252.zig-45| ... | @@ -1,36 +1,5 @@ | ... | @@ -1,36 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | 2 | ||
| 3 | pub fn windows1252ToUtf8Stream(writer: anytype, reader: anytype) !usize { | ||
| 4 | var bytes_written: usize = 0; | ||
| 5 | var utf8_buf: [3]u8 = undefined; | ||
| 6 | while (true) { | ||
| 7 | const c = reader.readByte() catch |err| switch (err) { | ||
| 8 | error.EndOfStream => return bytes_written, | ||
| 9 | else => |e| return e, | ||
| 10 | }; | ||
| 11 | const codepoint = toCodepoint(c); | ||
| 12 | if (codepoint <= 0x7F) { | ||
| 13 | try writer.writeByte(c); | ||
| 14 | bytes_written += 1; | ||
| 15 | } else { | ||
| 16 | const utf8_len = std.unicode.utf8Encode(codepoint, &utf8_buf) catch unreachable; | ||
| 17 | try writer.writeAll(utf8_buf[0..utf8_len]); | ||
| 18 | bytes_written += utf8_len; | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | /// Returns the number of code units written to the writer | ||
| 24 | pub fn windows1252ToUtf16AllocZ(allocator: std.mem.Allocator, win1252_str: []const u8) ![:0]u16 { | ||
| 25 | // Guaranteed to need exactly the same number of code units as Windows-1252 bytes | ||
| 26 | var utf16_slice = try allocator.allocSentinel(u16, win1252_str.len, 0); | ||
| 27 | errdefer allocator.free(utf16_slice); | ||
| 28 | for (win1252_str, 0..) |c, i| { | ||
| 29 | utf16_slice[i] = toCodepoint(c); | ||
| 30 | } | ||
| 31 | return utf16_slice; | ||
| 32 | } | ||
| 33 | |||
| 34 | /// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1252.txt | 3 | /// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1252.txt |
| 35 | pub fn toCodepoint(c: u8) u16 { | 4 | pub fn toCodepoint(c: u8) u16 { |
| 36 | return switch (c) { | 5 | return switch (c) { |
| ... | @@ -572,17 +541,3 @@ pub fn bestFitFromCodepoint(codepoint: u21) ?u8 { | ... | @@ -572,17 +541,3 @@ pub fn bestFitFromCodepoint(codepoint: u21) ?u8 { |
| 572 | else => null, | 541 | else => null, |
| 573 | }; | 542 | }; |
| 574 | } | 543 | } |
| 575 | |||
| 576 | test "windows-1252 to utf8" { | ||
| 577 | var buf = std.array_list.Managed(u8).init(std.testing.allocator); | ||
| 578 | defer buf.deinit(); | ||
| 579 | |||
| 580 | const input_windows1252 = "\x81pqrstuvwxyz{|}~\x80\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8e\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9e\x9f\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; | ||
| 581 | const expected_utf8 = "\xc2\x81pqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; | ||
| 582 | |||
| 583 | var fbs = std.io.fixedBufferStream(input_windows1252); | ||
| 584 | const bytes_written = try windows1252ToUtf8Stream(buf.writer(), fbs.reader()); | ||
| 585 | |||
| 586 | try std.testing.expectEqualStrings(expected_utf8, buf.items); | ||
| 587 | try std.testing.expectEqual(expected_utf8.len, bytes_written); | ||
| 588 | } |