mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 03:08:31 +00:00
Add x86_64-linux-gnu emulator
I wanted a tiny scriptable meltdown proof way to run userspace programs and visualize how program execution impacts memory. It helps to explain how things like Actually Portable Executable works. It can show you how the GCC generated code is going about manipulating matrices and more. I didn't feel fully comfortable with Qemu and Bochs because I'm not smart enough to understand them. I wanted something like gVisor but with much stronger levels of assurances. I wanted a single binary that'll run, on all major operating systems with an embedded GPL barrier ZIP filesystem that is tiny enough to transpile to JavaScript and run in browsers too. https://justine.storage.googleapis.com/emulator625.mp4
This commit is contained in:
parent
467504308a
commit
f4f4caab0e
1052 changed files with 65667 additions and 7825 deletions
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_APPENDCHAR_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_APPENDCHAR_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "libc/str/tpencode.h"
|
||||
|
@ -15,4 +16,5 @@ static inline void AppendChar(char **p, char *pe, wint_t wc) {
|
|||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* !ANSI */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_APPENDCHAR_H_ */
|
||||
|
|
58
libc/str/getcachesize.c
Normal file
58
libc/str/getcachesize.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/cachesize.h"
|
||||
#include "libc/nexgen32e/cpuid4.h"
|
||||
|
||||
static unsigned getcachesize$cpuid4(int type, int level) {
|
||||
unsigned i, k;
|
||||
static int once;
|
||||
static unsigned char kCacheKey[8];
|
||||
static unsigned kCacheSize[8];
|
||||
if (!once) {
|
||||
CPUID4_ITERATE(i, {
|
||||
kCacheKey[i] = CPUID4_KEY;
|
||||
kCacheSize[i] = CPUID4_CACHE_SIZE_IN_BYTES;
|
||||
});
|
||||
once = 1;
|
||||
}
|
||||
k = ((level & 7) << 5) | (type & 31);
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if (kCacheKey[i] == k) {
|
||||
return kCacheSize[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns CPU cache size.
|
||||
*
|
||||
* @param type 1=data, 2=instruction, 3=unified
|
||||
* @param level starts at 1
|
||||
* @return size in bytes, or 0 if unknown
|
||||
*/
|
||||
unsigned getcachesize(enum CpuCacheType type, int level) {
|
||||
assert(1 <= type && type <= 3);
|
||||
assert(level >= 1);
|
||||
return getcachesize$cpuid4(type, level);
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
* @note synchronization is performed to skip leading continuations;
|
||||
* canonicalization and validation are performed to some extent
|
||||
*/
|
||||
unsigned(getutf16)(const char16_t *p, wint_t *wc) {
|
||||
forcealignargpointer unsigned(getutf16)(const char16_t *p, wint_t *wc) {
|
||||
unsigned skip = 0;
|
||||
while ((p[skip] & UTF16_MASK) == UTF16_CONT) skip++;
|
||||
if ((p[skip] & UTF16_MASK) != UTF16_MOAR) {
|
||||
|
|
39
libc/str/getx86processormodel.c
Normal file
39
libc/str/getx86processormodel.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/alg/bisect.h"
|
||||
#include "libc/nexgen32e/x86info.h"
|
||||
|
||||
static int CmpX86ProcModelKey(const struct X86ProcessorModel *a,
|
||||
const struct X86ProcessorModel *b) {
|
||||
return a->key > b->key ? 1 : a->key < b->key ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies microarchitecture of host processor.
|
||||
*
|
||||
* @param key can be kX86ProcessorModelKey for host info
|
||||
* @see https://en.wikichip.org/wiki/intel/cpuid
|
||||
* @see https://a4lg.com/tech/x86/database/x86-families-and-models.en.html
|
||||
*/
|
||||
const struct X86ProcessorModel *getx86processormodel(short key) {
|
||||
return bisect(&(struct X86ProcessorModel){key}, kX86ProcessorModels,
|
||||
kX86ProcessorModelCount, sizeof(struct X86ProcessorModel),
|
||||
(void *)CmpX86ProcModelKey, NULL);
|
||||
}
|
39
libc/str/insertionsort.greg.c
Normal file
39
libc/str/insertionsort.greg.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/log/log.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
|
||||
/**
|
||||
* Sorts array of signed 32-bit integers.
|
||||
* @see djbsort()
|
||||
*/
|
||||
textreal void insertionsort(size_t n, int32_t a[n]) {
|
||||
int t;
|
||||
unsigned i, j;
|
||||
for (i = 1; i < n; ++i) {
|
||||
j = i;
|
||||
t = a[i];
|
||||
while (j > 0 && t < a[j - 1]) {
|
||||
a[j] = a[j - 1];
|
||||
--j;
|
||||
}
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_STR_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_INTERNAL_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
@ -48,16 +49,13 @@ nodebuginfo forceinline bool32 iscont(wint_t c) {
|
|||
return (c & 0b11000000) == 0b10000000;
|
||||
}
|
||||
|
||||
extern const uint32_t kCrc32Tab[256];
|
||||
|
||||
char *strstr$sse42(const char *, const char *) strlenesque hidden;
|
||||
char16_t *strstr16$sse42(const char16_t *, const char16_t *) strlenesque hidden;
|
||||
void *memmem$sse42(const void *, size_t, const void *,
|
||||
size_t) strlenesque hidden;
|
||||
uint32_t crc32c$sse42(uint32_t, const void *, size_t) strlenesque hidden;
|
||||
uint32_t crc32$pclmul(uint32_t, const void *, size_t) hidden;
|
||||
void sha256$x86(uint32_t[hasatleast 8], const uint8_t[hasatleast 64],
|
||||
uint32_t) hidden;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* !ANSI */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_INTERNAL_H_ */
|
||||
|
|
33
libc/str/knobs.c
Normal file
33
libc/str/knobs.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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 "tool/viz/lib/knobs.h"
|
||||
|
||||
bool pf1_;
|
||||
bool pf2_;
|
||||
bool pf3_;
|
||||
bool pf4_;
|
||||
bool pf5_;
|
||||
bool pf6_;
|
||||
bool pf7_;
|
||||
bool pf8_;
|
||||
bool pf9_;
|
||||
bool pf10_;
|
||||
bool pf11_;
|
||||
bool pf12_;
|
|
@ -1,26 +1,15 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_KNUTHMULTIPLICATIVEHASH_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_KNUTHMULTIPLICATIVEHASH_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
forceinline uint32_t KnuthMultiplicativeHash32(const void *buf, size_t size) {
|
||||
/* frozen due to presence in sqlite & promise in libc/getuid.c */
|
||||
const unsigned char *const p = (const unsigned char *)buf;
|
||||
uint32_t hash = 0, kPhiPrime = 0x9e3779b1;
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) hash = (p[i] + hash) * kPhiPrime;
|
||||
return hash;
|
||||
uint32_t h;
|
||||
const uint32_t kPhiPrime = 0x9e3779b1;
|
||||
const unsigned char *p = (const unsigned char *)buf;
|
||||
for (h = i = 0; i < size; i++) h = (p[i] + h) * kPhiPrime;
|
||||
return h;
|
||||
}
|
||||
|
||||
forceinline uint64_t KnuthMultiplicativeHash(const void *buf, size_t size) {
|
||||
/* TODO(jart): verify w/ primary source */
|
||||
const unsigned char *const p = (const unsigned char *)buf;
|
||||
uint64_t hash = 0, kPhiPrime = 0x9e3779b9925d4c17;
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) hash = (p[i] + hash) * kPhiPrime;
|
||||
return hash;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_KNUTHMULTIPLICATIVEHASH_H_ */
|
||||
|
|
83
libc/str/kx86processormodels.c
Normal file
83
libc/str/kx86processormodels.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/bits/bits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/x86info.h"
|
||||
|
||||
const struct X86ProcessorModel kX86ProcessorModels[] = {
|
||||
/* <SORTED> */
|
||||
{0x060F, X86_MARCH_CORE2, X86_GRADE_CLIENT},
|
||||
{0x0616, X86_MARCH_CORE2, X86_GRADE_MOBILE},
|
||||
{0x0617, X86_MARCH_CORE2, X86_GRADE_SERVER},
|
||||
{0x061A, X86_MARCH_NEHALEM, X86_GRADE_DENSITY},
|
||||
{0x061C, X86_MARCH_BONNELL, X86_GRADE_APPLIANCE},
|
||||
{0x061D, X86_MARCH_CORE2, X86_GRADE_SERVER},
|
||||
{0x061E, X86_MARCH_NEHALEM, X86_GRADE_CLIENT},
|
||||
{0x061F, X86_MARCH_NEHALEM, X86_GRADE_DESKTOP},
|
||||
{0x0625, X86_MARCH_WESTMERE, X86_GRADE_CLIENT},
|
||||
{0x0626, X86_MARCH_BONNELL, X86_GRADE_TABLET},
|
||||
{0x0627, X86_MARCH_SALTWELL, X86_GRADE_TABLET},
|
||||
{0x062A, X86_MARCH_SANDYBRIDGE, X86_GRADE_CLIENT},
|
||||
{0x062C, X86_MARCH_WESTMERE, X86_GRADE_DENSITY},
|
||||
{0x062D, X86_MARCH_SANDYBRIDGE, X86_GRADE_SERVER},
|
||||
{0x062E, X86_MARCH_NEHALEM, X86_GRADE_SERVER},
|
||||
{0x062F, X86_MARCH_WESTMERE, X86_GRADE_SERVER},
|
||||
{0x0635, X86_MARCH_SALTWELL, X86_GRADE_TABLET},
|
||||
{0x0636, X86_MARCH_SALTWELL, X86_GRADE_APPLIANCE},
|
||||
{0x0637, X86_MARCH_SILVERMONT, X86_GRADE_APPLIANCE},
|
||||
{0x063A, X86_MARCH_IVYBRIDGE, X86_GRADE_CLIENT},
|
||||
{0x063C, X86_MARCH_HASWELL, X86_GRADE_CLIENT},
|
||||
{0x063D, X86_MARCH_BROADWELL, X86_GRADE_CLIENT},
|
||||
{0x063E, X86_MARCH_IVYBRIDGE, X86_GRADE_SERVER},
|
||||
{0x063F, X86_MARCH_HASWELL, X86_GRADE_SERVER},
|
||||
{0x0645, X86_MARCH_HASWELL, X86_GRADE_MOBILE},
|
||||
{0x0646, X86_MARCH_HASWELL, X86_GRADE_DESKTOP},
|
||||
{0x0647, X86_MARCH_BROADWELL, X86_GRADE_DESKTOP},
|
||||
{0x064A, X86_MARCH_SILVERMONT, X86_GRADE_TABLET},
|
||||
{0x064C, X86_MARCH_AIRMONT, X86_GRADE_APPLIANCE},
|
||||
{0x064D, X86_MARCH_SILVERMONT, X86_GRADE_DENSITY},
|
||||
{0x064E, X86_MARCH_SKYLAKE, X86_GRADE_MOBILE},
|
||||
{0x064F, X86_MARCH_BROADWELL, X86_GRADE_SERVER},
|
||||
{0x0655, X86_MARCH_SKYLAKE, X86_GRADE_SERVER},
|
||||
{0x0656, X86_MARCH_BROADWELL, X86_GRADE_DENSITY},
|
||||
{0x0657, X86_MARCH_KNIGHTSLANDING, X86_GRADE_SCIENCE},
|
||||
{0x065A, X86_MARCH_AIRMONT, X86_GRADE_TABLET},
|
||||
{0x065C, X86_MARCH_GOLDMONT, X86_GRADE_APPLIANCE},
|
||||
{0x065E, X86_MARCH_SKYLAKE, X86_GRADE_CLIENT},
|
||||
{0x065F, X86_MARCH_GOLDMONT, X86_GRADE_DENSITY},
|
||||
{0x0666, X86_MARCH_CANNONLAKE, X86_GRADE_MOBILE},
|
||||
{0x066A, X86_MARCH_ICELAKE, X86_GRADE_SERVER},
|
||||
{0x066C, X86_MARCH_ICELAKE, X86_GRADE_DENSITY},
|
||||
{0x0675, X86_MARCH_AIRMONT, X86_GRADE_APPLIANCE},
|
||||
{0x067A, X86_MARCH_GOLDMONTPLUS, X86_GRADE_APPLIANCE},
|
||||
{0x067D, X86_MARCH_ICELAKE, X86_GRADE_CLIENT},
|
||||
{0x067E, X86_MARCH_ICELAKE, X86_GRADE_MOBILE},
|
||||
{0x0685, X86_MARCH_KNIGHTSMILL, X86_GRADE_SCIENCE},
|
||||
{0x0686, X86_MARCH_TREMONT, X86_GRADE_APPLIANCE},
|
||||
{0x068C, X86_MARCH_TIGERLAKE, X86_GRADE_MOBILE},
|
||||
{0x068D, X86_MARCH_TIGERLAKE, X86_GRADE_CLIENT},
|
||||
{0x068E, X86_MARCH_KABYLAKE, X86_GRADE_MOBILE},
|
||||
{0x0696, X86_MARCH_TREMONT, X86_GRADE_APPLIANCE},
|
||||
{0x069D, X86_MARCH_ICELAKE, X86_GRADE_SCIENCE},
|
||||
{0x069E, X86_MARCH_KABYLAKE, X86_GRADE_CLIENT},
|
||||
/* </SORTED> */
|
||||
};
|
||||
|
||||
const size_t kX86ProcessorModelCount = ARRAYLEN(kX86ProcessorModels);
|
34
libc/str/lz4check.c
Normal file
34
libc/str/lz4check.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/kompressor.h"
|
||||
#include "libc/nexgen32e/lz4.h"
|
||||
|
||||
const unsigned char *lz4check(const void *data) {
|
||||
const unsigned char *frame = data;
|
||||
if (LZ4_MAGIC(frame) == LZ4_MAGICNUMBER && LZ4_FRAME_VERSION(frame) == 1 &&
|
||||
LZ4_FRAME_BLOCKINDEPENDENCE(frame) == true &&
|
||||
LZ4_FRAME_BLOCKCONTENTSIZEFLAG(frame) == true &&
|
||||
LZ4_FRAME_RESERVED1(frame) == 0 && LZ4_FRAME_RESERVED2(frame) == 0 &&
|
||||
LZ4_FRAME_RESERVED3(frame) == 0) {
|
||||
return frame;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
61
libc/str/lz4cpy.initabi.c
Normal file
61
libc/str/lz4cpy.initabi.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/intrin/repmovsb.h"
|
||||
#include "libc/nexgen32e/kompressor.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Decompresses LZ4 block.
|
||||
*
|
||||
* This is a 103 byte implementation of the LZ4 algorithm. Please note
|
||||
* LZ4 files are comprised of multiple frames, which may be decoded
|
||||
* together using the wrapper function lz4decode().
|
||||
*
|
||||
* @see rldecode() for a 16-byte decompressor
|
||||
*/
|
||||
textstartup void *lz4cpy(void *dest, const void *blockdata, size_t blocksize) {
|
||||
unsigned char *op, *ip, *ipe, *match;
|
||||
unsigned token, length, fifteen, offset, matchlen;
|
||||
for (op = dest, ip = blockdata, ipe = ip + blocksize;;) {
|
||||
token = *ip++;
|
||||
length = token >> 4;
|
||||
fifteen = pushpop(15);
|
||||
if (length == fifteen) {
|
||||
do {
|
||||
length += *ip;
|
||||
} while (*ip++ == 255);
|
||||
}
|
||||
repmovsb(&op, &ip, length);
|
||||
if (ip >= ipe) break;
|
||||
offset = read16le(ip);
|
||||
matchlen = token & fifteen;
|
||||
ip += 2;
|
||||
if (matchlen == fifteen) {
|
||||
do {
|
||||
matchlen += *ip;
|
||||
} while (*ip++ == 255);
|
||||
}
|
||||
match = op - offset;
|
||||
repmovsb(&op, &match, (matchlen += 4));
|
||||
}
|
||||
return op;
|
||||
}
|
50
libc/str/lz4decode.c
Normal file
50
libc/str/lz4decode.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/kompressor.h"
|
||||
#include "libc/nexgen32e/lz4.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Decompresses LZ4 file.
|
||||
*
|
||||
* We assume (1) the file is mmap()'d or was copied into into memory
|
||||
* beforehand; and (2) folks handling untrustworthy data shall place
|
||||
* 64kb of guard pages on the ends of each buffer, see mapanon(). We
|
||||
* don't intend to support XXHASH; we recommend folks needing checks
|
||||
* against data corruption consider crc32c(), or gzip since it's the
|
||||
* best at file recovery. Dictionaries are supported; by convention,
|
||||
* they are passed in the ≤64kb bytes preceding src.
|
||||
*
|
||||
* @return pointer to end of decoded data, similar to mempcpy()
|
||||
* @see mapanon(), lz4check()
|
||||
*/
|
||||
void *lz4decode(void *dest, const void *src) {
|
||||
const unsigned char *frame, *block;
|
||||
frame = (const unsigned char *)src;
|
||||
for (block = frame + LZ4_FRAME_HEADERSIZE(frame); !LZ4_BLOCK_ISEOF(block);
|
||||
block += LZ4_BLOCK_SIZE(frame, block)) {
|
||||
if (LZ4_BLOCK_ISCOMPRESSED(block)) {
|
||||
dest = lz4cpy(dest, LZ4_BLOCK_DATA(block), LZ4_BLOCK_DATASIZE(block));
|
||||
} else {
|
||||
dest = mempcpy(dest, LZ4_BLOCK_DATA(block), LZ4_BLOCK_DATASIZE(block));
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
28
libc/str/memset16.c
Normal file
28
libc/str/memset16.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/bits/bigword.h"
|
||||
#include "libc/str/str.h"
|
||||
#define wmemset memset16
|
||||
#define T unsigned short
|
||||
#define N (BIGWORD / sizeof(T))
|
||||
#include "libc/nexgen32e/wmemset.inc"
|
||||
#undef wmemset
|
||||
#undef T
|
||||
#undef N
|
|
@ -31,7 +31,7 @@ static void sha256_transform(uint32_t state[hasatleast 8],
|
|||
size_t i;
|
||||
uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64];
|
||||
for (i = 0; i < 16; ++i, data += 4) {
|
||||
m[i] = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
}
|
||||
for (; i < 64; ++i) {
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
|
|
|
@ -25,5 +25,10 @@
|
|||
* @param prefix is also NUL-terminated
|
||||
*/
|
||||
bool(startswith)(const char *s, const char *prefix) {
|
||||
return strncmp(s, prefix, strlen(prefix)) == 0;
|
||||
if (s == prefix) return true;
|
||||
for (;;) {
|
||||
if (!*prefix) return true;
|
||||
if (!*s) return false;
|
||||
if (*s++ != *prefix++) return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,16 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies string, returning pointer to where copying ended.
|
||||
*
|
||||
* @see strcpy(), mempcpy()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *stpcpy(char *dst, const char *src) {
|
||||
return (char *)mempcpy(dst, src, strlen(src) + 1) - 1;
|
||||
dst = memccpy(dst, src, '\0', SIZE_MAX);
|
||||
return dst - 1;
|
||||
}
|
||||
|
|
172
libc/str/str.h
172
libc/str/str.h
|
@ -14,7 +14,7 @@ extern const uint8_t kToLower[256];
|
|||
extern const uint8_t kToUpper[256];
|
||||
extern const uint16_t kToLower16[256];
|
||||
extern const uint8_t kBase36[256];
|
||||
extern const char16_t kCp437[256]; /** IBM Code Page 437 */
|
||||
extern const char16_t kCp437[256];
|
||||
|
||||
int isascii(int);
|
||||
int isspace(int);
|
||||
|
@ -68,8 +68,8 @@ void *isnotplaintext(const void *, size_t) nothrow nocallback nosideeffect;
|
|||
#define UTF16_MOAR 0b1101100000000000 /* 0xD800..0xDBFF */
|
||||
#define UTF16_CONT 0b1101110000000000 /* 0xDC00..0xDBFF */
|
||||
|
||||
unsigned getutf16(const char16_t *p, wint_t *wc);
|
||||
int pututf16(char16_t *s, size_t size, wint_t wc, bool awesome);
|
||||
unsigned getutf16(const char16_t *, wint_t *);
|
||||
int pututf16(char16_t *, size_t, wint_t, bool);
|
||||
int iswalnum(wint_t);
|
||||
int iswalpha(wint_t);
|
||||
int iswblank(wint_t);
|
||||
|
@ -105,6 +105,7 @@ void *memchr(const void *, int, size_t) strlenesque;
|
|||
char *strchrnul(const char *, int) strlenesque returnsnonnull;
|
||||
void *rawmemchr(const void *, int) strlenesque returnsnonnull;
|
||||
void bzero(void *, size_t) paramsnonnull() libcesque;
|
||||
void explicit_bzero(void *, size_t) paramsnonnull() libcesque;
|
||||
size_t strlen16(const char16_t *) strlenesque;
|
||||
size_t strnlen16(const char16_t *, size_t) strlenesque;
|
||||
size_t strnlen16_s(const char16_t *, size_t);
|
||||
|
@ -165,7 +166,6 @@ char *strcpy(char *, const char *) memcpyesque;
|
|||
char16_t *strcpy16(char16_t *, const char16_t *) memcpyesque;
|
||||
char *strncat(char *, const char *, size_t) memcpyesque;
|
||||
char *strncpy(char *, const char *, size_t) memcpyesque;
|
||||
char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||
char *strtok(char *, const char *) paramsnonnull((2)) libcesque;
|
||||
char *strtok_r(char *, const char *, char **) paramsnonnull((2, 3));
|
||||
uint16_t *strcpyzbw(uint16_t *, const char *) memcpyesque;
|
||||
|
@ -179,7 +179,6 @@ bool endswith16(const char16_t *, const char16_t *) strlenesque;
|
|||
bool wcsendswith(const wchar_t *, const wchar_t *) strlenesque;
|
||||
const char *indexdoublenulstring(const char *, unsigned) strlenesque;
|
||||
int getkvlin(const char *, const char *const[]);
|
||||
void crc32init(uint32_t[hasatleast 256], uint32_t);
|
||||
wchar_t *wmemset(wchar_t *, wchar_t, size_t) memcpyesque;
|
||||
char16_t *memset16(char16_t *, char16_t, size_t) memcpyesque;
|
||||
compatfn wchar_t *wmemcpy(wchar_t *, const wchar_t *, size_t) memcpyesque;
|
||||
|
@ -190,28 +189,14 @@ char *tinystrstr(const char *, const char *) strlenesque;
|
|||
char16_t *tinystrstr16(const char16_t *, const char16_t *) strlenesque;
|
||||
void *tinymemmem(const void *, size_t, const void *, size_t) strlenesque;
|
||||
|
||||
void *memtolower(void *p, size_t n);
|
||||
char *strntolower(char *s, size_t n);
|
||||
char *strtolower(char *s) paramsnonnull();
|
||||
char *strntoupper(char *s, size_t n);
|
||||
char *strtoupper(char *s) paramsnonnull();
|
||||
char *chomp(char *line);
|
||||
char16_t *chomp16(char16_t *line);
|
||||
wchar_t *wchomp(wchar_t *line);
|
||||
|
||||
/* gcc -Werror=stringop-truncation misunderstands strncpy() api */
|
||||
#define strncpy(DEST, SRC, N) _strncpy(DEST, SRC, N)
|
||||
|
||||
#define explicit_bzero(STR, BYTES) \
|
||||
do { \
|
||||
void *Str; \
|
||||
size_t Bytes; \
|
||||
asm volatile("call\texplicit_bzero" \
|
||||
: "=D"(Str), "=S"(Bytes) \
|
||||
: "0"(STR), "1"(BYTES) \
|
||||
: "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", \
|
||||
"cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); \
|
||||
} while (0)
|
||||
void *memtolower(void *, size_t);
|
||||
char *strntolower(char *, size_t);
|
||||
char *strtolower(char *) paramsnonnull();
|
||||
char *strntoupper(char *, size_t);
|
||||
char *strtoupper(char *) paramsnonnull();
|
||||
char *chomp(char *);
|
||||
char16_t *chomp16(char16_t *);
|
||||
wchar_t *wchomp(wchar_t *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » multibyte ─╬─│┼
|
||||
|
@ -246,8 +231,8 @@ size_t strclen16(const char16_t *) nosideeffect;
|
|||
size_t strnclen16(const char16_t *, size_t) nosideeffect;
|
||||
|
||||
typedef unsigned wctype_t;
|
||||
wctype_t wctype(const char *name) strlenesque;
|
||||
int iswctype(wint_t c, wctype_t type) pureconst;
|
||||
wctype_t wctype(const char *) strlenesque;
|
||||
int iswctype(wint_t, wctype_t) pureconst;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » hashing ─╬─│┼
|
||||
|
@ -262,9 +247,6 @@ struct Sha256Ctx {
|
|||
uint32_t state[8];
|
||||
};
|
||||
|
||||
uint32_t crc32_z(uint32_t, const void *, size_t);
|
||||
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t) paramsnonnull();
|
||||
|
||||
void sha256_init(struct Sha256Ctx *);
|
||||
void sha256_update(struct Sha256Ctx *, const uint8_t *, size_t);
|
||||
void sha256_final(struct Sha256Ctx *, uint8_t *);
|
||||
|
@ -307,13 +289,6 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
: strstr16, default \
|
||||
: strstr)(haystack, needle)
|
||||
|
||||
#define strchr(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcschr, char16_t \
|
||||
: strchr16, default \
|
||||
: (isconstant(s) && isconstant(c) ? __builtin_strchr : _strchr))(s, \
|
||||
c)
|
||||
|
||||
#define strrchr(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsrchr, char16_t \
|
||||
|
@ -419,10 +394,28 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
extern int (*const __memcmp)(const void *, const void *, size_t);
|
||||
#define memcmp(a, b, n) __memcmp(a, b, n)
|
||||
|
||||
/* gcc -Werror=stringop-truncation misunderstands strncpy() api */
|
||||
char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||
#define strncpy(DEST, SRC, N) _strncpy(DEST, SRC, N)
|
||||
|
||||
#define explicit_bzero(STR, BYTES) \
|
||||
do { \
|
||||
void *Str; \
|
||||
size_t Bytes; \
|
||||
asm volatile("call\texplicit_bzero" \
|
||||
: "=D"(Str), "=S"(Bytes) \
|
||||
: "0"(STR), "1"(BYTES) \
|
||||
: "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", \
|
||||
"cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); \
|
||||
} while (0)
|
||||
|
||||
#ifdef UNBLOAT_STDARG
|
||||
#define __STR_XMM_CLOBBER
|
||||
#else
|
||||
#define __STR_XMM_CLOBBER "xmm3",
|
||||
#define __STR_XMM_CLOBBER "xmm3", "xmm4",
|
||||
#endif
|
||||
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
|
@ -437,7 +430,7 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
|
||||
#define memcpy(DEST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DEST, SRC, SIZE) \
|
||||
: __memcpy("_memcpy", DEST, SRC, SIZE))
|
||||
: __memcpy("MemCpy", DEST, SRC, SIZE))
|
||||
|
||||
#define memset(DEST, BYTE, SIZE) \
|
||||
(__memset_isgoodsize(SIZE) ? __builtin_memset(DEST, BYTE, SIZE) \
|
||||
|
@ -445,7 +438,8 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
|
||||
#if defined(__STDC_HOSTED__) && (defined(__SSE2__) || defined(UNBLOAT_STDARG))
|
||||
|
||||
#define memmove(DEST, SRC, SIZE) __memcpy("_memmove", (DEST), (SRC), (SIZE))
|
||||
#define memmove(DEST, SRC, SIZE) __memcpy("MemMove", (DEST), (SRC), (SIZE))
|
||||
|
||||
#define __memcpy(FN, DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *DeSt = (DEST); \
|
||||
|
@ -457,16 +451,18 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
: __STR_XMM_CLOBBER "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
|
||||
#define mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
size_t SIze = (SIZE); \
|
||||
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
|
||||
})
|
||||
|
||||
#define __memset(DEST, BYTE, SIZE) \
|
||||
({ \
|
||||
void *DeSt = (DEST); \
|
||||
size_t SiZe = (SIZE); \
|
||||
asm("call\t_memset" \
|
||||
asm("call\tMemSet" \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \
|
||||
: __STR_XMM_CLOBBER "cc"); \
|
||||
|
@ -476,6 +472,7 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
#else /* hosted/sse2/unbloat */
|
||||
|
||||
#define memmove(DEST, SRC, SIZE) __memcpy((DEST), (SRC), (SIZE))
|
||||
|
||||
#define mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *Rdi, *Dest = (DEST); \
|
||||
|
@ -488,6 +485,7 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
: "cc"); \
|
||||
Rdi; \
|
||||
})
|
||||
|
||||
#define __memcpy(FN, DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *Rdi, *Dest = (DEST); \
|
||||
|
@ -500,6 +498,7 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
: "cc"); \
|
||||
Dest; \
|
||||
})
|
||||
|
||||
#define __memset(DEST, BYTE, SIZE) \
|
||||
({ \
|
||||
void *Rdi, *Dest = (DEST); \
|
||||
|
@ -532,8 +531,8 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
#define pututf16(BUF, SIZE, CH, AWESOME) __pututf16(BUF, SIZE, CH, AWESOME)
|
||||
#define getutf16(BUF, CHPTR) __getutf16(BUF, CHPTR)
|
||||
size_t _strlen(const char *s) asm("strlen") strlenesque;
|
||||
char *_strchr(const char *, int) asm("strchr") strlenesque;
|
||||
void *_memchr(const void *, int, size_t) asm("memchr") strlenesque;
|
||||
|
||||
forceinline int __pututf16(char16_t *s, size_t size, wint_t wc,
|
||||
bool32 awesome) {
|
||||
if (size >= 1 && (0x00 <= wc && wc <= 0xD7FF)) {
|
||||
|
@ -548,98 +547,25 @@ forceinline int __pututf16(char16_t *s, size_t size, wint_t wc,
|
|||
}
|
||||
int ax;
|
||||
asm("call\tpututf16"
|
||||
: "=a"(ax), "=m"(*(char16_t(*)[size])s)
|
||||
: "=a"(ax), "=m"(*(char(*)[size])s)
|
||||
: "D"(s), "S"(size), "d"(wc)
|
||||
: "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
forceinline unsigned __getutf16(const char16_t *s, wint_t *wc) {
|
||||
if ((0x00 <= s[0] && s[0] <= 0xD7FF)) {
|
||||
*wc = s[0];
|
||||
return 1;
|
||||
}
|
||||
unsigned ax;
|
||||
asm("call\tgetutf16" : "=a"(ax), "=m"(*wc) : "D"(s), "S"(wc), "m"(*s) : "cc");
|
||||
asm("call\tgetutf16"
|
||||
: "=a"(ax), "=m"(*wc)
|
||||
: "D"(s), "S"(wc), "m"(*s), "m"(*(char(*)[4])s)
|
||||
: "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
/*
|
||||
* GCC has builtins for these, that only do things for literals. They
|
||||
* also cause the compiler to whine in a kafkaesque way when flags like
|
||||
* -Werror=shadow and -Werror=implicit-function-declaration are passed.
|
||||
*/
|
||||
#define isascii(c) isascii_(c)
|
||||
#define isspace(c) isspace_(c)
|
||||
#define isalpha(c) isalpha_(c)
|
||||
#define isdigit(c) isdigit_(c)
|
||||
#define isalnum(c) isalnum_(c)
|
||||
#define isxdigit(c) isxdigit_(c)
|
||||
#define isprint(c) isprint_(c)
|
||||
#define islower(c) islower_(c)
|
||||
#define isupper(c) isupper_(c)
|
||||
#define isblank(c) isblank_(c)
|
||||
#define iscntrl(c) iscntrl_(c)
|
||||
#define isgraph(c) isgraph_(c)
|
||||
#define tolower(c) tolower_(c)
|
||||
#define ispunct(c) ispunct_(c)
|
||||
#define toupper(c) toupper_(c)
|
||||
#define hextoint(c) hextoint_(c)
|
||||
#define DECLARE_CTYPE(NAME, EXPR) \
|
||||
pureconst forceinline nodebuginfo int NAME(int i) { \
|
||||
unsigned char c = (unsigned char)i; \
|
||||
return (EXPR); \
|
||||
}
|
||||
DECLARE_CTYPE(isascii_, 0 <= c && c <= 0x7f)
|
||||
DECLARE_CTYPE(isspace_, kCtype[c] & 0x01)
|
||||
DECLARE_CTYPE(isalpha_, kCtype[c] & 0x02)
|
||||
DECLARE_CTYPE(isdigit_, '0' <= c && c <= '9')
|
||||
DECLARE_CTYPE(isalnum_, kCtype[c] & 0x06)
|
||||
DECLARE_CTYPE(isxdigit_, kCtype[c] & 0x08)
|
||||
DECLARE_CTYPE(isprint_, kCtype[c] & 0x10)
|
||||
DECLARE_CTYPE(islower_, 'a' <= c && c <= 'z')
|
||||
DECLARE_CTYPE(isupper_, 'A' <= c && c <= 'Z')
|
||||
DECLARE_CTYPE(isblank_, kCtype[c] & 0x80)
|
||||
DECLARE_CTYPE(iscntrl_, !isprint_(c))
|
||||
DECLARE_CTYPE(isgraph_, isprint_(c) && (c) != ' ')
|
||||
DECLARE_CTYPE(tolower_, kToLower[c])
|
||||
DECLARE_CTYPE(ispunct_, isprint(c) && !(kCtype[c] & 0x07))
|
||||
DECLARE_CTYPE(toupper_, kToUpper[c])
|
||||
DECLARE_CTYPE(hextoint_, (c + 9 * (1 & (SAR(c, 6)))) & 0xf)
|
||||
#undef DECLARE_CTYPE
|
||||
#define iswalnum(c) iswalnum_(c)
|
||||
#define iswalpha(c) iswalpha_(c)
|
||||
#define iswblank(c) iswblank_(c)
|
||||
#define iswcntrl(c) iswcntrl_(c)
|
||||
#define iswdigit(c) iswdigit_(c)
|
||||
#define iswgraph(c) iswgraph_(c)
|
||||
#define iswlower(c) iswlower_(c)
|
||||
#define iswspace(c) iswspace_(c)
|
||||
#define iswupper(c) iswupper_(c)
|
||||
#define iswxdigit(c) iswxdigit_(c)
|
||||
#define iswpunct(c) iswpunct_(c)
|
||||
#define iswprint(c) iswprint_(c)
|
||||
#define towlower(c) towlower_(c)
|
||||
#define towupper(c) towupper_(c)
|
||||
#define DECLARE_WCTYPE(R, NAME, T, EXPR) \
|
||||
forceinline nodebuginfo R NAME(T c) { \
|
||||
return EXPR; \
|
||||
}
|
||||
DECLARE_WCTYPE(int, iswalnum_, wint_t, isascii(c) ? isalnum(c) : c)
|
||||
DECLARE_WCTYPE(int, iswalpha_, wint_t, isascii(c) ? isalpha(c) : c)
|
||||
DECLARE_WCTYPE(int, iswblank_, wint_t, isascii(c) ? isblank(c) : c)
|
||||
DECLARE_WCTYPE(int, iswcntrl_, wint_t, isascii(c) ? iscntrl(c) : c)
|
||||
DECLARE_WCTYPE(int, iswdigit_, wint_t, isascii(c) ? isdigit(c) : c)
|
||||
DECLARE_WCTYPE(int, iswgraph_, wint_t, isascii(c) ? isgraph(c) : c)
|
||||
DECLARE_WCTYPE(int, iswlower_, wint_t, isascii(c) ? islower(c) : c)
|
||||
DECLARE_WCTYPE(int, iswspace_, wint_t, isascii(c) ? isspace(c) : c)
|
||||
DECLARE_WCTYPE(int, iswupper_, wint_t, isascii(c) ? isupper(c) : c)
|
||||
DECLARE_WCTYPE(int, iswxdigit_, wint_t, isascii(c) ? isxdigit(c) : c)
|
||||
DECLARE_WCTYPE(int, iswpunct_, wint_t, !isascii(c) || ispunct(c))
|
||||
DECLARE_WCTYPE(int, iswprint_, wint_t, !isascii(c) || isprint(c))
|
||||
DECLARE_WCTYPE(unsigned, towlower_, unsigned, isascii(c) ? tolower(c) : c)
|
||||
DECLARE_WCTYPE(unsigned, towupper_, unsigned, isascii(c) ? toupper(c) : c)
|
||||
#undef DECLARE_WCTYPE
|
||||
|
||||
#endif /* __GNUC__ && !__STRICT_ANSI__ */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
36
libc/str/strcspn.c
Normal file
36
libc/str/strcspn.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns prefix length, consisting of chars not in reject.
|
||||
* a.k.a. Return index of first byte that's in charset.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t(strcspn)(const char *s, const char *reject) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacter(s[i], reject)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
28
libc/str/strcspn16.c
Normal file
28
libc/str/strcspn16.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef strcspn
|
||||
#define char char16_t
|
||||
#define HasCharacter HasCharacter16
|
||||
#define strcspn strcspn16
|
||||
|
||||
#include "libc/str/strcspn.c"
|
41
libc/str/strpbrk.c
Normal file
41
libc/str/strpbrk.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns pointer to first byte matching any in accept, or NULL.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *(strpbrk)(const char *s, const char *accept) {
|
||||
size_t i;
|
||||
if (accept[0]) {
|
||||
if (!accept[1]) {
|
||||
return strchr(s, accept[0]);
|
||||
} else {
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacter(s[i], accept)) {
|
||||
return (/*unconst*/ char *)&s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
29
libc/str/strpbrk16.c
Normal file
29
libc/str/strpbrk16.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.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"
|
|
@ -23,14 +23,20 @@
|
|||
|
||||
static const char kSig[4] = "SIG";
|
||||
static const char kUnknown[8] = "UNKNOWN";
|
||||
|
||||
alignas(1) static const char kStrSignals[][8] = {
|
||||
"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS",
|
||||
"FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM",
|
||||
"STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG",
|
||||
"XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "SYS"};
|
||||
"XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "SYS",
|
||||
};
|
||||
|
||||
static char g_strsignal[4 + 8];
|
||||
|
||||
/**
|
||||
* Returns name associated with signal code.
|
||||
* @see sigaction()
|
||||
*/
|
||||
char *strsignal(int sig) {
|
||||
if (0 <= sig && (unsigned)sig < ARRAYLEN(kStrSignals)) {
|
||||
memcpy(g_strsignal, kSig, 4);
|
||||
|
|
38
libc/str/strspn.c
Normal file
38
libc/str/strspn.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns prefix length, consisting of chars in accept.
|
||||
*
|
||||
* @param accept is nul-terminated character set
|
||||
* @see strcspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t(strspn)(const char *s, const char *accept) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (!HasCharacter(s[i], accept)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
28
libc/str/strspn16.c
Normal file
28
libc/str/strspn16.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef strspn
|
||||
#define char char16_t
|
||||
#define HasCharacter HasCharacter16
|
||||
#define strspn strspn16
|
||||
|
||||
#include "libc/str/strspn.c"
|
|
@ -30,16 +30,17 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strtok_r(char *s, const char *sep, char **state) {
|
||||
size_t leadingseps, tokenlen;
|
||||
if (!s) {
|
||||
s = *state;
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
size_t leadingseps = strspn(s, sep);
|
||||
leadingseps = strspn(s, sep);
|
||||
s += leadingseps;
|
||||
if (*s) {
|
||||
size_t tokenlen = strcspn(s, sep);
|
||||
tokenlen = strcspn(s, sep);
|
||||
if (s[tokenlen]) {
|
||||
s[tokenlen] = '\0';
|
||||
*state = &s[tokenlen + 1];
|
||||
|
|
31
libc/str/tinymemccpy.c
Normal file
31
libc/str/tinymemccpy.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/str/str.h"
|
||||
#include "libc/str/tinymemccpy.h"
|
||||
|
||||
void *tinymemccpy(void *dst, const void *src, int termchar, size_t limit) {
|
||||
size_t i;
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
for (termchar &= 0xff, d = dst, s = src, i = 0; i < limit; ++i) {
|
||||
if ((d[i] = s[i]) == termchar) return d + i + 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
10
libc/str/tinymemccpy.h
Normal file
10
libc/str/tinymemccpy.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYMEMCCPY_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYMEMCCPY_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void *tinymemccpy(void *, const void *, int, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYMEMCCPY_H_ */
|
|
@ -1,12 +1,13 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline void *tinymemmemi(const void *haystk, size_t haystksize,
|
||||
const void *needle, size_t needlesize) {
|
||||
const char *p = haystk;
|
||||
const char *pe = p + haystksize;
|
||||
const char *p = (const char *)haystk;
|
||||
const char *pe = (const char *)haystk + haystksize;
|
||||
while (p < pe) {
|
||||
size_t i = 0;
|
||||
++p;
|
||||
|
@ -21,4 +22,5 @@ forceinline void *tinymemmemi(const void *haystk, size_t haystksize,
|
|||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* !ANSI */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYMEMMEM_H_ */
|
||||
|
|
|
@ -8,11 +8,11 @@ int tpdecode(const char *, wint_t *) paramsnonnull((1)) libcesque;
|
|||
#ifndef __STRICT_ANSI__
|
||||
#define tpdecode(S, OUT) __tpdecode(S, OUT)
|
||||
forceinline int __tpdecode(const char *s, wint_t *out) {
|
||||
int ax;
|
||||
if (0 <= *s && *s <= 0x7f) {
|
||||
*out = *s;
|
||||
return 1;
|
||||
}
|
||||
int ax;
|
||||
asm("call\ttpdecode"
|
||||
: "=a"(ax), "=m"(*(char(*)[6])s)
|
||||
: "D"(s), "S"(out)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_STR_TPDECODECB_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TPDECODECB_H_
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
|
@ -28,17 +29,16 @@
|
|||
*/
|
||||
forceinline int tpdecodecb(wint_t *out, int first,
|
||||
int get(void *arg, uint32_t i), void *arg) {
|
||||
uint32_t wc, cb, need, msb, i = 1;
|
||||
if ((wc = first) == -1) return -1;
|
||||
while ((wc & 0b11000000) == 0b10000000) {
|
||||
uint32_t wc, cb, need, msb, j, i = 1;
|
||||
if (unlikely((wc = first) == -1)) return -1;
|
||||
while (unlikely((wc & 0b11000000) == 0b10000000)) {
|
||||
if ((wc = get(arg, i++)) == -1) return -1;
|
||||
}
|
||||
if ((wc & 0b10000000) == 0b10000000) {
|
||||
asm("bsr\t%1,%0" : "=r"(msb) : "rm"(~wc & 0xff) : "cc");
|
||||
if (!msb) msb = 1;
|
||||
if (unlikely(!(0 <= wc && wc <= 0x7F))) {
|
||||
msb = wc < 252 ? bsr(~wc & 0xff) : 1;
|
||||
need = 7 - msb;
|
||||
wc &= ((1u << msb) - 1) | 0b00000011;
|
||||
for (uint32_t j = 1; j < need; ++j) {
|
||||
for (j = 1; j < need; ++j) {
|
||||
if ((cb = get(arg, i++)) == -1) return -1;
|
||||
if ((cb & 0b11000000) == 0b10000000) {
|
||||
wc = wc << 6 | (cb & 0b00111111);
|
||||
|
@ -48,7 +48,7 @@ forceinline int tpdecodecb(wint_t *out, int first,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (out) *out = (wint_t)wc;
|
||||
if (likely(out)) *out = (wint_t)wc;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,19 @@ COSMOPOLITAN_C_START_
|
|||
uint64_t tpenc(int32_t) pureconst;
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
long Buf; \
|
||||
int32_t Code = (CODE); \
|
||||
if (0 <= Code && Code <= 127) { \
|
||||
Buf = Code; \
|
||||
} else { \
|
||||
asm("call\ttpenc" : "=a"(Buf), "+D"(Code) : /* inputs */ : "cc"); \
|
||||
} \
|
||||
Buf; \
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
long Buf; \
|
||||
int32_t Code = (CODE); \
|
||||
if (0 <= Code && Code <= 127) { \
|
||||
Buf = Code; \
|
||||
} else { \
|
||||
asm("call\ttpenc" \
|
||||
: "=a"(Buf), "+D"(Code) \
|
||||
: /* inputs */ \
|
||||
: "cc"); \
|
||||
} \
|
||||
Buf; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_VARINT_H_
|
||||
#define COSMOPOLITAN_LIBC_VARINT_H_
|
||||
#include "libc/limits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define unzigzag(x) ((x >> 1) ^ -(x & 1))
|
||||
#define zigzag(x) _Generic((x), int32_t : zigzag32, default : zigzag64)(x)
|
||||
|
||||
forceinline int32_t zigzag32(int32_t x) {
|
||||
return (int64_t)((uint64_t)x << 1) ^ (x >> 31);
|
||||
}
|
||||
|
||||
forceinline int64_t zigzag64(int64_t x) {
|
||||
return (int64_t)((uint64_t)x << 1) ^ (x >> 63);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies variable-length integer to buffer.
|
||||
*
|
||||
* @param p needs 10+ bytes for 64-bit and 5+ for 32-bit
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last written byte
|
||||
* @see writesint() which has more efficient encoding for signed numbers
|
||||
*/
|
||||
forceinline uint8_t *writevint(uint8_t *p, uint64_t x) {
|
||||
do {
|
||||
*p++ = (uint8_t)(x | 0x80);
|
||||
x >>= 7;
|
||||
} while (x > 0);
|
||||
p[-1] &= 0x7f;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies variable-length signed integer to buffer.
|
||||
*
|
||||
* @param p needs 10+ bytes for 64-bit and 5+ for 32-bit
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last written byte
|
||||
*/
|
||||
forceinline uint8_t *writesint(uint8_t *p, int64_t x) {
|
||||
return writevint(p, zigzag(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable-length integer from buffer.
|
||||
*
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last read byte or -1ul on error
|
||||
*/
|
||||
forceinline uint8_t *readvint(uint8_t *p, uint8_t *pe, uint64_t *res) {
|
||||
uint8_t b;
|
||||
uint64_t x, o;
|
||||
x = 0;
|
||||
b = 0;
|
||||
while (p < pe) {
|
||||
o = *p++;
|
||||
x |= ((uint64_t)o & 0x7f) << b;
|
||||
if (!(o & 0x80)) {
|
||||
*res = x;
|
||||
return p;
|
||||
}
|
||||
if ((b += 7) > 64) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (uint8_t *)-1ul;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable-length zig-zagged integer from buffer.
|
||||
*
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last read byte or -1ul on error
|
||||
*/
|
||||
forceinline uint8_t *readsint(uint8_t *p, uint8_t *pe, int64_t *res) {
|
||||
uint64_t u;
|
||||
if ((p = readvint(p, pe, &u)) != (uint8_t *)-1ul) {
|
||||
*res = unzigzag((int64_t)u);
|
||||
return p;
|
||||
} else {
|
||||
return (uint8_t *)-1ul;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_VARINT_H_ */
|
28
libc/str/wcscspn.c
Normal file
28
libc/str/wcscspn.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef strcspn
|
||||
#define char wchar_t
|
||||
#define HasCharacter HasCharacterWide
|
||||
#define strcspn wcscspn
|
||||
|
||||
#include "libc/str/strcspn.c"
|
29
libc/str/wcspbrk.c
Normal file
29
libc/str/wcspbrk.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.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"
|
28
libc/str/wcsspn.c
Normal file
28
libc/str/wcsspn.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/nexgen32e/hascharacter.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#undef strspn
|
||||
#define char wchar_t
|
||||
#define HasCharacter HasCharacterWide
|
||||
#define strspn wcsspn
|
||||
|
||||
#include "libc/str/strspn.c"
|
26
libc/str/wmemset.c
Normal file
26
libc/str/wmemset.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 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/bits/bigword.h"
|
||||
#include "libc/str/str.h"
|
||||
#define T wchar_t
|
||||
#define N (BIGWORD / sizeof(T))
|
||||
#include "libc/nexgen32e/wmemset.inc"
|
||||
#undef T
|
||||
#undef N
|
Loading…
Add table
Add a link
Reference in a new issue