| 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); |
| 3 | const symbol = @import("../c.zig").symbol; |
| 4 | |
| 5 | comptime { |
| 6 | if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { |
| 7 | // bcmp is implemented in compiler_rt |
| 8 | symbol(&bcopy, "bcopy"); |
| 9 | symbol(&bzero, "bzero"); |
| 10 | symbol(&index, "index"); |
| 11 | symbol(&rindex, "rindex"); |
| 12 | |
| 13 | symbol(&ffs, "ffs"); |
| 14 | symbol(&ffsl, "ffsl"); |
| 15 | symbol(&ffsll, "ffsll"); |
| 16 | |
| 17 | symbol(&strcasecmp, "strcasecmp"); |
| 18 | symbol(&strncasecmp, "strncasecmp"); |
| 19 | |
| 20 | symbol(&__strcasecmp_l, "__strcasecmp_l"); |
| 21 | symbol(&__strncasecmp_l, "__strncasecmp_l"); |
| 22 | |
| 23 | symbol(&__strcasecmp_l, "strcasecmp_l"); |
| 24 | symbol(&__strncasecmp_l, "strncasecmp_l"); |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | fn bcopy(src: *const anyopaque, dst: *anyopaque, len: usize) callconv(.c) void { |
| 29 | const src_bytes: [*]const u8 = @ptrCast(src); |
| 30 | const dst_bytes: [*]u8 = @ptrCast(dst); |
| 31 | @memmove(dst_bytes[0..len], src_bytes[0..len]); |
| 32 | } |
| 33 | |
| 34 | fn bzero(s: *anyopaque, n: usize) callconv(.c) void { |
| 35 | const s_cast: [*]u8 = @ptrCast(s); |
| 36 | @memset(s_cast[0..n], 0); |
| 37 | } |
| 38 | |
| 39 | fn index(str: [*:0]const c_char, value: c_int) callconv(.c) ?[*:0]c_char { |
| 40 | return @constCast(str[std.mem.findScalar(u8, std.mem.span(@as([*:0]const u8, @ptrCast(str))), @truncate(@as(c_uint, @bitCast(value)))) orelse return null ..]); |
| 41 | } |
| 42 | |
| 43 | fn rindex(str: [*:0]const c_char, value: c_int) callconv(.c) ?[*:0]c_char { |
| 44 | return @constCast(str[std.mem.findScalarLast(u8, std.mem.span(@as([*:0]const u8, @ptrCast(str))), @truncate(@as(c_uint, @bitCast(value)))) orelse return null ..]); |
| 45 | } |
| 46 | |
| 47 | fn firstBitSet(comptime T: type, value: T) T { |
| 48 | return @bitSizeOf(T) - @clz(value); |
| 49 | } |
| 50 | |
| 51 | fn ffs(i: c_int) callconv(.c) c_int { |
| 52 | return firstBitSet(c_int, i); |
| 53 | } |
| 54 | |
| 55 | fn ffsl(i: c_long) callconv(.c) c_long { |
| 56 | return firstBitSet(c_long, i); |
| 57 | } |
| 58 | |
| 59 | fn ffsll(i: c_longlong) callconv(.c) c_longlong { |
| 60 | return firstBitSet(c_longlong, i); |
| 61 | } |
| 62 | |
| 63 | fn strcasecmp(a: [*:0]const c_char, b: [*:0]const c_char) callconv(.c) c_int { |
| 64 | return strncasecmp(a, b, std.math.maxInt(usize)); |
| 65 | } |
| 66 | |
| 67 | fn __strcasecmp_l(a: [*:0]const c_char, b: [*:0]const c_char, locale: *anyopaque) callconv(.c) c_int { |
| 68 | _ = locale; |
| 69 | return strcasecmp(a, b); |
| 70 | } |
| 71 | |
| 72 | fn strncasecmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) callconv(.c) c_int { |
| 73 | return switch (std.ascii.boundedOrderIgnoreCaseZ(@ptrCast(a), @ptrCast(b), max)) { |
| 74 | .eq => 0, |
| 75 | .gt => 1, |
| 76 | .lt => -1, |
| 77 | }; |
| 78 | } |
| 79 | |
| 80 | fn __strncasecmp_l(a: [*:0]const c_char, b: [*:0]const c_char, n: usize, locale: *anyopaque) callconv(.c) c_int { |
| 81 | _ = locale; |
| 82 | return strncasecmp(a, b, n); |
| 83 | } |