|
| 1 | +const std = @import("std"); |
| 2 | +const fehler = @import("root.zig"); |
| 3 | + |
| 4 | +var gpa = std.heap.GeneralPurposeAllocator(.{}){}; |
| 5 | +const c_allocator = gpa.allocator(); |
| 6 | + |
| 7 | +pub const FehlerReporter = opaque {}; |
| 8 | + |
| 9 | +pub const FehlerDiagnostic = opaque {}; |
| 10 | + |
| 11 | +pub const FehlerSeverity = enum(c_int) { |
| 12 | + fatal = 0, |
| 13 | + err = 1, |
| 14 | + warn = 2, |
| 15 | + note = 3, |
| 16 | + todo = 4, |
| 17 | + unimplemented = 5, |
| 18 | +}; |
| 19 | + |
| 20 | +pub const FehlerFormat = enum(c_int) { |
| 21 | + fehler = 0, |
| 22 | + gcc = 1, |
| 23 | + msvc = 2, |
| 24 | +}; |
| 25 | + |
| 26 | +pub const FehlerPosition = extern struct { |
| 27 | + line: usize, |
| 28 | + column: usize, |
| 29 | +}; |
| 30 | + |
| 31 | +pub const FehlerSourceRange = extern struct { |
| 32 | + file: [*:0]const u8, |
| 33 | + start: FehlerPosition, |
| 34 | + end: FehlerPosition, |
| 35 | +}; |
| 36 | + |
| 37 | +export fn fehler_reporter_create() ?*FehlerReporter { |
| 38 | + const reporter = c_allocator.create(fehler.ErrorReporter) catch return null; |
| 39 | + reporter.* = fehler.ErrorReporter.init(c_allocator); |
| 40 | + return @ptrCast(reporter); |
| 41 | +} |
| 42 | + |
| 43 | +export fn fehler_reporter_destroy(reporter: *FehlerReporter) void { |
| 44 | + const r: *fehler.ErrorReporter = @ptrCast(@alignCast(reporter)); |
| 45 | + r.deinit(); |
| 46 | + c_allocator.destroy(r); |
| 47 | +} |
| 48 | + |
| 49 | +export fn fehler_reporter_set_format(reporter: *FehlerReporter, format: FehlerFormat) void { |
| 50 | + const r: *fehler.ErrorReporter = @ptrCast(@alignCast(reporter)); |
| 51 | + r.format = switch (format) { |
| 52 | + .fehler => .fehler, |
| 53 | + .gcc => .gcc, |
| 54 | + .msvc => .msvc, |
| 55 | + }; |
| 56 | +} |
| 57 | + |
| 58 | +export fn fehler_reporter_add_source( |
| 59 | + reporter: *FehlerReporter, |
| 60 | + filename: [*:0]const u8, |
| 61 | + content: [*:0]const u8, |
| 62 | +) c_int { |
| 63 | + const r: *fehler.ErrorReporter = @ptrCast(@alignCast(reporter)); |
| 64 | + const filename_slice = std.mem.span(filename); |
| 65 | + const content_slice = std.mem.span(content); |
| 66 | + r.addSource(filename_slice, content_slice) catch return -1; |
| 67 | + return 0; |
| 68 | +} |
| 69 | + |
| 70 | +export fn fehler_reporter_report(reporter: *FehlerReporter, diagnostic: *FehlerDiagnostic) void { |
| 71 | + const r: *fehler.ErrorReporter = @ptrCast(@alignCast(reporter)); |
| 72 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 73 | + r.report(d.*); |
| 74 | +} |
| 75 | + |
| 76 | +export fn fehler_diagnostic_create( |
| 77 | + severity: FehlerSeverity, |
| 78 | + message: [*:0]const u8, |
| 79 | +) ?*FehlerDiagnostic { |
| 80 | + const diag = c_allocator.create(fehler.Diagnostic) catch return null; |
| 81 | + const message_slice = std.mem.span(message); |
| 82 | + const owned_message = c_allocator.dupe(u8, message_slice) catch { |
| 83 | + c_allocator.destroy(diag); |
| 84 | + return null; |
| 85 | + }; |
| 86 | + |
| 87 | + const sev = switch (severity) { |
| 88 | + .fatal => fehler.Severity.fatal, |
| 89 | + .err => fehler.Severity.err, |
| 90 | + .warn => fehler.Severity.warn, |
| 91 | + .note => fehler.Severity.note, |
| 92 | + .todo => fehler.Severity.todo, |
| 93 | + .unimplemented => fehler.Severity.unimplemented, |
| 94 | + }; |
| 95 | + |
| 96 | + diag.* = fehler.Diagnostic.init(sev, owned_message); |
| 97 | + return @ptrCast(diag); |
| 98 | +} |
| 99 | + |
| 100 | +export fn fehler_diagnostic_destroy(diagnostic: *FehlerDiagnostic) void { |
| 101 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 102 | + c_allocator.free(d.message); |
| 103 | + if (d.help) |help| c_allocator.free(help); |
| 104 | + if (d.code) |code| c_allocator.free(code); |
| 105 | + if (d.url) |url| c_allocator.free(url); |
| 106 | + c_allocator.destroy(d); |
| 107 | +} |
| 108 | + |
| 109 | +export fn fehler_diagnostic_set_location( |
| 110 | + diagnostic: *FehlerDiagnostic, |
| 111 | + file: [*:0]const u8, |
| 112 | + line: usize, |
| 113 | + column: usize, |
| 114 | +) c_int { |
| 115 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 116 | + const file_slice = std.mem.span(file); |
| 117 | + d.range = fehler.SourceRange.single(file_slice, line, column); |
| 118 | + return 0; |
| 119 | +} |
| 120 | + |
| 121 | +export fn fehler_diagnostic_set_range( |
| 122 | + diagnostic: *FehlerDiagnostic, |
| 123 | + file: [*:0]const u8, |
| 124 | + start_line: usize, |
| 125 | + start_col: usize, |
| 126 | + end_line: usize, |
| 127 | + end_col: usize, |
| 128 | +) c_int { |
| 129 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 130 | + const file_slice = std.mem.span(file); |
| 131 | + d.range = fehler.SourceRange.span(file_slice, start_line, start_col, end_line, end_col); |
| 132 | + return 0; |
| 133 | +} |
| 134 | + |
| 135 | +export fn fehler_diagnostic_set_help( |
| 136 | + diagnostic: *FehlerDiagnostic, |
| 137 | + help: [*:0]const u8, |
| 138 | +) c_int { |
| 139 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 140 | + const help_slice = std.mem.span(help); |
| 141 | + const owned_help = c_allocator.dupe(u8, help_slice) catch return -1; |
| 142 | + if (d.help) |old_help| c_allocator.free(old_help); |
| 143 | + d.help = owned_help; |
| 144 | + return 0; |
| 145 | +} |
| 146 | + |
| 147 | +export fn fehler_diagnostic_set_code( |
| 148 | + diagnostic: *FehlerDiagnostic, |
| 149 | + code: [*:0]const u8, |
| 150 | +) c_int { |
| 151 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 152 | + const code_slice = std.mem.span(code); |
| 153 | + const owned_code = c_allocator.dupe(u8, code_slice) catch return -1; |
| 154 | + if (d.code) |old_code| c_allocator.free(old_code); |
| 155 | + d.code = owned_code; |
| 156 | + return 0; |
| 157 | +} |
| 158 | + |
| 159 | +export fn fehler_diagnostic_set_url( |
| 160 | + diagnostic: *FehlerDiagnostic, |
| 161 | + url: [*:0]const u8, |
| 162 | +) c_int { |
| 163 | + const d: *fehler.Diagnostic = @ptrCast(@alignCast(diagnostic)); |
| 164 | + const url_slice = std.mem.span(url); |
| 165 | + const owned_url = c_allocator.dupe(u8, url_slice) catch return -1; |
| 166 | + if (d.url) |old_url| c_allocator.free(old_url); |
| 167 | + d.url = owned_url; |
| 168 | + return 0; |
| 169 | +} |
| 170 | + |
| 171 | +export fn fehler_report_simple( |
| 172 | + reporter: *FehlerReporter, |
| 173 | + severity: FehlerSeverity, |
| 174 | + message: [*:0]const u8, |
| 175 | + file: [*:0]const u8, |
| 176 | + line: usize, |
| 177 | + column: usize, |
| 178 | +) void { |
| 179 | + const diag = fehler_diagnostic_create(severity, message) orelse return; |
| 180 | + defer fehler_diagnostic_destroy(diag); |
| 181 | + _ = fehler_diagnostic_set_location(diag, file, line, column); |
| 182 | + fehler_reporter_report(reporter, diag); |
| 183 | +} |
| 184 | + |
| 185 | +export fn fehler_report_range( |
| 186 | + reporter: *FehlerReporter, |
| 187 | + severity: FehlerSeverity, |
| 188 | + message: [*:0]const u8, |
| 189 | + file: [*:0]const u8, |
| 190 | + start_line: usize, |
| 191 | + start_col: usize, |
| 192 | + end_line: usize, |
| 193 | + end_col: usize, |
| 194 | +) void { |
| 195 | + const diag = fehler_diagnostic_create(severity, message) orelse return; |
| 196 | + defer fehler_diagnostic_destroy(diag); |
| 197 | + _ = fehler_diagnostic_set_range(diag, file, start_line, start_col, end_line, end_col); |
| 198 | + fehler_reporter_report(reporter, diag); |
| 199 | +} |
| 200 | + |
| 201 | +export fn fehler_version() [*:0]const u8 { |
| 202 | + return "0.6.1"; |
| 203 | +} |
0 commit comments