This commit is contained in:
fn ⌃ ⌥ 2025-11-25 11:32:00 +08:00 committed by GitHub
commit 86ab6e3480
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 172 additions and 376 deletions

View file

@ -17,11 +17,11 @@ comptime {
_ = @import("c/inttypes.zig");
_ = @import("c/stdlib.zig");
_ = @import("c/math.zig");
_ = @import("c/string.zig");
_ = @import("c/strings.zig");
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
// Files specific to musl and wasi-libc.
_ = @import("c/string.zig");
_ = @import("c/strings.zig");
}
if (builtin.target.isMuslLibC()) {

View file

@ -4,6 +4,7 @@ const builtin = @import("builtin");
comptime {
if (builtin.target.isMinGW()) {
// Files specific to MinGW-w64.
@export(&isnan, .{ .name = "isnan", .linkage = common.linkage, .visibility = common.visibility });
@export(&isnan, .{ .name = "__isnan", .linkage = common.linkage, .visibility = common.visibility });
@export(&isnanf, .{ .name = "isnanf", .linkage = common.linkage, .visibility = common.visibility });

View file

@ -3,30 +3,44 @@ const std = @import("std");
const common = @import("common.zig");
comptime {
@export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&strcasecmp, .{ .name = "strcasecmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&strncasecmp, .{ .name = "strncasecmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&__strcasecmp_l, .{ .name = "__strcasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
@export(&__strncasecmp_l, .{ .name = "__strncasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
@export(&__strcasecmp_l, .{ .name = "strcasecmp_l", .linkage = .weak, .visibility = common.visibility });
@export(&__strncasecmp_l, .{ .name = "strncasecmp_l", .linkage = .weak, .visibility = common.visibility });
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
// Functions specific to musl and wasi-libc.
@export(&strcmp, .{ .name = "strcmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&strncmp, .{ .name = "strncmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&strcasecmp, .{ .name = "strcasecmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&strncasecmp, .{ .name = "strncasecmp", .linkage = common.linkage, .visibility = common.visibility });
@export(&__strcasecmp_l, .{ .name = "__strcasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
@export(&__strncasecmp_l, .{ .name = "__strncasecmp_l", .linkage = common.linkage, .visibility = common.visibility });
@export(&__strcasecmp_l, .{ .name = "strcasecmp_l", .linkage = .weak, .visibility = common.visibility });
@export(&__strncasecmp_l, .{ .name = "strncasecmp_l", .linkage = .weak, .visibility = common.visibility });
@export(&strspn, .{ .name = "strspn", .linkage = common.linkage, .visibility = common.visibility });
@export(&strcspn, .{ .name = "strcspn", .linkage = common.linkage, .visibility = common.visibility });
@export(&strpbrk, .{ .name = "strpbrk", .linkage = common.linkage, .visibility = common.visibility });
@export(&strstr, .{ .name = "strstr", .linkage = common.linkage, .visibility = common.visibility });
@export(&strtok, .{ .name = "strtok", .linkage = common.linkage, .visibility = common.visibility });
@export(&strtok_r, .{ .name = "strtok_r", .linkage = common.linkage, .visibility = common.visibility });
}
if (builtin.target.isMinGW()) {
// Files specific to MinGW-w64.
@export(&strtok_r, .{ .name = "strtok_r", .linkage = common.linkage, .visibility = common.visibility });
}
}
fn strcmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
fn strcmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) c_int {
// We need to perform unsigned comparisons.
return switch (std.mem.orderZ(u8, @ptrCast(s1), @ptrCast(s2))) {
return switch (std.mem.orderZ(u8, s1, s2)) {
.lt => -1,
.eq => 0,
.gt => 1,
};
}
fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
fn strncmp(s1: [*:0]const u8, s2: [*:0]const u8, n: usize) callconv(.c) c_int {
if (n == 0) return 0;
var l: [*:0]const u8 = @ptrCast(s1);
var r: [*:0]const u8 = @ptrCast(s2);
var l = s1;
var r = s2;
var i = n - 1;
while (l[0] != 0 and r[0] != 0 and i != 0 and l[0] == r[0]) {
@ -38,10 +52,10 @@ fn strncmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c)
return @as(c_int, l[0]) - @as(c_int, r[0]);
}
fn strcasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
fn strcasecmp(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) c_int {
const toLower = std.ascii.toLower;
var l: [*:0]const u8 = @ptrCast(s1);
var r: [*:0]const u8 = @ptrCast(s2);
var l = s1;
var r = s2;
while (l[0] != 0 and r[0] != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
l += 1;
@ -51,15 +65,15 @@ fn strcasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char) callconv(.c) c_int {
return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
}
fn __strcasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, locale: *anyopaque) callconv(.c) c_int {
fn __strcasecmp_l(s1: [*:0]const u8, s2: [*:0]const u8, locale: *anyopaque) callconv(.c) c_int {
_ = locale;
return strcasecmp(s1, s2);
}
fn strncasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(.c) c_int {
fn strncasecmp(s1: [*:0]const u8, s2: [*:0]const u8, n: usize) callconv(.c) c_int {
const toLower = std.ascii.toLower;
var l: [*:0]const u8 = @ptrCast(s1);
var r: [*:0]const u8 = @ptrCast(s2);
var l = s1;
var r = s2;
var i = n - 1;
while (l[0] != 0 and r[0] != 0 and i != 0 and (l[0] == r[0] or toLower(l[0]) == toLower(r[0]))) {
@ -71,34 +85,145 @@ fn strncasecmp(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize) callconv(
return @as(c_int, toLower(l[0])) - @as(c_int, toLower(r[0]));
}
fn __strncasecmp_l(s1: [*:0]const c_char, s2: [*:0]const c_char, n: usize, locale: *anyopaque) callconv(.c) c_int {
fn __strncasecmp_l(s1: [*:0]const u8, s2: [*:0]const u8, n: usize, locale: *anyopaque) callconv(.c) c_int {
_ = locale;
return strncasecmp(s1, s2, n);
}
test strcasecmp {
try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
try std.testing.expect(strcasecmp("a", "b") < 0);
try std.testing.expect(strcasecmp("b", "a") > 0);
try std.testing.expect(strcasecmp("A", "b") < 0);
try std.testing.expect(strcasecmp("b", "A") > 0);
try std.testing.expect(strcasecmp("A", "A") == 0);
try std.testing.expect(strcasecmp("B", "b") == 0);
try std.testing.expect(strcasecmp("bb", "AA") > 0);
}
test strncasecmp {
try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
try std.testing.expect(strncasecmp("a", "b", 1) < 0);
try std.testing.expect(strncasecmp("b", "a", 1) > 0);
try std.testing.expect(strncasecmp("A", "b", 1) < 0);
try std.testing.expect(strncasecmp("b", "A", 1) > 0);
try std.testing.expect(strncasecmp("A", "A", 1) == 0);
try std.testing.expect(strncasecmp("B", "b", 1) == 0);
try std.testing.expect(strncasecmp("bb", "AA", 2) > 0);
}
test strncmp {
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
try std.testing.expect(strncmp("a", "b", 1) < 0);
try std.testing.expect(strncmp("a", "c", 1) < 0);
try std.testing.expect(strncmp("b", "a", 1) > 0);
try std.testing.expect(strncmp("\xff", "\x02", 1) > 0);
}
fn strspn(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) usize {
const slice1 = std.mem.span(s1);
const slice2 = std.mem.span(s2);
return std.mem.indexOfNone(u8, slice1, slice2) orelse slice1.len;
}
test strspn {
try std.testing.expectEqual(0, strspn("foobarbaz", ""));
try std.testing.expectEqual(0, strspn("foobarbaz", "c"));
try std.testing.expectEqual(3, strspn("foobarbaz", "fo"));
try std.testing.expectEqual(9, strspn("foobarbaz", "fobarz"));
try std.testing.expectEqual(9, strspn("foobarbaz", "abforz"));
}
fn strcspn(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) usize {
const slice1 = std.mem.span(s1);
const slice2 = std.mem.span(s2);
return std.mem.indexOfAny(u8, slice1, slice2) orelse slice1.len;
}
test strcspn {
try std.testing.expectEqual(0, strcspn("foobarbaz", "f"));
try std.testing.expectEqual(3, strcspn("foobarbaz", "rab"));
try std.testing.expectEqual(4, strcspn("foobarbaz", "ra"));
try std.testing.expectEqual(9, strcspn("foobarbaz", ""));
}
fn strpbrk(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) ?[*:0]const u8 {
const slice1 = std.mem.span(s1);
const slice2 = std.mem.span(s2);
const index = std.mem.indexOfAny(u8, slice1, slice2) orelse
return null;
return s1 + index;
}
test strpbrk {
try std.testing.expectEqualStrings("barbaz", std.mem.span(strpbrk("foobarbaz", "rab").?));
try std.testing.expectEqualStrings("arbaz", std.mem.span(strpbrk("foobarbaz", "ra").?));
try std.testing.expectEqual(null, strpbrk("foobarbaz", ""));
}
fn strstr(s1: [*:0]const u8, s2: [*:0]const u8) callconv(.c) ?[*:0]const u8 {
const slice1 = std.mem.span(s1);
const slice2 = std.mem.span(s2);
const index = std.mem.indexOf(u8, slice1, slice2) orelse
return null;
return s1 + index;
}
test strstr {
try std.testing.expectEqualStrings("barbaz", std.mem.span(strstr("foobarbaz", "ba").?));
try std.testing.expectEqualStrings("foobarbaz", std.mem.span(strstr("foobarbaz", "fo").?));
try std.testing.expectEqualStrings("foobarbaz", std.mem.span(strstr("foobarbaz", "f").?));
try std.testing.expectEqualStrings("foobarbaz", std.mem.span(strstr("foobarbaz", "").?));
try std.testing.expectEqual(null, strstr("foobarbaz", "boofarfaz"));
try std.testing.expectEqual(null, strstr("foobarbaz", "fa"));
try std.testing.expectEqual(null, strstr("foobarbaz", "c"));
}
fn strtok_r(s: ?[*:0]u8, sep: [*:0]const u8, lasts: *?[*:0]u8) callconv(.c) ?[*:0]u8 {
const slice = std.mem.span(s orelse lasts.* orelse return null);
const delim = std.mem.span(sep);
const index = std.mem.indexOfNone(u8, slice, delim) orelse {
lasts.* = null;
return null;
};
if (std.mem.indexOfAny(u8, slice[index..], delim)) |len| {
slice[index + len] = 0;
lasts.* = slice[index + len + 1 ..];
} else {
lasts.* = null;
}
return slice[index..];
}
fn strtok(s: ?[*:0]u8, sep: [*:0]const u8) callconv(.c) ?[*:0]u8 {
const static = struct {
var lasts: ?[*:0]u8 = null;
};
return strtok_r(s, sep, &static.lasts);
}
test strtok {
var str = "?a???b,,,#c?#,".*;
{
const ret = strtok(&str, "?");
try std.testing.expectEqual(str[1..], ret);
try std.testing.expectEqualStrings("a", std.mem.span(ret.?));
}
{
const ret = strtok(null, ",");
try std.testing.expectEqual(str[3..], ret);
try std.testing.expectEqualStrings("??b", std.mem.span(ret.?));
}
{
const ret = strtok(null, "#,");
try std.testing.expectEqual(str[10..], ret);
try std.testing.expectEqualStrings("c?", std.mem.span(ret.?));
}
{
const ret = strtok(null, "?");
try std.testing.expectEqual(str[13..], ret);
try std.testing.expectEqualStrings(",", std.mem.span(ret.?));
}
{
const ret = strtok(null, "?");
try std.testing.expectEqual(null, ret);
}
try std.testing.expectEqualSlices(u8, "?a" ++ .{0} ++ "??b" ++ .{0} ++ ",,#c?" ++ .{0} ++ ",", &str);
}

View file

@ -1,8 +1,12 @@
const builtin = @import("builtin");
const std = @import("std");
const common = @import("common.zig");
comptime {
@export(&bzero, .{ .name = "bzero", .linkage = common.linkage, .visibility = common.visibility });
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
// Functions specific to musl and wasi-libc.
@export(&bzero, .{ .name = "bzero", .linkage = common.linkage, .visibility = common.visibility });
}
}
fn bzero(s: *anyopaque, n: usize) callconv(.c) void {

View file

@ -1,98 +0,0 @@
/*-
* Copyright (c) 1998 Softweyr LLC. All rights reserved.
*
* strtok_r, from Berkeley strtok
* Oct 13, 1998 by Wes Peters <wes@softweyr.com>
*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notices, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notices, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
* REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _POSIX_SOURCE 1
#include <string.h>
/*
* strtok_r documentation:
* http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok.html
*
* Implementation:
* http://svnweb.freebsd.org/base/head/lib/libc/string/strtok.c?view=co
*
* strtok_r cannot completely be implemented by strtok because of the internal state.
* It breaks when used on 2 strings where they are scanned A, B then A, B.
* Thread-safety is not the issue.
*
* Sample strtok implemenatation, note the internal state:
* char *strtok(char *s, const char *d) { static char *t; return strtok_r(s,d,t); }
*
*/
char *
strtok_r(char * __restrict s, const char * __restrict delim, char ** __restrict last)
{
char *spanp, *tok;
int c, sc;
if (s == NULL && (s = *last) == NULL)
return (NULL);
/*
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
*/
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
if (c == 0) { /* no non-delimiter characters */
*last = NULL;
return (NULL);
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
*/
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = '\0';
*last = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}

View file

@ -1,17 +0,0 @@
#include <string.h>
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
size_t strcspn(const char *s, const char *c)
{
const char *a = s;
size_t byteset[32/sizeof(size_t)];
if (!c[0] || !c[1]) return __strchrnul(s, *c)-a;
memset(byteset, 0, sizeof byteset);
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++);
return s-a;
}

View file

@ -1,7 +0,0 @@
#include <string.h>
char *strpbrk(const char *s, const char *b)
{
s += strcspn(s, b);
return *s ? (char *)s : 0;
}

View file

@ -1,20 +0,0 @@
#include <string.h>
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
size_t strspn(const char *s, const char *c)
{
const char *a = s;
size_t byteset[32/sizeof(size_t)] = { 0 };
if (!c[0]) return 0;
if (!c[1]) {
for (; *s == *c; s++);
return s-a;
}
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
return s-a;
}

View file

@ -1,154 +0,0 @@
#include <string.h>
#include <stdint.h>
static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
{
uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
for (h++; *h && hw != nw; hw = hw<<8 | *++h);
return *h ? (char *)h-1 : 0;
}
static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
{
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
return *h ? (char *)h-2 : 0;
}
static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
{
uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
return *h ? (char *)h-3 : 0;
}
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
{
const unsigned char *z;
size_t l, ip, jp, k, p, ms, p0, mem, mem0;
size_t byteset[32 / sizeof(size_t)] = { 0 };
size_t shift[256];
/* Computing length of needle and fill shift table */
for (l=0; n[l] && h[l]; l++)
BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
if (n[l]) return 0; /* hit the end of h */
/* Compute maximal suffix */
ip = -1; jp = 0; k = p = 1;
while (jp+k<l) {
if (n[ip+k] == n[jp+k]) {
if (k == p) {
jp += p;
k = 1;
} else k++;
} else if (n[ip+k] > n[jp+k]) {
jp += k;
k = 1;
p = jp - ip;
} else {
ip = jp++;
k = p = 1;
}
}
ms = ip;
p0 = p;
/* And with the opposite comparison */
ip = -1; jp = 0; k = p = 1;
while (jp+k<l) {
if (n[ip+k] == n[jp+k]) {
if (k == p) {
jp += p;
k = 1;
} else k++;
} else if (n[ip+k] < n[jp+k]) {
jp += k;
k = 1;
p = jp - ip;
} else {
ip = jp++;
k = p = 1;
}
}
if (ip+1 > ms+1) ms = ip;
else p = p0;
/* Periodic needle? */
if (memcmp(n, n+p, ms+1)) {
mem0 = 0;
p = MAX(ms, l-ms-1) + 1;
} else mem0 = l-p;
mem = 0;
/* Initialize incremental end-of-haystack pointer */
z = h;
/* Search loop */
for (;;) {
/* Update incremental end-of-haystack pointer */
if (z-h < l) {
/* Fast estimate for MAX(l,63) */
size_t grow = l | 63;
const unsigned char *z2 = memchr(z, 0, grow);
if (z2) {
z = z2;
if (z-h < l) return 0;
} else z += grow;
}
/* Check last byte first; advance by shift on mismatch */
if (BITOP(byteset, h[l-1], &)) {
k = l-shift[h[l-1]];
if (k) {
if (k < mem) k = mem;
h += k;
mem = 0;
continue;
}
} else {
h += l;
mem = 0;
continue;
}
/* Compare right half */
for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
if (n[k]) {
h += k-ms;
mem = 0;
continue;
}
/* Compare left half */
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
if (k <= mem) return (char *)h;
h += p;
mem = mem0;
}
}
char *strstr(const char *h, const char *n)
{
/* Return immediately on empty needle */
if (!n[0]) return (char *)h;
/* Use faster algorithms for short needles */
h = strchr(h, *n);
if (!h || !n[1]) return (char *)h;
if (!h[1]) return 0;
if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
if (!h[2]) return 0;
if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
if (!h[3]) return 0;
if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
return twoway_strstr((void *)h, (void *)n);
}

View file

@ -1,13 +0,0 @@
#include <string.h>
char *strtok(char *restrict s, const char *restrict sep)
{
static char *p;
if (!s && !(s = p)) return NULL;
s += strspn(s, sep);
if (!*s) return p = 0;
p = s + strcspn(s, sep);
if (*p) *p++ = 0;
else p = 0;
return s;
}

View file

@ -1,12 +0,0 @@
#include <string.h>
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict p)
{
if (!s && !(s = *p)) return NULL;
s += strspn(s, sep);
if (!*s) return *p = 0;
*p = s + strcspn(s, sep);
if (**p) *(*p)++ = 0;
else *p = 0;
return s;
}

View file

@ -740,7 +740,6 @@ const mingw32_generic_src = [_][]const u8{
"stdio" ++ path.sep_str ++ "mingw_vswscanf.c",
"stdio" ++ path.sep_str ++ "snprintf.c",
"stdio" ++ path.sep_str ++ "snwprintf.c",
"stdio" ++ path.sep_str ++ "strtok_r.c",
"stdio" ++ path.sep_str ++ "truncate.c",
"stdio" ++ path.sep_str ++ "ulltoa.c",
"stdio" ++ path.sep_str ++ "ulltow.c",

View file

@ -1768,7 +1768,6 @@ const src_files = [_][]const u8{
"musl/src/string/strchr.c",
"musl/src/string/strchrnul.c",
"musl/src/string/strcpy.c",
"musl/src/string/strcspn.c",
"musl/src/string/strdup.c",
"musl/src/string/strerror_r.c",
"musl/src/string/strlcat.c",
@ -1777,14 +1776,9 @@ const src_files = [_][]const u8{
"musl/src/string/strncpy.c",
"musl/src/string/strndup.c",
"musl/src/string/strnlen.c",
"musl/src/string/strpbrk.c",
"musl/src/string/strrchr.c",
"musl/src/string/strsep.c",
"musl/src/string/strsignal.c",
"musl/src/string/strspn.c",
"musl/src/string/strstr.c",
"musl/src/string/strtok.c",
"musl/src/string/strtok_r.c",
"musl/src/string/strverscmp.c",
"musl/src/string/swab.c",
"musl/src/string/wcpcpy.c",

View file

@ -1045,7 +1045,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/string/strcat.c",
"musl/src/string/strchr.c",
"musl/src/string/strcpy.c",
"musl/src/string/strcspn.c",
"musl/src/string/strdup.c",
"musl/src/string/strerror_r.c",
"musl/src/string/strlcat.c",
@ -1054,13 +1053,8 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/string/strncpy.c",
"musl/src/string/strndup.c",
"musl/src/string/strnlen.c",
"musl/src/string/strpbrk.c",
"musl/src/string/strrchr.c",
"musl/src/string/strsep.c",
"musl/src/string/strspn.c",
"musl/src/string/strstr.c",
"musl/src/string/strtok.c",
"musl/src/string/strtok_r.c",
"musl/src/string/strverscmp.c",
"musl/src/string/swab.c",
"musl/src/string/wcpcpy.c",