// ============================================================================ // lib/string.cpp - Freestanding memory and string operations // // These are required because we compile with -nostdlib. // The compiler may generate implicit calls to memcpy/memset/memmove // (e.g., for struct copies, array init), so these must exist with // standard C linkage and standard names. // ============================================================================ #include #include extern "C" { void* memcpy(void* dest, const void* src, size_t n) { auto* d = static_cast(dest); auto* s = static_cast(src); for (size_t i = 0; i < n; i++) d[i] = s[i]; return dest; } void* memmove(void* dest, const void* src, size_t n) { auto* d = static_cast(dest); auto* s = static_cast(src); if (d < s) { for (size_t i = 0; i < n; i++) d[i] = s[i]; } else { for (size_t i = n; i > 0; i--) d[i - 1] = s[i - 1]; } return dest; } void* memset(void* dest, int val, size_t n) { auto* d = static_cast(dest); for (size_t i = 0; i < n; i++) d[i] = static_cast(val); return dest; } int memcmp(const void* s1, const void* s2, size_t n) { auto* a = static_cast(s1); auto* b = static_cast(s2); for (size_t i = 0; i < n; i++) { // Cast to int before subtracting: uint8_t → int is safe, range [0, 255] if (a[i] != b[i]) return static_cast(a[i]) - static_cast(b[i]); } return 0; } size_t strlen(const char* s) { size_t len = 0; while (s[len]) len++; return len; } int strcmp(const char* s1, const char* s2) { // Cast to unsigned before comparison — char may be signed, // and unsigned subtraction gives the correct lexicographic ordering. const auto* u1 = reinterpret_cast(s1); const auto* u2 = reinterpret_cast(s2); while (*u1 && *u1 == *u2) { ++u1; ++u2; } return static_cast(*u1) - static_cast(*u2); } char* strcpy(char* dest, const char* src) { char* ret = dest; while (*src) *dest++ = *src++; *dest = '\0'; return ret; } char* strncpy(char* dest, const char* src, size_t n) { size_t i = 0; for (; i < n && src[i]; i++) dest[i] = src[i]; for (; i < n; i++) dest[i] = '\0'; return dest; } } // extern "C"