Add chibicc

This program popped up on Hacker News recently. It's the only modern
compiler I've ever seen that doesn't have dependencies and is easily
modified. So I added all of the missing GNU extensions I like to use
which means it might be possible soon to build on non-Linux and have
third party not vendor gcc binaries.
This commit is contained in:
Justine Tunney 2020-12-05 12:20:41 -08:00
parent e44a0cf6f8
commit 8da931a7f6
298 changed files with 19493 additions and 11950 deletions

View file

@ -19,14 +19,16 @@
*/
#include "libc/str/str.h"
#undef char
#undef endswith
#undef strlen
#undef strnlen
#define char char16_t
#define endswith endswith16
#define strlen strlen16
#define strnlen strnlen16
#include "libc/str/endswith.c"
/**
* Returns true if s has suffix.
*
* @param s is a NUL-terminated string
* @param suffix is also NUL-terminated
*/
bool endswith16(const char16_t *s, const char16_t *suffix) {
size_t n, m;
n = strlen16(s);
m = strlen16(suffix);
if (m > n) return false;
return memcmp(s + n - m, suffix, m * sizeof(char16_t)) == 0;
}

View file

@ -19,14 +19,16 @@
*/
#include "libc/str/str.h"
#undef char
#undef startswith
#undef strlen
#undef strncmp
#define char char16_t
#define startswith startswith16
#define strlen strlen16
#define strncmp strncmp16
#include "libc/str/startswith.c"
/**
* Returns true if s has prefix.
*
* @param s is a NUL-terminated string
* @param prefix is also NUL-terminated
*/
bool startswith16(const char16_t *s, const char16_t *prefix) {
for (;;) {
if (!*prefix) return true;
if (!*s) return false;
if (*s++ != *prefix++) return false;
}
}

View file

