/* string_api.c —— `Lib/c/string.h` 里那 9 个**从前只有声明、没有实现**的标准 C 函数的判据。
 * string_api.c — criterion for the nine standard C functions that used to be declared with no body.
 *
 * ## 为什么单独立一个
 * ## Why a dedicated probe
 *
 * 它们从前是「**照着头写能编过、链接时才报 `未解析标签`**」（本仓点名过这是最难查的一类错）。
 * 2026-10-08 补了实现 —— 而"补上了"这件事**必须有一条会响的判据**：这 9 个函数各自有
 * 明确的边界（`strncat` 的截断、`strrchr` 找结尾 0、`strtok` 的跨调用游标…），
 * 写错一半照样能编过。
 *
 * They compile fine either way; only their edge behaviour tells whether the bodies are right.
 *
 * 跑法（桌面，秒级）：
 *     dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll third_party/vml/Examples/c/test/string_api.c
 */

#include <string.h>

int fails = 0;

/* 比字符串：`got` 与 `want` 相等记 OK —— ⚠ 一律 `strcmp` 比**内容**，不比指针
 * （两个内容相同的字面量地址不同，比指针会全假红）。 */
void ck_s(char* name, char* got, char* want) {
    if (strcmp(got, want) == 0) {
        printf("OK   %s = %s\n", name, got);
    } else {
        printf("FAIL %s: got %s, want %s\n", name, got, want);
        fails = fails + 1;
    }
}

void ck_i(char* name, int got, int want) {
    if (got == want) {
        printf("OK   %s = %d\n", name, got);
    } else {
        printf("FAIL %s: got %d, want %d\n", name, got, want);
        fails = fails + 1;
    }
}

int main(void) {
    char b[64];
    char t[64];
    char* p;
    int n;

    /* ① strncat：只接 n 个字符 */
    strcpy(b, "abc");
    strncat(b, "defgh", 2);
    ck_s("strncat(n=2)", b, "abcde");

    /* ② strrchr：找**最后**一个（不是第一个） */
    strcpy(b, "a/b/c");
    p = strrchr(b, '/');
    ck_s("strrchr", p, "/c");

    /* ③ strrchr 找 0 ⇒ 指向结尾（标准语义） */
    strcpy(b, "abc");
    n = (int)strrchr(b, 0) - (int)b;
    ck_i("strrchr(0) 指向结尾", n, 3);

    /* ④ strpbrk：第一处出现在 accept 里的字符 */
    strcpy(b, "hello world");
    p = strpbrk(b, "ow");
    ck_s("strpbrk", p, "o world");

    /* ⑤ strspn：开头连续属于 accept 的长度 */
    ck_i("strspn", strspn("aabbcc", "ab"), 4);

    /* ⑥ strcspn：开头连续**不**属于 reject 的长度 */
    ck_i("strcspn", strcspn("aabbcc", "bc"), 2);

    /* ⑦ memchr：在给定的 n 字节内找 */
    strcpy(b, "abcdef");
    p = memchr(b, 'd', 6);
    ck_s("memchr", p, "def");
    p = memchr(b, 'd', 3);
    ck_i("memchr 越界内找不到", p == 0, 1);

    /* ⑧ strcoll：本平台就是 strcmp */
    ck_i("strcoll 相等", strcoll("abc", "abc"), 0);
    ck_i("strcoll 小于", strcoll("abc", "abd") < 0, 1);

    /* ⑨ strxfrm：拷贝 + 返回需要的长度 */
    strcpy(b, "-------");
    n = strxfrm(b, "hello", 64);
    ck_s("strxfrm 拷贝", b, "hello");
    ck_i("strxfrm 返回长度", n, 5);

    /* ⑩ strtok：连续切分（游标要跨调用保住）*/
    strcpy(t, "a,bb,ccc");
    p = strtok(t, ",");
    ck_s("strtok 第 1 段", p, "a");
    p = strtok(0, ",");
    ck_s("strtok 第 2 段", p, "bb");
    p = strtok(0, ",");
    ck_s("strtok 第 3 段", p, "ccc");
    p = strtok(0, ",");
    ck_i("strtok 到头返回 0", p == 0, 1);

    printf("STRING_API %s (fails=%d)\n", fails == 0 ? "PASS" : "FAIL", fails);
    return fails;
}