@ -238,8 +238,8 @@ char *strsignal(int) returnsnonnull libcesque;
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
#define strncpy(DEST, SRC, N) _strncpy(DEST, SRC, N) /* pacify bad warning */
char *__strncpy(char *, const char *, size_t) memcpyesque;
#define strncpy(DEST, SRC, N) __strncpy(DEST, SRC, N) /* pacify bad warning */
#define explicit_bzero(STR, BYTES) \
do { \
@ -318,7 +318,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
size_t SiZe = (SIZE); \
size_t Rcx; \
asm("rep movsb" \
: "=D"(Rdi), "=S"(Rsi), "=D"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
: "=D"(Rdi), "=S"(Rsi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
: "0"(Dest), "1"(Src), "2"(SiZe), "m"(*(const char(*)[SiZe])(Src)) \
: "cc"); \
Rdi; \
@ -351,9 +351,6 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
#endif /* hosted/sse2/unbloat */
size_t _strlen(const char *s) asm("strlen") strlenesque;
void *_memchr(const void *, int, size_t) asm("memchr") strlenesque;
#endif /* __GNUC__ && !__STRICT_ANSI__ */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

24
libc/str/strncpy.thunk.S Normal file
View file

@ -0,0 +1,24 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
__strncpy:
jmp strncpy
.endfn __strncpy,globl

View file

@ -24,7 +24,7 @@
* Returns pointer to first byte matching any in accept, or NULL.
* @asyncsignalsafe
*/
char *(strpbrk)(const char *s, const char *accept) {
char *strpbrk(const char *s, const char *accept) {
size_t i;
if (accept[0]) {
if (!accept[1]) {

View file

@ -20,10 +20,22 @@
#include "libc/nexgen32e/hascharacter.internal.h"
#include "libc/str/str.h"
#undef strpbrk
#define char char16_t
#define HasCharacter HasCharacter16
#define strpbrk strpbrk16
#define strchr(x, y) strchr16(x, y)
#include "libc/str/strpbrk.c"
/**
* Returns pointer to first byte matching any in accept, or NULL.
* @asyncsignalsafe
*/
char16_t *strpbrk16(const char16_t *s, const char16_t *accept) {
size_t i;
if (accept[0]) {
if (!accept[1]) {
return strchr16(s, accept[0]);
} else {
for (i = 0; s[i]; ++i) {
if (HasCharacter16(s[i], accept)) {
return (/*unconst*/ char16_t *)&s[i];
}
}
}
}
return NULL;
}

View file

@ -27,7 +27,7 @@
* @see strcspn(), strtok_r()
* @asyncsignalsafe
*/
size_t(strspn)(const char *s, const char *accept) {
size_t strspn(const char *s, const char *accept) {
size_t i;
for (i = 0; s[i]; ++i) {
if (!HasCharacter(s[i], accept)) {

View file

@ -20,9 +20,19 @@
#include "libc/nexgen32e/hascharacter.internal.h"
#include "libc/str/str.h"
#undef strspn
#define char char16_t
#define HasCharacter HasCharacter16
#define strspn strspn16
#include "libc/str/strspn.c"
/**
* Returns prefix length, consisting of chars in accept.
*
* @param accept is nul-terminated character set
* @see strcspn(), strtok_r()
* @asyncsignalsafe
*/
size_t strspn16(const char16_t *s, const char16_t *accept) {
size_t i;
for (i = 0; s[i]; ++i) {
if (!HasCharacter16(s[i], accept)) {
break;
}
}
return i;
}

View file

@ -18,7 +18,6 @@
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/dce.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/internal.h"
#include "libc/str/str.h"
@ -32,22 +31,26 @@
* @asyncsignalsafe
* @see memmem()
*/
char *(strstr)(const char *haystack, const char *needle) {
char *strstr(const char *haystack, const char *needle) {
size_t i;
if (needle[0]) {
if (needle[1]) {
if (!((intptr_t)needle & 0xf) && X86_HAVE(SSE4_2)) {
return strstr$sse42(haystack, needle);
} else {
size_t needlelen;
alignas(16) char needle2[64];
needlelen = strlen(needle);
if (needlelen < 64 && X86_HAVE(SSE4_2)) {
memcpy(needle2, needle, (needlelen + 1) * sizeof(char));
return strstr$sse42(haystack, needle2);
} else {
return tinystrstr(haystack, needle);
for (;;) {
#if 0 /* todo: fix me */
if (!((uintptr_t)haystack & 15) && X86_HAVE(SSE4_2) &&
(((uintptr_t)needle + strlen(needle)) & 0xfff) <= 0xff0) {
return strstr$sse42(haystack, needle);
}
#endif
for (i = 0;;) {
if (!needle[i]) return haystack;
if (!haystack[i]) break;
if (needle[i] != haystack[i]) break;
++i;
}
if (!*haystack++) break;
}
return NULL;
} else {
return strchr(haystack, needle[0]);
}

View file

@ -19,14 +19,16 @@
*/
#include "libc/str/str.h"
#undef char
#undef endswith
#undef strlen
#undef strnlen
#define char wchar_t
#define endswith wcsendswith
#define strlen wcslen
#define strnlen wcsnlen
#include "libc/str/endswith.c"
/**
* Returns true if s has suffix.
*
* @param s is a NUL-terminated string
* @param suffix is also NUL-terminated
*/
bool wcsendswith(const wchar_t *s, const wchar_t *suffix) {
size_t n, m;
n = wcslen(s);
m = wcslen(suffix);
if (m > n) return false;
return memcmp(s + n - m, suffix, m * sizeof(wchar_t)) == 0;
}

View file

@ -20,10 +20,22 @@
#include "libc/nexgen32e/hascharacter.internal.h"
#include "libc/str/str.h"
#undef strpbrk
#define char wchar_t
#define HasCharacter HasCharacterWide
#define strpbrk wcspbrk
#define strchr(x, y) wcschr(x, y)
#include "libc/str/strpbrk.c"
/**
* Returns pointer to first byte matching any in accept, or NULL.
* @asyncsignalsafe
*/
wchar_t *wcspbrk(const wchar_t *s, const wchar_t *accept) {
size_t i;
if (accept[0]) {
if (!accept[1]) {
return wcschr(s, accept[0]);
} else {
for (i = 0; s[i]; ++i) {
if (HasCharacterWide(s[i], accept)) {
return (/*unconst*/ wchar_t *)&s[i];
}
}
}
}
return NULL;
}

View file

@ -20,9 +20,19 @@
#include "libc/nexgen32e/hascharacter.internal.h"
#include "libc/str/str.h"
#undef strspn
#define char wchar_t
#define HasCharacter HasCharacterWide
#define strspn wcsspn
#include "libc/str/strspn.c"
/**
* Returns prefix length, consisting of chars in accept.
*
* @param accept is nul-terminated character set
* @see strcspn(), strtok_r()
* @asyncsignalsafe
*/
size_t wcsspn(const wchar_t *s, const wchar_t *accept) {
size_t i;
for (i = 0; s[i]; ++i) {
if (!HasCharacterWide(s[i], accept)) {
break;
}
}
return i;
}

View file

@ -19,14 +19,16 @@
*/
#include "libc/str/str.h"
#undef char
#undef startswith
#undef strlen
#undef strncmp
#define char wchar_t
#define startswith wcsstartswith
#define strlen wcslen
#define strncmp wcsncmp
#include "libc/str/startswith.c"
/**
* Returns true if s has prefix.
*
* @param s is a NUL-terminated string
* @param prefix is also NUL-terminated
*/
bool wcsstartswith(const wchar_t *s, const wchar_t *prefix) {
for (;;) {
if (!*prefix) return true;
if (!*s) return false;
if (*s++ != *prefix++) return false;
}
}