Add minor improvements and cleanup
parent
9e3e985ae5
commit
feed0d2b0e
1
Makefile
1
Makefile
|
@ -117,7 +117,6 @@ include libc/ohmyplus/ohmyplus.mk # │
|
|||
include libc/zipos/zipos.mk # │
|
||||
include third_party/dtoa/dtoa.mk # │
|
||||
include libc/time/time.mk # │
|
||||
include libc/escape/escape.mk # │
|
||||
include libc/alg/alg.mk # │
|
||||
include libc/calls/hefty/hefty.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
/* Long Mode Paging
|
||||
@see Intel Manual V.3A §4.1 §4.5
|
||||
IsValid (ignored on CR3) V┐
|
||||
┌Block Instr. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
||||
┌XD:No Inst. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
||||
│ Permit User-Mode Access - u┐││
|
||||
│ Page-level Write-Through - PWT┐│││
|
||||
│ Page-level Cache Disable - PCD┐││││
|
||||
|
@ -147,7 +147,6 @@
|
|||
││ ││ ││├──────────────────┐ │ ││ ││││││││││
|
||||
││ ││ │││ Phys. Addr. 1GB │ │ ││ ││││││││││
|
||||
││ ││ │││ │ │ ││ ││││││││││
|
||||
0b00000000000011111111111111111111111111111111111111000000000000
|
||||
6666555555555544444444443333333333222222222211111111110000000000
|
||||
3210987654321098765432109876543210987654321098765432109876543210*/
|
||||
#define PAGE_V /* */ 0b000000001
|
||||
|
|
|
@ -15,22 +15,22 @@
|
|||
# remove comments
|
||||
s/[ \t][ \t]*#.*//
|
||||
|
||||
#s/leave\(q\|\)/leavew/
|
||||
#s/call\(q\|\)/callw/
|
||||
#s/ret\(q\|\)/retw/
|
||||
#s/popq\t%rbp/pop\t%bp/
|
||||
#s/pushq\t%rbp/push\t%bp/
|
||||
#s/pushq\t\(.*\)/sub $6,%sp\n\tpush \1/
|
||||
#s/popq\t\(.*\)/pop \1\n\tadd $6,%sp/
|
||||
|
||||
# preserve hardcoded stack offsets
|
||||
# bloats code size 13%
|
||||
s/leave\(q\|\)/leavew\n\tadd\t$6,%sp/
|
||||
s/call\(q\|\)\t/sub\t$6,%sp\n\tcallw\t/
|
||||
s/ret\(q\|\)/retw\t$6/
|
||||
s/leave\(q\|\)/leavew/
|
||||
s/call\(q\|\)/callw/
|
||||
s/ret\(q\|\)/retw/
|
||||
s/popq\t%rbp/pop\t%bp/
|
||||
s/pushq\t%rbp/push\t%bp/
|
||||
s/pushq\t\(.*\)/sub\t$6,%sp\n\tpush\t\1/
|
||||
s/popq\t\(.*\)/pop\t\1\n\tadd\t$6,%sp/
|
||||
|
||||
# # preserve hardcoded stack offsets
|
||||
# # bloats code size 13%
|
||||
# s/leave\(q\|\)/leavew\n\tadd\t$6,%sp/
|
||||
# s/call\(q\|\)\t/sub\t$6,%sp\n\tcallw\t/
|
||||
# s/ret\(q\|\)/retw\t$6/
|
||||
# s/pushq\t\(.*\)/sub\t$6,%sp\n\tpush\t\1/
|
||||
# s/popq\t\(.*\)/pop\t\1\n\tadd\t$6,%sp/
|
||||
|
||||
s/, /,/g
|
||||
|
||||
# 32-bitify
|
||||
|
|
|
@ -27,24 +27,21 @@ struct Itoa8 kItoa8;
|
|||
static textstartup void itoa8_init(void) {
|
||||
int i;
|
||||
uint8_t z;
|
||||
char p[4];
|
||||
uint32_t w;
|
||||
for (i = 0; i < 256; ++i) {
|
||||
memset(p, 0, sizeof(p));
|
||||
if (i < 10) {
|
||||
z = 1;
|
||||
p[0] = '0' + i;
|
||||
w = '0' + i;
|
||||
} else if (i < 100) {
|
||||
z = 2;
|
||||
p[0] = '0' + i / 10;
|
||||
p[1] = '0' + i % 10;
|
||||
w = ('0' + i / 10) | ('0' + i % 10) << 8;
|
||||
} else {
|
||||
z = 3;
|
||||
p[0] = '0' + i / 100;
|
||||
p[1] = '0' + i % 100 / 10;
|
||||
p[2] = '0' + i % 100 % 10;
|
||||
w = ('0' + i / 100) | ('0' + i % 100 / 10) << 8 |
|
||||
('0' + i % 100 % 10) << 16;
|
||||
}
|
||||
kItoa8.size[i] = z;
|
||||
memcpy(&kItoa8.data[i], p, sizeof(p));
|
||||
kItoa8.data[i] = w;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -240,9 +240,10 @@ static const struct Pick kPicksMixBlock[32] = {
|
|||
{TL, TR, 9}, /* ▓ */
|
||||
};
|
||||
|
||||
static unsigned short bdist(struct TtyRgb a, struct TtyRgb b, struct TtyRgb c,
|
||||
struct TtyRgb d, struct TtyRgb w, struct TtyRgb x,
|
||||
struct TtyRgb y, struct TtyRgb z) {
|
||||
static unsigned short GetBlockDist(struct TtyRgb a, struct TtyRgb b,
|
||||
struct TtyRgb c, struct TtyRgb d,
|
||||
struct TtyRgb w, struct TtyRgb x,
|
||||
struct TtyRgb y, struct TtyRgb z) {
|
||||
unsigned short dist;
|
||||
dist = 0;
|
||||
dist += ABS(a.r - w.r);
|
||||
|
@ -260,7 +261,7 @@ static unsigned short bdist(struct TtyRgb a, struct TtyRgb b, struct TtyRgb c,
|
|||
return dist;
|
||||
}
|
||||
|
||||
static uint16_t *mixblock(uint16_t *p, struct TtyRgb ttl, struct TtyRgb ttr,
|
||||
static uint16_t *MixBlock(uint16_t *p, struct TtyRgb ttl, struct TtyRgb ttr,
|
||||
struct TtyRgb tbl, struct TtyRgb tbr,
|
||||
struct TtyRgb qtl, struct TtyRgb qtr,
|
||||
struct TtyRgb qbl, struct TtyRgb qbr) {
|
||||
|
@ -465,15 +466,15 @@ static uint16_t *mixblock(uint16_t *p, struct TtyRgb ttl, struct TtyRgb ttr,
|
|||
return p;
|
||||
}
|
||||
|
||||
static struct TtyRgb getquant(struct TtyRgb rgb) {
|
||||
static struct TtyRgb GetQuant(struct TtyRgb rgb) {
|
||||
return g_ansi2rgb_[rgb.xt];
|
||||
}
|
||||
|
||||
static uint16_t *pickunicode(uint16_t *p, struct TtyRgb tl, struct TtyRgb tr,
|
||||
static uint16_t *PickUnicode(uint16_t *p, struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br,
|
||||
struct TtyRgb tl2, struct TtyRgb tr2,
|
||||
struct TtyRgb bl2, struct TtyRgb br2) {
|
||||
#define PICK(A, B, C, D) *p++ = bdist(tl, tr, bl, br, A, B, C, D)
|
||||
#define PICK(A, B, C, D) *p++ = GetBlockDist(tl, tr, bl, br, A, B, C, D)
|
||||
PICK(bl2, bl2, bl2, bl2); /* k=0 bg=bl fg=NULL */
|
||||
PICK(bl2, bl2, bl2, br2); /* ▗ k=4 bg=bl fg=br */
|
||||
PICK(bl2, bl2, bl2, tl2); /* ▗ k=4 bg=bl fg=tl */
|
||||
|
@ -566,11 +567,11 @@ static uint16_t *pickunicode(uint16_t *p, struct TtyRgb tl, struct TtyRgb tr,
|
|||
return p;
|
||||
}
|
||||
|
||||
static uint16_t *pickcp437(uint16_t *p, struct TtyRgb tl, struct TtyRgb tr,
|
||||
static uint16_t *PickCp437(uint16_t *p, struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br,
|
||||
struct TtyRgb tl2, struct TtyRgb tr2,
|
||||
struct TtyRgb bl2, struct TtyRgb br2) {
|
||||
#define PICK(A, B, C, D) *p++ = bdist(tl, tr, bl, br, A, B, C, D)
|
||||
#define PICK(A, B, C, D) *p++ = GetBlockDist(tl, tr, bl, br, A, B, C, D)
|
||||
PICK(bl2, bl2, bl2, bl2); /* k=0 bg=bl fg=NULL */
|
||||
PICK(bl2, bl2, br2, br2); /* ▄ k=1 bg=bl fg=br */
|
||||
PICK(bl2, bl2, tl2, tl2); /* ▄ k=1 bg=bl fg=tl */
|
||||
|
@ -603,30 +604,30 @@ static uint16_t *pickcp437(uint16_t *p, struct TtyRgb tl, struct TtyRgb tr,
|
|||
return p;
|
||||
}
|
||||
|
||||
static struct Pick pickblock_unicode_ansi(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
struct TtyRgb tl2 = getquant(tl);
|
||||
struct TtyRgb tr2 = getquant(tr);
|
||||
struct TtyRgb bl2 = getquant(bl);
|
||||
struct TtyRgb br2 = getquant(br);
|
||||
static struct Pick PickBlockUnicodeAnsi(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
struct TtyRgb tl2 = GetQuant(tl);
|
||||
struct TtyRgb tr2 = GetQuant(tr);
|
||||
struct TtyRgb bl2 = GetQuant(bl);
|
||||
struct TtyRgb br2 = GetQuant(br);
|
||||
unsigned i, p1, p2;
|
||||
uint16_t picks1[96] aligned(32);
|
||||
uint16_t picks2[32] aligned(32);
|
||||
memset(picks1, 0x79, sizeof(picks1));
|
||||
memset(picks2, 0x79, sizeof(picks2));
|
||||
pickunicode(picks1, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
mixblock(picks2, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
PickUnicode(picks1, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
MixBlock(picks2, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
p1 = windex(picks1, 96);
|
||||
p2 = windex(picks2, 32);
|
||||
return picks1[p1] <= picks2[p2] ? kPicksUnicode[p1] : kPicksMixBlock[p2];
|
||||
}
|
||||
|
||||
static struct Pick pickblock_unicode_true(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
static struct Pick PickBlockUnicodeTrue(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
unsigned i;
|
||||
uint16_t picks[96] aligned(32);
|
||||
memset(picks, 0x79, sizeof(picks));
|
||||
pickunicode(picks, tl, tr, bl, br, tl, tr, bl, br);
|
||||
PickUnicode(picks, tl, tr, bl, br, tl, tr, bl, br);
|
||||
i = windex(picks, 96);
|
||||
if (i >= 88) {
|
||||
unsigned j;
|
||||
|
@ -640,39 +641,39 @@ static struct Pick pickblock_unicode_true(struct TtyRgb tl, struct TtyRgb tr,
|
|||
return kPicksUnicode[i];
|
||||
}
|
||||
|
||||
static struct Pick pickblock_cp437_ansi(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
struct TtyRgb tl2 = getquant(tl);
|
||||
struct TtyRgb tr2 = getquant(tr);
|
||||
struct TtyRgb bl2 = getquant(bl);
|
||||
struct TtyRgb br2 = getquant(br);
|
||||
static struct Pick PickBlockCp437Ansi(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
struct TtyRgb tl2 = GetQuant(tl);
|
||||
struct TtyRgb tr2 = GetQuant(tr);
|
||||
struct TtyRgb bl2 = GetQuant(bl);
|
||||
struct TtyRgb br2 = GetQuant(br);
|
||||
unsigned i, p1, p2;
|
||||
uint16_t picks1[32] aligned(32);
|
||||
uint16_t picks2[32] aligned(32);
|
||||
memset(picks1, 0x79, sizeof(picks1));
|
||||
memset(picks2, 0x79, sizeof(picks2));
|
||||
pickcp437(picks1, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
mixblock(picks2, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
PickCp437(picks1, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
MixBlock(picks2, tl, tr, bl, br, tl2, tr2, bl2, br2);
|
||||
p1 = windex(picks1, 32);
|
||||
p2 = windex(picks2, 32);
|
||||
return picks1[p1] <= picks2[p2] ? kPicksCp437[p1] : kPicksMixBlock[p2];
|
||||
}
|
||||
|
||||
static struct Pick pickblock_cp437_true(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
static struct Pick PickBlockCp437True(struct TtyRgb tl, struct TtyRgb tr,
|
||||
struct TtyRgb bl, struct TtyRgb br) {
|
||||
unsigned i;
|
||||
uint16_t picks[32] aligned(32);
|
||||
memset(picks, 0x79, sizeof(picks));
|
||||
pickcp437(picks, tl, tr, bl, br, tl, tr, bl, br);
|
||||
PickCp437(picks, tl, tr, bl, br, tl, tr, bl, br);
|
||||
return kPicksCp437[windex(picks, 32)];
|
||||
}
|
||||
|
||||
static char *copyglyph(char *v, struct Glyph glyph) {
|
||||
static char *CopyGlyph(char *v, struct Glyph glyph) {
|
||||
memcpy(v, &glyph, 4);
|
||||
return v + glyph.len;
|
||||
}
|
||||
|
||||
static char *copyblock(char *v, const struct TtyRgb chunk[hasatleast 4],
|
||||
static char *CopyBlock(char *v, const struct TtyRgb chunk[hasatleast 4],
|
||||
struct Pick pick, struct TtyRgb *bg, struct TtyRgb *fg,
|
||||
struct Glyph *glyph) {
|
||||
unsigned i;
|
||||
|
@ -721,16 +722,16 @@ static char *copyblock(char *v, const struct TtyRgb chunk[hasatleast 4],
|
|||
} else if (!ttyeq(*bg, chunk[pick.bg])) {
|
||||
v = setbg(v, (*bg = chunk[pick.bg]));
|
||||
}
|
||||
return copyglyph(v, (*glyph = kGlyphs[i][pick.k]));
|
||||
return CopyGlyph(v, (*glyph = kGlyphs[i][pick.k]));
|
||||
}
|
||||
|
||||
static bool chunkeq(struct TtyRgb c[hasatleast 4],
|
||||
static bool ChunkEq(struct TtyRgb c[hasatleast 4],
|
||||
struct TtyRgb c2[hasatleast 4]) {
|
||||
return ttyeq(c[TL], c[TR]) && ttyeq(c[BL], c[BR]) && ttyeq(c2[TL], c2[TR]) &&
|
||||
ttyeq(c2[BL], c2[BR]);
|
||||
}
|
||||
|
||||
static struct TtyRgb *copychunk(struct TtyRgb chunk[hasatleast 4],
|
||||
static struct TtyRgb *CopyChunk(struct TtyRgb chunk[hasatleast 4],
|
||||
const struct TtyRgb *c, size_t n) {
|
||||
chunk[TL] = c[0 + 0];
|
||||
chunk[TR] = c[0 + 1];
|
||||
|
@ -739,7 +740,7 @@ static struct TtyRgb *copychunk(struct TtyRgb chunk[hasatleast 4],
|
|||
return chunk;
|
||||
}
|
||||
|
||||
static noinline char *copyrun(char *v, size_t n,
|
||||
static noinline char *CopyRun(char *v, size_t n,
|
||||
struct TtyRgb lastchunk[hasatleast 4],
|
||||
const struct TtyRgb **c, size_t *x,
|
||||
struct TtyRgb *bg, struct TtyRgb *fg,
|
||||
|
@ -752,12 +753,12 @@ static noinline char *copyrun(char *v, size_t n,
|
|||
*glyph = kGlyphs[0][0];
|
||||
}
|
||||
do {
|
||||
v = copyglyph(v, *glyph);
|
||||
v = CopyGlyph(v, *glyph);
|
||||
*x += 2;
|
||||
*c += 2;
|
||||
if (*x >= n) break;
|
||||
copychunk(chunk, *c, n);
|
||||
} while (chunkeq(chunk, lastchunk));
|
||||
CopyChunk(chunk, *c, n);
|
||||
} while (ChunkEq(chunk, lastchunk));
|
||||
*x -= 2;
|
||||
*c -= 2;
|
||||
return v;
|
||||
|
@ -776,21 +777,21 @@ char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t n,
|
|||
for (y = 0; y < yn; y += 2, c += n) {
|
||||
if (y) *v++ = '\r', *v++ = '\n';
|
||||
for (x = 0; x < n; x += 2, c += 2) {
|
||||
copychunk(chun, c, n);
|
||||
CopyChunk(chun, c, n);
|
||||
if (ttyquant()->alg == kTtyQuantTrue) {
|
||||
if (ttyquant()->blocks == kTtyBlocksCp437) {
|
||||
p = pickblock_cp437_true(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
p = PickBlockCp437True(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
} else {
|
||||
p = pickblock_unicode_true(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
p = PickBlockUnicodeTrue(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
}
|
||||
} else {
|
||||
if (ttyquant()->blocks == kTtyBlocksCp437) {
|
||||
p = pickblock_cp437_ansi(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
p = PickBlockCp437Ansi(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
} else {
|
||||
p = pickblock_unicode_ansi(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
p = PickBlockUnicodeAnsi(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
}
|
||||
}
|
||||
v = copyblock(v, chun, p, &bg, &fg, &glyph);
|
||||
v = CopyBlock(v, chun, p, &bg, &fg, &glyph);
|
||||
memcpy(lastchunk, chun, sizeof(chun));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,5 @@ textstartup int ttyraw(enum TtyRawFlags flags) {
|
|||
} else {
|
||||
rc = ttyraw_disable();
|
||||
}
|
||||
cancolor();
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "libc/conv/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -26,7 +26,7 @@ int main(int argc, char *argv[]) {
|
|||
*
|
||||
* 1. gc() automates calling free() on return.
|
||||
* 2. xasprintf("foo %s", "bar") is our version of "foo %s" % ("bar")
|
||||
* 3. Demonstrates correct escaping for bourne shell cf. xaescapeshq()
|
||||
* 3. Demonstrates correct escaping for bourne shell
|
||||
*/
|
||||
if (!fileexists(kProgram)) {
|
||||
system(gc(xasprintf("%s '%s'", "make -j4",
|
||||
|
|
|
@ -620,12 +620,12 @@
|
|||
#define octtobin(c) ((c) - '0')
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||
|
||||
/* #define TRACE(param) */
|
||||
#define TRACE(param) \
|
||||
do { \
|
||||
printf("TRACE: "); \
|
||||
printf param; \
|
||||
} while (0)
|
||||
#define TRACE(param)
|
||||
/* #define TRACE(param) \ */
|
||||
/* do { \ */
|
||||
/* printf("TRACE: "); \ */
|
||||
/* printf param; \ */
|
||||
/* } while (0) */
|
||||
|
||||
#define TRACEV(param)
|
||||
#define digit_val(c) ((c) - '0')
|
||||
|
@ -634,8 +634,6 @@
|
|||
#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
|
||||
#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
|
||||
#define is_special(c) ((is_type + SYNBASE)[(signed char)(c)] & (ISSPECL | ISDIGIT))
|
||||
/* #define likely(x) __builtin_expect(!!(x), 1) */
|
||||
/* #define unlikely(x) __builtin_expect(!!(x), 0) */
|
||||
|
||||
#define uninitialized_var(x) x = x /* suppress uninitialized warning w/o code */
|
||||
|
||||
|
@ -643,9 +641,7 @@
|
|||
* Shell variables.
|
||||
*/
|
||||
#define vifs varinit[0]
|
||||
#define vmail (&vifs)[1]
|
||||
#define vmpath (&vmail)[1]
|
||||
#define vpath (&vmpath)[1]
|
||||
#define vpath (&vifs)[1]
|
||||
#define vps1 (&vpath)[1]
|
||||
#define vps2 (&vps1)[1]
|
||||
#define vps4 (&vps2)[1]
|
||||
|
@ -1497,46 +1493,48 @@ enum token {
|
|||
|
||||
enum token_types { UNOP, BINOP, BUNOP, BBINOP, PAREN };
|
||||
|
||||
static struct t_op const ops[] = {{"-r", FILRD, UNOP},
|
||||
{"-w", FILWR, UNOP},
|
||||
{"-x", FILEX, UNOP},
|
||||
{"-e", FILEXIST, UNOP},
|
||||
{"-f", FILREG, UNOP},
|
||||
{"-d", FILDIR, UNOP},
|
||||
{"-c", FILCDEV, UNOP},
|
||||
{"-b", FILBDEV, UNOP},
|
||||
{"-p", FILFIFO, UNOP},
|
||||
{"-u", FILSUID, UNOP},
|
||||
{"-g", FILSGID, UNOP},
|
||||
{"-k", FILSTCK, UNOP},
|
||||
{"-s", FILGZ, UNOP},
|
||||
{"-t", FILTT, UNOP},
|
||||
{"-z", STREZ, UNOP},
|
||||
{"-n", STRNZ, UNOP},
|
||||
{"-h", FILSYM, UNOP}, /* for backwards compat */
|
||||
{"-O", FILUID, UNOP},
|
||||
{"-G", FILGID, UNOP},
|
||||
{"-L", FILSYM, UNOP},
|
||||
{"-S", FILSOCK, UNOP},
|
||||
{"=", STREQ, BINOP},
|
||||
{"!=", STRNE, BINOP},
|
||||
{"<", STRLT, BINOP},
|
||||
{">", STRGT, BINOP},
|
||||
{"-eq", INTEQ, BINOP},
|
||||
{"-ne", INTNE, BINOP},
|
||||
{"-ge", INTGE, BINOP},
|
||||
{"-gt", INTGT, BINOP},
|
||||
{"-le", INTLE, BINOP},
|
||||
{"-lt", INTLT, BINOP},
|
||||
{"-nt", FILNT, BINOP},
|
||||
{"-ot", FILOT, BINOP},
|
||||
{"-ef", FILEQ, BINOP},
|
||||
{"!", UNOT, BUNOP},
|
||||
{"-a", BAND, BBINOP},
|
||||
{"-o", BOR, BBINOP},
|
||||
{"(", LPAREN, PAREN},
|
||||
{")", RPAREN, PAREN},
|
||||
{0, 0, 0}};
|
||||
static struct t_op const ops[] = {
|
||||
{"-r", FILRD, UNOP},
|
||||
{"-w", FILWR, UNOP},
|
||||
{"-x", FILEX, UNOP},
|
||||
{"-e", FILEXIST, UNOP},
|
||||
{"-f", FILREG, UNOP},
|
||||
{"-d", FILDIR, UNOP},
|
||||
{"-c", FILCDEV, UNOP},
|
||||
{"-b", FILBDEV, UNOP},
|
||||
{"-p", FILFIFO, UNOP},
|
||||
{"-u", FILSUID, UNOP},
|
||||
{"-g", FILSGID, UNOP},
|
||||
{"-k", FILSTCK, UNOP},
|
||||
{"-s", FILGZ, UNOP},
|
||||
{"-t", FILTT, UNOP},
|
||||
{"-z", STREZ, UNOP},
|
||||
{"-n", STRNZ, UNOP},
|
||||
{"-h", FILSYM, UNOP}, /* for backwards compat */
|
||||
{"-O", FILUID, UNOP},
|
||||
{"-G", FILGID, UNOP},
|
||||
{"-L", FILSYM, UNOP},
|
||||
{"-S", FILSOCK, UNOP},
|
||||
{"=", STREQ, BINOP},
|
||||
{"!=", STRNE, BINOP},
|
||||
{"<", STRLT, BINOP},
|
||||
{">", STRGT, BINOP},
|
||||
{"-eq", INTEQ, BINOP},
|
||||
{"-ne", INTNE, BINOP},
|
||||
{"-ge", INTGE, BINOP},
|
||||
{"-gt", INTGT, BINOP},
|
||||
{"-le", INTLE, BINOP},
|
||||
{"-lt", INTLT, BINOP},
|
||||
{"-nt", FILNT, BINOP},
|
||||
{"-ot", FILOT, BINOP},
|
||||
{"-ef", FILEQ, BINOP},
|
||||
{"!", UNOT, BUNOP},
|
||||
{"-a", BAND, BBINOP},
|
||||
{"-o", BOR, BBINOP},
|
||||
{"(", LPAREN, PAREN},
|
||||
{")", RPAREN, PAREN},
|
||||
{0, 0, 0},
|
||||
};
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § the unbourne shell » text ─╬─│┼
|
||||
|
@ -3644,7 +3642,7 @@ static int evalcommand(union node *cmd, int flags) {
|
|||
}
|
||||
/* Now locate the command. */
|
||||
if (cmdentry.cmdtype != CMDBUILTIN || !(cmdentry.u.cmd->flags & BUILTIN_REGULAR)) {
|
||||
path = unlikely(path != NULL) ? path : pathval();
|
||||
path = unlikely(path != NULL) ? path : pathval(); /* wut */
|
||||
find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
|
||||
}
|
||||
jp = NULL;
|
||||
|
@ -4213,21 +4211,21 @@ static void hashcd(void) {
|
|||
* Called with interrupts off.
|
||||
*/
|
||||
static void changepath(const char *newval) {
|
||||
const char *new;
|
||||
int idx;
|
||||
int bltin;
|
||||
new = newval;
|
||||
const char *neu;
|
||||
neu = newval;
|
||||
idx = 0;
|
||||
bltin = -1;
|
||||
for (;;) {
|
||||
if (*new == '%' && prefix(new + 1, "builtin")) {
|
||||
if (*neu == '%' && prefix(neu + 1, "builtin")) {
|
||||
bltin = idx;
|
||||
break;
|
||||
}
|
||||
new = strchr(new, ':');
|
||||
if (!new) break;
|
||||
neu = strchr(neu, ':');
|
||||
if (!neu) break;
|
||||
idx++;
|
||||
new ++;
|
||||
neu++;
|
||||
}
|
||||
builtinloc = bltin;
|
||||
clearcmdentry();
|
||||
|
@ -9603,6 +9601,9 @@ static char *conv_escape(char *str, int *conv_ch) {
|
|||
case 'f':
|
||||
value = '\f';
|
||||
break; /* form-feed */
|
||||
case 'e':
|
||||
value = '\e';
|
||||
break; /* escape */
|
||||
case 'n':
|
||||
value = '\n';
|
||||
break; /* newline */
|
||||
|
@ -10787,6 +10788,7 @@ static int exitcmd(int argc, char **argv) {
|
|||
*/
|
||||
int main(int argc, char **argv) {
|
||||
showcrashreports();
|
||||
unsetenv("PS1");
|
||||
char *shinit;
|
||||
volatile int state;
|
||||
struct jmploc jmploc;
|
||||
|
|
|
@ -111,7 +111,7 @@ int fchmod(int, uint32_t) nothrow;
|
|||
int fchmodat(int, const char *, uint32_t, uint32_t);
|
||||
int fchown(int, uint32_t, uint32_t);
|
||||
int fchownat(int, const char *, uint32_t, uint32_t, uint32_t);
|
||||
int fcntl();
|
||||
int fcntl(int, int, ...);
|
||||
int fdatasync(int);
|
||||
int filecmp(const char *, const char *);
|
||||
int flock(int, int);
|
||||
|
@ -189,7 +189,7 @@ int uname(struct utsname *);
|
|||
int unlink(const char *);
|
||||
int unlink_s(const char **);
|
||||
int unlinkat(int, const char *, int);
|
||||
int vfork(void);
|
||||
int vfork(void) returnstwice;
|
||||
int wait(int *);
|
||||
int wait3(int *, int, struct rusage *);
|
||||
int wait4(int, int *, int, struct rusage *);
|
||||
|
@ -242,7 +242,7 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
|
|||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
void _init_onntconsoleevent(void);
|
||||
void _init_onwincrash(void);
|
||||
void _init_wincrash(void);
|
||||
|
||||
#define __SIGACTION(FN, SIG, ...) \
|
||||
({ \
|
||||
|
@ -260,14 +260,14 @@ void _init_onwincrash(void);
|
|||
case SIGSEGV: \
|
||||
case SIGABRT: \
|
||||
case SIGFPE: \
|
||||
YOINK(_init_onwincrash); \
|
||||
YOINK(_init_wincrash); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
YOINK(_init_onwincrash); \
|
||||
YOINK(_init_wincrash); \
|
||||
} \
|
||||
} \
|
||||
(FN)(SIG, __VA_ARGS__); \
|
||||
|
|
|
@ -24,16 +24,17 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int fcntl$nt(int fd, int cmd, unsigned arg) {
|
||||
uint32_t flags;
|
||||
if (!isfdkind(fd, kFdFile)) return ebadf();
|
||||
switch (cmd) {
|
||||
case F_GETFD:
|
||||
return GetHandleInformation(g_fds.p[fd].handle, &arg) ? (arg ^ FD_CLOEXEC)
|
||||
: -1;
|
||||
if (!GetHandleInformation(g_fds.p[fd].handle, &flags)) return -1;
|
||||
arg = (flags & FD_CLOEXEC) ^ FD_CLOEXEC;
|
||||
return arg;
|
||||
case F_SETFD:
|
||||
return SetHandleInformation(g_fds.p[fd].handle, FD_CLOEXEC,
|
||||
arg ^ FD_CLOEXEC)
|
||||
? 0
|
||||
: -1;
|
||||
arg ^= FD_CLOEXEC;
|
||||
if (!SetHandleInformation(g_fds.p[fd].handle, FD_CLOEXEC, arg)) return -1;
|
||||
return 0;
|
||||
default:
|
||||
return 0; /* TODO(jart): Implement me. */
|
||||
}
|
||||
|
|
|
@ -31,7 +31,12 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int fcntl(int fd, int cmd, int arg) {
|
||||
int fcntl(int fd, int cmd, ...) {
|
||||
va_list va;
|
||||
unsigned arg;
|
||||
va_start(va, cmd);
|
||||
arg = va_arg(va, unsigned);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return fcntl$sysv(fd, cmd, arg);
|
||||
} else {
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/*-*- 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/calls/internal.h"
|
||||
#include "libc/calls/ntmagicpaths.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
textwindows const char *(fixntmagicpath)(const char *path, unsigned flags) {
|
||||
const struct NtMagicPaths *mp = &kNtMagicPaths;
|
||||
asm("" : "+r"(mp));
|
||||
if (path[0] != '/') return path;
|
||||
if (tinystrcmp(path, mp->devtty) == 0) {
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
return mp->conin;
|
||||
} else if ((flags & O_ACCMODE) == O_WRONLY) {
|
||||
return mp->conout;
|
||||
}
|
||||
}
|
||||
if (tinystrcmp(path, mp->devnull) == 0) return mp->nul;
|
||||
if (tinystrcmp(path, mp->devstdin) == 0) return mp->conin;
|
||||
if (tinystrcmp(path, mp->devstdout) == 0) return mp->conout;
|
||||
return path;
|
||||
}
|
|
@ -261,15 +261,11 @@ void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
|
|||
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
||||
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
||||
bool32 onntconsoleevent$nt(u32) hidden;
|
||||
void onntalarm(void *, uint32_t, uint32_t) hidden;
|
||||
void __winalarm(void *, uint32_t, uint32_t) hidden;
|
||||
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
|
||||
i64 ntreturn(u32);
|
||||
i64 winerr(void) nocallback privileged;
|
||||
|
||||
const char *__fixntmagicpath(const char *, unsigned) paramsnonnull() hidden;
|
||||
int __mkntpath(const char *, unsigned, char16_t[hasatleast PATH_MAX - 16])
|
||||
paramsnonnull() hidden;
|
||||
|
||||
#define mkntpath(PATH, PATH16) mkntpath2(PATH, -1u, PATH16)
|
||||
#define mkntpath2(PATH, FLAGS, PATH16) \
|
||||
({ \
|
||||
|
@ -281,16 +277,6 @@ int __mkntpath(const char *, unsigned, char16_t[hasatleast PATH_MAX - 16])
|
|||
Count; \
|
||||
})
|
||||
|
||||
#define fixntmagicpath(PATH, FLAGS) \
|
||||
({ \
|
||||
const char *Path2; \
|
||||
asm("call\tfixntmagicpath" \
|
||||
: "=a"(Path2) \
|
||||
: "D"(PATH), "S"(FLAGS), "m"((PATH)[0]) \
|
||||
: "cc"); \
|
||||
Path2; \
|
||||
})
|
||||
|
||||
#undef sigset
|
||||
#undef i32
|
||||
#undef i64
|
||||
|
|
|
@ -17,15 +17,31 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/calls/ntmagicpaths.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpdecode.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows static const char *FixNtMagicPath(const char *path,
|
||||
unsigned flags) {
|
||||
const struct NtMagicPaths *mp = &kNtMagicPaths;
|
||||
asm("" : "+r"(mp));
|
||||
if (path[0] != '/') return path;
|
||||
if (tinystrcmp(path, mp->devtty) == 0) {
|
||||
if ((flags & O_ACCMODE) == O_RDONLY) {
|
||||
return mp->conin;
|
||||
} else if ((flags & O_ACCMODE) == O_WRONLY) {
|
||||
return mp->conout;
|
||||
}
|
||||
}
|
||||
if (tinystrcmp(path, mp->devnull) == 0) return mp->nul;
|
||||
if (tinystrcmp(path, mp->devstdin) == 0) return mp->conin;
|
||||
if (tinystrcmp(path, mp->devstdout) == 0) return mp->conout;
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies path for Windows NT.
|
||||
*
|
||||
|
@ -33,13 +49,13 @@
|
|||
* forward-slashes with backslashes; and (3) remapping several
|
||||
* well-known paths (e.g. /dev/null → NUL) for convenience.
|
||||
*
|
||||
* @param flags is used by open()
|
||||
* @param path16 is shortened so caller can prefix, e.g. \\.\pipe\, and
|
||||
* due to a plethora of special-cases throughout the Win32 API
|
||||
* @param flags is used by open(), see fixntmagicpath2()
|
||||
* @return short count excluding NUL on success, or -1 w/ errno
|
||||
* @error ENAMETOOLONG
|
||||
*/
|
||||
forcealignargpointer textwindows int(mkntpath)(
|
||||
forcealignargpointer textwindows int mkntpath(
|
||||
const char *path, unsigned flags,
|
||||
char16_t path16[hasatleast PATH_MAX - 16]) {
|
||||
/*
|
||||
|
@ -52,7 +68,7 @@ forcealignargpointer textwindows int(mkntpath)(
|
|||
int rc;
|
||||
wint_t wc;
|
||||
size_t i, j;
|
||||
path = fixntmagicpath(path, flags);
|
||||
path = FixNtMagicPath(path, flags);
|
||||
i = 0;
|
||||
j = 0;
|
||||
for (;;) {
|
||||
|
|
|
@ -55,7 +55,7 @@ static struct ItimerNt {
|
|||
static uint32_t ItimerWorker(void *arg) {
|
||||
do {
|
||||
if (!WaitForSingleObject(g_itimernt.ith, -1)) {
|
||||
onntalarm(NULL, 0, 0);
|
||||
__winalarm(NULL, 0, 0);
|
||||
}
|
||||
} while (g_itimernt.ith && g_itimernt.tid == GetCurrentThreadId());
|
||||
return 0;
|
||||
|
|
|
@ -23,5 +23,5 @@
|
|||
|
||||
onntconsoleevent$nt:
|
||||
ezlea onntconsoleevent,ax
|
||||
jmp nt2sysv
|
||||
jmp __nt2sysv
|
||||
.endfn onntconsoleevent$nt,globl,hidden
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
.text.windows
|
||||
.source __FILE__
|
||||
|
||||
onwincrash$nt:
|
||||
ezlea onwincrash,ax
|
||||
jmp nt2sysv
|
||||
.endfn onwincrash$nt,globl
|
||||
__wincrash$nt:
|
||||
ezlea __wincrash,ax
|
||||
jmp __nt2sysv
|
||||
.endfn __wincrash$nt,globl
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
.text.windows
|
||||
.source __FILE__
|
||||
|
||||
onntalarm$nt:
|
||||
ezlea onntalarm,ax
|
||||
jmp nt2sysv
|
||||
.endfn onntalarm$nt,globl,hidden
|
||||
__winalarm$nt:
|
||||
ezlea __winalarm,ax
|
||||
jmp __nt2sysv
|
||||
.endfn __winalarm$nt,globl,hidden
|
|
@ -22,8 +22,8 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
void onntalarm(void *lpArgToCompletionRoutine, uint32_t dwTimerLowValue,
|
||||
uint32_t dwTimerHighValue) {
|
||||
void __winalarm(void *lpArgToCompletionRoutine, uint32_t dwTimerLowValue,
|
||||
uint32_t dwTimerHighValue) {
|
||||
siginfo_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = SIGALRM;
|
|
@ -27,7 +27,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
textwindows unsigned onwincrash(struct NtExceptionPointers *ep) {
|
||||
textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
|
||||
int sig;
|
||||
struct Goodies {
|
||||
ucontext_t ctx;
|
|
@ -20,8 +20,8 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
.init.start 300,_init_onwincrash
|
||||
.init.start 300,_init_wincrash
|
||||
pushpop 1,%rcx
|
||||
ezlea onwincrash$nt,dx
|
||||
ezlea __wincrash$nt,dx
|
||||
ntcall __imp_AddVectoredExceptionHandler
|
||||
.init.end 300,_init_onwincrash,globl,hidden
|
||||
.init.end 300,_init_wincrash,globl,hidden
|
|
@ -54,9 +54,8 @@ _start: test %rdi,%rdi
|
|||
mov %rdi,%rcx # auxv
|
||||
mov %ebx,%edi
|
||||
call _executive
|
||||
9: .endfn _start,weak,hidden
|
||||
|
||||
ud2
|
||||
9: ud2
|
||||
.endfn _start,weak,hidden
|
||||
|
||||
/ Macintosh userspace program entrypoint.
|
||||
/
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
/**
|
||||
* Resolves address for internet name.
|
||||
*
|
||||
* @param node is either an ip string or a utf-8 hostname
|
||||
* @param name is either an ip string or a utf-8 hostname
|
||||
* @param service is the port number as a string
|
||||
* @param hints may be passed to specialize behavior (optional)
|
||||
* @param res receives a pointer that must be freed with freeaddrinfo(),
|
||||
|
|
262
libc/errno.h
262
libc/errno.h
|
@ -6,137 +6,137 @@
|
|||
* @see libc/sysv/consts.sh for numbers
|
||||
*/
|
||||
|
||||
#define EPERM EPERM /* operation not permitted */
|
||||
#define ENOENT ENOENT /* no such file or directory */
|
||||
#define ESRCH ESRCH /* no such process */
|
||||
#define EINTR EINTR /* interrupted system call */
|
||||
#define EIO EIO /* input/output error */
|
||||
#define ENXIO ENXIO /* no such device or address */
|
||||
#define E2BIG E2BIG /* argument list too long */
|
||||
#define ENOEXEC ENOEXEC /* exec format error */
|
||||
#define EBADF EBADF /* bad file descriptor */
|
||||
#define ECHILD ECHILD /* no child processes */
|
||||
#define EAGAIN EAGAIN /* resource temporarily unavailable */
|
||||
#define ENOMEM ENOMEM /* not enough space */
|
||||
#define EACCES EACCES /* permission denied */
|
||||
#define EFAULT EFAULT /* bad address */
|
||||
#define ENOTBLK ENOTBLK /* block device required */
|
||||
#define EBUSY EBUSY /* device or resource busy */
|
||||
#define EEXIST EEXIST /* file exists */
|
||||
#define EXDEV EXDEV /* improper link */
|
||||
#define ENODEV ENODEV /* no such device */
|
||||
#define ENOTDIR ENOTDIR /* not a directory */
|
||||
#define EISDIR EISDIR /* is a directory */
|
||||
#define EINVAL EINVAL /* invalid argument */
|
||||
#define ENFILE ENFILE /* too many open files in system */
|
||||
#define EMFILE EMFILE /* too many open files */
|
||||
#define ENOTTY ENOTTY /* inappropriate I/O control op */
|
||||
#define ETXTBSY ETXTBSY /* text file busy */
|
||||
#define EFBIG EFBIG /* file too large */
|
||||
#define ENOSPC ENOSPC /* no space left on device */
|
||||
#define ESPIPE ESPIPE /* invalid seek */
|
||||
#define EROFS EROFS /* read-only filesystem */
|
||||
#define EMLINK EMLINK /* too many links */
|
||||
#define EPIPE EPIPE /* broken pipe */
|
||||
#define EDOM EDOM /* argument out of function domain */
|
||||
#define ERANGE ERANGE /* result too large */
|
||||
#define EDEADLK EDEADLK /* resource deadlock avoided */
|
||||
#define ENAMETOOLONG ENAMETOOLONG /* filename too long */
|
||||
#define ENOLCK ENOLCK /* no locks available */
|
||||
#define ENOSYS ENOSYS /* system call not implemented */
|
||||
#define ENOTEMPTY ENOTEMPTY /* directory not empty */
|
||||
#define ELOOP ELOOP /* too many levels of symbolic links */
|
||||
#define ENOMSG ENOMSG /* no message of the desired type */
|
||||
#define EIDRM EIDRM /* identifier removed */
|
||||
#define ECHRNG ECHRNG /* channel number out of range */
|
||||
#define EL2NSYNC EL2NSYNC /* level 2 not synchronized */
|
||||
#define EL3HLT EL3HLT /* level 3 halted */
|
||||
#define EL3RST EL3RST /* level 3 halted */
|
||||
#define ELNRNG ELNRNG /* link number out of range */
|
||||
#define EUNATCH EUNATCH /* protocol driver not attached */
|
||||
#define ENOCSI ENOCSI /* no csi structure available */
|
||||
#define EL2HLT EL2HLT /* level 2 halted */
|
||||
#define EBADE EBADE /* invalid exchange */
|
||||
#define EBADR EBADR /* invalid request descriptor */
|
||||
#define EXFULL EXFULL /* exchange full */
|
||||
#define ENOANO ENOANO /* no anode */
|
||||
#define EBADRQC EBADRQC /* invalid request code */
|
||||
#define EBADSLT EBADSLT /* invalid slot */
|
||||
#define ENOSTR ENOSTR /* no string */
|
||||
#define ENODATA ENODATA /* no data */
|
||||
#define ETIME ETIME /* timer expired */
|
||||
#define ENOSR ENOSR /* out of streams resources */
|
||||
#define ENONET ENONET /* no network */
|
||||
#define ENOPKG ENOPKG /* package not installed */
|
||||
#define EREMOTE EREMOTE /* object is remote */
|
||||
#define ENOLINK ENOLINK /* link severed */
|
||||
#define EADV EADV /* todo */
|
||||
#define ESRMNT ESRMNT /* todo */
|
||||
#define ECOMM ECOMM /* communication error on send */
|
||||
#define EPROTO EPROTO /* protocol error */
|
||||
#define EMULTIHOP EMULTIHOP /* multihop attempted */
|
||||
#define EDOTDOT EDOTDOT /* todo */
|
||||
#define EBADMSG EBADMSG /* bad message */
|
||||
#define EOVERFLOW EOVERFLOW /* value too large for type */
|
||||
#define ENOTUNIQ ENOTUNIQ /* name not unique on network */
|
||||
#define EBADFD EBADFD /* fd in bad *state* (cf. EBADF) */
|
||||
#define EREMCHG EREMCHG /* remote address changed */
|
||||
#define ELIBACC ELIBACC /* cannot access dso */
|
||||
#define ELIBBAD ELIBBAD /* corrupted shared library */
|
||||
#define ELIBSCN ELIBSCN /* a.out section corrupted */
|
||||
#define ELIBMAX ELIBMAX /* too many shared libraries */
|
||||
#define ELIBEXEC ELIBEXEC /* cannot exec a dso directly */
|
||||
#define EILSEQ EILSEQ /* invalid wide character */
|
||||
#define ERESTART ERESTART /* please restart syscall */
|
||||
#define ESTRPIPE ESTRPIPE /* streams pipe error */
|
||||
#define EUSERS EUSERS /* too many users */
|
||||
#define ENOTSOCK ENOTSOCK /* not a socket */
|
||||
#define EDESTADDRREQ EDESTADDRREQ /* dest address needed */
|
||||
#define EMSGSIZE EMSGSIZE /* message too long */
|
||||
#define EPROTOTYPE EPROTOTYPE /* protocol wrong for socket */
|
||||
#define ENOPROTOOPT ENOPROTOOPT /* protocol not available */
|
||||
#define EPROTONOSUPPORT EPROTONOSUPPORT /* protocol not supported */
|
||||
#define ESOCKTNOSUPPORT ESOCKTNOSUPPORT /* socket type not supported */
|
||||
#define EOPNOTSUPP EOPNOTSUPP /* operation not supported on socket */
|
||||
#define EPFNOSUPPORT EPFNOSUPPORT /* protocol family not supported */
|
||||
#define EAFNOSUPPORT EAFNOSUPPORT /* address family not supported */
|
||||
#define EADDRINUSE EADDRINUSE /* address already in use */
|
||||
#define EADDRNOTAVAIL EADDRNOTAVAIL /* address not available */
|
||||
#define ENETDOWN ENETDOWN /* network is down */
|
||||
#define ENETUNREACH ENETUNREACH /* network unreachable */
|
||||
#define ENETRESET ENETRESET /* connection aborted by network */
|
||||
#define ECONNABORTED ECONNABORTED /* connection aborted */
|
||||
#define ECONNRESET ECONNRESET /* connection reset */
|
||||
#define ENOBUFS ENOBUFS /* no buffer space available */
|
||||
#define EISCONN EISCONN /* socket is connected */
|
||||
#define ENOTCONN ENOTCONN /* the socket is not connected */
|
||||
#define ESHUTDOWN ESHUTDOWN /* no send after endpoint shutdown */
|
||||
#define ETOOMANYREFS ETOOMANYREFS /* too many refs */
|
||||
#define ETIMEDOUT ETIMEDOUT /* connection timed out */
|
||||
#define ECONNREFUSED ECONNREFUSED /* connection refused */
|
||||
#define EHOSTDOWN EHOSTDOWN /* host is down */
|
||||
#define EHOSTUNREACH EHOSTUNREACH /* host is unreachable */
|
||||
#define EALREADY EALREADY /* connection already in progress */
|
||||
#define EINPROGRESS EINPROGRESS /* operation in progress */
|
||||
#define ESTALE ESTALE /* stale file handle */
|
||||
#define EUCLEAN EUCLEAN /* structure needs cleaning */
|
||||
#define ENOTNAM ENOTNAM /* todo */
|
||||
#define ENAVAIL ENAVAIL /* todo */
|
||||
#define EISNAM EISNAM /* is a named type file */
|
||||
#define EREMOTEIO EREMOTEIO /* remote i/o error */
|
||||
#define EDQUOT EDQUOT /* disk quota exceeded */
|
||||
#define ENOMEDIUM ENOMEDIUM /* no medium found */
|
||||
#define EMEDIUMTYPE EMEDIUMTYPE /* wrong medium type */
|
||||
#define ECANCELED ECANCELED /* operation canceled */
|
||||
#define ENOKEY ENOKEY /* required key not available */
|
||||
#define EKEYEXPIRED EKEYEXPIRED /* key has expired */
|
||||
#define EKEYREVOKED EKEYREVOKED /* key has been revoked */
|
||||
#define EKEYREJECTED EKEYREJECTED /* key was rejected by service */
|
||||
#define EOWNERDEAD EOWNERDEAD /* owner died */
|
||||
#define ENOTRECOVERABLE ENOTRECOVERABLE /* state not recoverable */
|
||||
#define ERFKILL ERFKILL /* can't op b/c RF-kill */
|
||||
#define EHWPOISON EHWPOISON /* mempage has h/w error */
|
||||
#define EWOULDBLOCK EAGAIN /* poll fd and try again */
|
||||
#define EPERM EPERM // operation not permitted
|
||||
#define ENOENT ENOENT // no such file or directory
|
||||
#define ESRCH ESRCH // no such process
|
||||
#define EINTR EINTR // interrupted system call
|
||||
#define EIO EIO // input/output error
|
||||
#define ENXIO ENXIO // no such device or address
|
||||
#define E2BIG E2BIG // argument list too long
|
||||
#define ENOEXEC ENOEXEC // exec format error
|
||||
#define EBADF EBADF // bad file descriptor
|
||||
#define ECHILD ECHILD // no child processes
|
||||
#define EAGAIN EAGAIN // resource temporarily unavailable
|
||||
#define ENOMEM ENOMEM // not enough space
|
||||
#define EACCES EACCES // permission denied
|
||||
#define EFAULT EFAULT // bad address
|
||||
#define ENOTBLK ENOTBLK // block device required
|
||||
#define EBUSY EBUSY // device or resource busy
|
||||
#define EEXIST EEXIST // file exists
|
||||
#define EXDEV EXDEV // improper link
|
||||
#define ENODEV ENODEV // no such device
|
||||
#define ENOTDIR ENOTDIR // not a directory
|
||||
#define EISDIR EISDIR // is a directory
|
||||
#define EINVAL EINVAL // invalid argument
|
||||
#define ENFILE ENFILE // too many open files in system
|
||||
#define EMFILE EMFILE // too many open files
|
||||
#define ENOTTY ENOTTY // inappropriate I/O control op
|
||||
#define ETXTBSY ETXTBSY // text file busy
|
||||
#define EFBIG EFBIG // file too large
|
||||
#define ENOSPC ENOSPC // no space left on device
|
||||
#define ESPIPE ESPIPE // invalid seek
|
||||
#define EROFS EROFS // read-only filesystem
|
||||
#define EMLINK EMLINK // too many links
|
||||
#define EPIPE EPIPE // broken pipe
|
||||
#define EDOM EDOM // argument out of function domain
|
||||
#define ERANGE ERANGE // result too large
|
||||
#define EDEADLK EDEADLK // resource deadlock avoided
|
||||
#define ENAMETOOLONG ENAMETOOLONG // filename too long
|
||||
#define ENOLCK ENOLCK // no locks available
|
||||
#define ENOSYS ENOSYS // system call not implemented
|
||||
#define ENOTEMPTY ENOTEMPTY // directory not empty
|
||||
#define ELOOP ELOOP // too many levels of symbolic links
|
||||
#define ENOMSG ENOMSG // no message of the desired type
|
||||
#define EIDRM EIDRM // identifier removed
|
||||
#define ECHRNG ECHRNG // channel number out of range
|
||||
#define EL2NSYNC EL2NSYNC // level 2 not synchronized
|
||||
#define EL3HLT EL3HLT // level 3 halted
|
||||
#define EL3RST EL3RST // level 3 halted
|
||||
#define ELNRNG ELNRNG // link number out of range
|
||||
#define EUNATCH EUNATCH // protocol driver not attached
|
||||
#define ENOCSI ENOCSI // no csi structure available
|
||||
#define EL2HLT EL2HLT // level 2 halted
|
||||
#define EBADE EBADE // invalid exchange
|
||||
#define EBADR EBADR // invalid request descriptor
|
||||
#define EXFULL EXFULL // exchange full
|
||||
#define ENOANO ENOANO // no anode
|
||||
#define EBADRQC EBADRQC // invalid request code
|
||||
#define EBADSLT EBADSLT // invalid slot
|
||||
#define ENOSTR ENOSTR // no string
|
||||
#define ENODATA ENODATA // no data
|
||||
#define ETIME ETIME // timer expired
|
||||
#define ENOSR ENOSR // out of streams resources
|
||||
#define ENONET ENONET // no network
|
||||
#define ENOPKG ENOPKG // package not installed
|
||||
#define EREMOTE EREMOTE // object is remote
|
||||
#define ENOLINK ENOLINK // link severed
|
||||
#define EADV EADV // todo
|
||||
#define ESRMNT ESRMNT // todo
|
||||
#define ECOMM ECOMM // communication error on send
|
||||
#define EPROTO EPROTO // protocol error
|
||||
#define EMULTIHOP EMULTIHOP // multihop attempted
|
||||
#define EDOTDOT EDOTDOT // todo
|
||||
#define EBADMSG EBADMSG // bad message
|
||||
#define EOVERFLOW EOVERFLOW // value too large for type
|
||||
#define ENOTUNIQ ENOTUNIQ // name not unique on network
|
||||
#define EBADFD EBADFD // fd in bad *state* (cf. EBADF)
|
||||
#define EREMCHG EREMCHG // remote address changed
|
||||
#define ELIBACC ELIBACC // cannot access dso
|
||||
#define ELIBBAD ELIBBAD // corrupted shared library
|
||||
#define ELIBSCN ELIBSCN // a.out section corrupted
|
||||
#define ELIBMAX ELIBMAX // too many shared libraries
|
||||
#define ELIBEXEC ELIBEXEC // cannot exec a dso directly
|
||||
#define EILSEQ EILSEQ // invalid wide character
|
||||
#define ERESTART ERESTART // please restart syscall
|
||||
#define ESTRPIPE ESTRPIPE // streams pipe error
|
||||
#define EUSERS EUSERS // too many users
|
||||
#define ENOTSOCK ENOTSOCK // not a socket
|
||||
#define EDESTADDRREQ EDESTADDRREQ // dest address needed
|
||||
#define EMSGSIZE EMSGSIZE // message too long
|
||||
#define EPROTOTYPE EPROTOTYPE // protocol wrong for socket
|
||||
#define ENOPROTOOPT ENOPROTOOPT // protocol not available
|
||||
#define EPROTONOSUPPORT EPROTONOSUPPORT // protocol not supported
|
||||
#define ESOCKTNOSUPPORT ESOCKTNOSUPPORT // socket type not supported
|
||||
#define EOPNOTSUPP EOPNOTSUPP // operation not supported on socket
|
||||
#define EPFNOSUPPORT EPFNOSUPPORT // protocol family not supported
|
||||
#define EAFNOSUPPORT EAFNOSUPPORT // address family not supported
|
||||
#define EADDRINUSE EADDRINUSE // address already in use
|
||||
#define EADDRNOTAVAIL EADDRNOTAVAIL // address not available
|
||||
#define ENETDOWN ENETDOWN // network is down
|
||||
#define ENETUNREACH ENETUNREACH // network unreachable
|
||||
#define ENETRESET ENETRESET // connection aborted by network
|
||||
#define ECONNABORTED ECONNABORTED // connection aborted
|
||||
#define ECONNRESET ECONNRESET // connection reset
|
||||
#define ENOBUFS ENOBUFS // no buffer space available
|
||||
#define EISCONN EISCONN // socket is connected
|
||||
#define ENOTCONN ENOTCONN // the socket is not connected
|
||||
#define ESHUTDOWN ESHUTDOWN // no send after endpoint shutdown
|
||||
#define ETOOMANYREFS ETOOMANYREFS // too many refs
|
||||
#define ETIMEDOUT ETIMEDOUT // connection timed out
|
||||
#define ECONNREFUSED ECONNREFUSED // connection refused
|
||||
#define EHOSTDOWN EHOSTDOWN // host is down
|
||||
#define EHOSTUNREACH EHOSTUNREACH // host is unreachable
|
||||
#define EALREADY EALREADY // connection already in progress
|
||||
#define EINPROGRESS EINPROGRESS // operation in progress
|
||||
#define ESTALE ESTALE // stale file handle
|
||||
#define EUCLEAN EUCLEAN // structure needs cleaning
|
||||
#define ENOTNAM ENOTNAM // todo
|
||||
#define ENAVAIL ENAVAIL // todo
|
||||
#define EISNAM EISNAM // is a named type file
|
||||
#define EREMOTEIO EREMOTEIO // remote i/o error
|
||||
#define EDQUOT EDQUOT // disk quota exceeded
|
||||
#define ENOMEDIUM ENOMEDIUM // no medium found
|
||||
#define EMEDIUMTYPE EMEDIUMTYPE // wrong medium type
|
||||
#define ECANCELED ECANCELED // operation canceled
|
||||
#define ENOKEY ENOKEY // required key not available
|
||||
#define EKEYEXPIRED EKEYEXPIRED // key has expired
|
||||
#define EKEYREVOKED EKEYREVOKED // key has been revoked
|
||||
#define EKEYREJECTED EKEYREJECTED // key was rejected by service
|
||||
#define EOWNERDEAD EOWNERDEAD // owner died
|
||||
#define ENOTRECOVERABLE ENOTRECOVERABLE // state not recoverable
|
||||
#define ERFKILL ERFKILL // can't op b/c RF-kill
|
||||
#define EHWPOISON EHWPOISON // mempage has h/w error
|
||||
#define EWOULDBLOCK EAGAIN // poll fd and try again
|
||||
#define ENOTSUP ENOTSUP
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*-*- 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/escape/escape.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Internal function aspecting escaping ops with allocating behavior.
|
||||
* @see aescapesh(), aescapec()
|
||||
*/
|
||||
int aescape(char **escaped, size_t size, const char *unescaped, unsigned length,
|
||||
int impl(char *escaped, unsigned size, const char *unescaped,
|
||||
unsigned length)) {
|
||||
int wrote;
|
||||
char *p2;
|
||||
if ((p2 = realloc(*escaped, size)) != NULL) {
|
||||
*escaped = p2;
|
||||
if ((wrote = impl(*escaped, size, unescaped, length)) != -1) {
|
||||
if ((unsigned)wrote <= size - 1) {
|
||||
return wrote;
|
||||
} else {
|
||||
assert(__builtin_return_address(0) != aescape);
|
||||
return aescape(escaped, wrote + 1, unescaped, length, impl);
|
||||
}
|
||||
}
|
||||
}
|
||||
free_s(escaped);
|
||||
return -1;
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*-*- 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/escape/escape.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
// TODO(jart): implement me
|
||||
|
||||
/**
|
||||
* Decodes backslash escape sequences in-place.
|
||||
*
|
||||
* We support the C standard definitions, and the gotchas that entails:
|
||||
*
|
||||
* \newline ← noop for multi-line str
|
||||
* \' \" \? \\ ← we try hard to avoid \?
|
||||
* \a \b \f \n \r \t \v \e ← \e is A++ GNU extension
|
||||
* \ octal-digit ← base-8 literal encoding
|
||||
* \ octal-digit octal-digit ← octal: super dependable
|
||||
* \ octal-digit octal-digit octal-digit ← longstanding DEC legacy
|
||||
* \x[0-9A-Fa-f]+ ← base16 literal encoding
|
||||
* \u[0-9A-Fa-f]{4} ← UNICODEs
|
||||
* \U[0-9A-Fa-f]{8} (astral planes) ← UNICODEs: Astral Planes
|
||||
*
|
||||
* @param n is # bytes in p
|
||||
* @param p is byte array of string literal content
|
||||
* @return new byte size of s, or -i to indicate first error at s[i]
|
||||
* @note we do not check for NUL terminator on input
|
||||
* @note array is zero-filled if shortened
|
||||
* @see cescapec(), strlen()
|
||||
*/
|
||||
int cunescape(size_t n, char p[n]) {
|
||||
unsigned char t[32];
|
||||
unsigned i, j, m, tc, tn, mask;
|
||||
for (m = n, i = 0; i < n; i += j) {
|
||||
tc = sizeof(t);
|
||||
tn = MIN(m - i, tc);
|
||||
memset(t, 0, tc);
|
||||
memcpy(t, p + i, tn);
|
||||
for (mask = j = 0; j < tc; ++j) {
|
||||
if (p[j] == '\\') mask |= 1u << j;
|
||||
}
|
||||
if (j < ARRAYLEN(t)) {
|
||||
memcpy(p + i, t, tn);
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ESCAPE_ESCAPE_H_
|
||||
#define COSMOPOLITAN_LIBC_ESCAPE_ESCAPE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § escaping ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
unsigned cescapec(int);
|
||||
int escapec(char *, unsigned, const char *, unsigned)
|
||||
paramsnonnull((3)) nothrow nocallback;
|
||||
int escapesh(char *, unsigned, const char *, unsigned) paramsnonnull((3));
|
||||
bool escapedos(char16_t *, unsigned, const char16_t *, unsigned);
|
||||
int aescapec(char **, const char *, unsigned) paramsnonnull();
|
||||
int aescapesh(char **, const char *, unsigned) paramsnonnull();
|
||||
int aescape(char **, size_t, const char *, unsigned,
|
||||
int (*)(char *, unsigned, const char *, unsigned)) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_ESCAPE_ESCAPE_H_ */
|
|
@ -1,57 +0,0 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += LIBC_ESCAPE
|
||||
|
||||
LIBC_ESCAPE_ARTIFACTS += LIBC_ESCAPE_A
|
||||
LIBC_ESCAPE = $(LIBC_ESCAPE_A_DEPS) $(LIBC_ESCAPE_A)
|
||||
LIBC_ESCAPE_A = o/$(MODE)/libc/escape/escape.a
|
||||
LIBC_ESCAPE_A_FILES := $(wildcard libc/escape/*)
|
||||
LIBC_ESCAPE_A_HDRS = $(filter %.h,$(LIBC_ESCAPE_A_FILES))
|
||||
LIBC_ESCAPE_A_SRCS_S = $(filter %.S,$(LIBC_ESCAPE_A_FILES))
|
||||
LIBC_ESCAPE_A_SRCS_C = $(filter %.c,$(LIBC_ESCAPE_A_FILES))
|
||||
|
||||
LIBC_ESCAPE_A_SRCS = \
|
||||
$(LIBC_ESCAPE_A_SRCS_S) \
|
||||
$(LIBC_ESCAPE_A_SRCS_C)
|
||||
|
||||
LIBC_ESCAPE_A_OBJS = \
|
||||
$(LIBC_ESCAPE_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_ESCAPE_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_ESCAPE_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_ESCAPE_A_CHECKS = \
|
||||
$(LIBC_ESCAPE_A).pkg \
|
||||
$(LIBC_ESCAPE_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_ESCAPE_A_DIRECTDEPS = \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV
|
||||
|
||||
LIBC_ESCAPE_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_ESCAPE_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_ESCAPE_A): \
|
||||
libc/escape/ \
|
||||
$(LIBC_ESCAPE_A).pkg \
|
||||
$(LIBC_ESCAPE_A_OBJS)
|
||||
|
||||
$(LIBC_ESCAPE_A).pkg: \
|
||||
$(LIBC_ESCAPE_A_OBJS) \
|
||||
$(foreach x,$(LIBC_ESCAPE_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
LIBC_ESCAPE_LIBS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)))
|
||||
LIBC_ESCAPE_SRCS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_ESCAPE_HDRS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_ESCAPE_BINS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_ESCAPE_CHECKS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_ESCAPE_OBJS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)_OBJS))
|
||||
LIBC_ESCAPE_TESTS = $(foreach x,$(LIBC_ESCAPE_ARTIFACTS),$($(x)_TESTS))
|
||||
$(LIBC_ESCAPE_OBJS): $(BUILD_FILES) libc/escape/escape.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/escape
|
||||
o/$(MODE)/libc/escape: $(LIBC_ESCAPE_CHECKS)
|
|
@ -1,73 +0,0 @@
|
|||
/*-*- 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/bits/safemacros.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define SHQUOTE_PUTCHAR(c) \
|
||||
do { \
|
||||
if (buf != NULL && j < size - 1) { \
|
||||
buf[j] = (c); \
|
||||
} \
|
||||
j++; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Quotes memory for inclusion in single-quoted SystemV string literals.
|
||||
*
|
||||
* The outer quotation marks are *not* added.
|
||||
*
|
||||
* @param buf is the output area, which can't overlap and, no matter
|
||||
* what, a NUL-terminator will always be placed in the buffer at
|
||||
* an appropriate place, provided buf!=NULL && size!=0
|
||||
* @param size is the byte-length of the output area
|
||||
* @param s is the data, which may have NUL characters
|
||||
* @param l is the byte-length of s
|
||||
* @return number of characters written, excluding NUL terminator; or,
|
||||
* if the output buffer wasn't passed, or was too short, then the
|
||||
* number of characters that *would* have been written is returned;
|
||||
* since that's how the snprintf() API works; and never < 0
|
||||
* @see xaescapesh() for an easier api
|
||||
*/
|
||||
int escapesh(char *buf, unsigned size, const char *s, unsigned l) {
|
||||
assert(size <= INT_MAX && l <= INT_MAX);
|
||||
if (!IsTrustworthy() && l >= INT_MAX) abort();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < l; ++i) {
|
||||
if (s[i] != '\'') {
|
||||
SHQUOTE_PUTCHAR(s[i]);
|
||||
} else {
|
||||
const char *const s2 = "'\"'\"'";
|
||||
unsigned l2 = 5;
|
||||
for (unsigned k = 0; k < l2; ++k) {
|
||||
SHQUOTE_PUTCHAR(s2[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buf && size) {
|
||||
buf[min(j, size - 1)] = '\0';
|
||||
}
|
||||
return j;
|
||||
}
|
|
@ -39,7 +39,6 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/paland.inc"
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
|
@ -58,7 +57,7 @@ static int ppatoi(const char **str) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements {,v}{,s{,n},{,{,x}as},f,d}printf state machine.
|
||||
* Implements {,v}{,s{,n},{,{,x}as},f,d}printf domain-specific language.
|
||||
*
|
||||
* Type Specifiers
|
||||
*
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/fmt/paland.inc"
|
||||
#include "libc/fmt/palandprintf.h"
|
||||
#include "libc/nexgen32e/tinystrlen.h"
|
||||
|
|
|
@ -35,7 +35,7 @@ const char *geterrname(int code) {
|
|||
n = &EXFULL + 1 - e;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (code == e[i]) {
|
||||
return indexdoublenulstring(kErrnoNames, i);
|
||||
return IndexDoubleNulString(kErrnoNames, i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
#include "libc/conv/itoa.h"
|
||||
#include "libc/log/asan.h"
|
||||
#include "libc/log/backtrace.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/hook/hook.h"
|
||||
#include "libc/runtime/directmap.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
@ -144,16 +146,23 @@ static const char *__asan_describe_access_poison(int c) {
|
|||
|
||||
static noreturn void __asan_die(const char *msg, size_t size) {
|
||||
write(STDERR_FILENO, msg, size);
|
||||
PrintBacktraceUsingSymbols(STDERR_FILENO, __builtin_frame_address(0),
|
||||
GetSymbolTable());
|
||||
DebugBreak();
|
||||
_Exit(66);
|
||||
die();
|
||||
}
|
||||
|
||||
static char *__asan_report_start(char *p) {
|
||||
bool ansi;
|
||||
const char *term;
|
||||
term = getenv("TERM");
|
||||
ansi = !term || strcmp(term, "dumb") != 0;
|
||||
if (ansi) p = stpcpy(p, "\r\e[J\e[1;91m");
|
||||
p = stpcpy(p, "asan error");
|
||||
if (ansi) p = stpcpy(p, "\e[0m");
|
||||
return stpcpy(p, ": ");
|
||||
}
|
||||
|
||||
static noreturn void __asan_report_deallocate_fault(void *addr, int c) {
|
||||
char *p, ibuf[21], buf[256];
|
||||
p = buf;
|
||||
p = stpcpy(p, "error: ");
|
||||
p = __asan_report_start(buf);
|
||||
p = stpcpy(p, __asan_dscribe_free_poison(c));
|
||||
p = stpcpy(p, " ");
|
||||
p = mempcpy(p, ibuf, int64toarray_radix10(c, ibuf));
|
||||
|
@ -166,8 +175,7 @@ static noreturn void __asan_report_deallocate_fault(void *addr, int c) {
|
|||
static noreturn void __asan_report_memory_fault(uint8_t *addr, int size,
|
||||
const char *kind) {
|
||||
char *p, ibuf[21], buf[256];
|
||||
p = buf;
|
||||
p = stpcpy(p, "error: ");
|
||||
p = __asan_report_start(buf);
|
||||
p = stpcpy(p, __asan_describe_access_poison(*(char *)SHADOW((intptr_t)addr)));
|
||||
p = stpcpy(p, " ");
|
||||
p = mempcpy(p, ibuf, uint64toarray_radix10(size, ibuf));
|
||||
|
|
|
@ -19,17 +19,19 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
STATIC_YOINK("stoa");
|
||||
|
@ -46,12 +48,12 @@ relegated void __check_fail(const char *suffix, const char *opstr,
|
|||
va_list va;
|
||||
char sufbuf[8];
|
||||
int lasterr = errno;
|
||||
startfatal(file, line);
|
||||
__start_fatal(file, line);
|
||||
|
||||
if (!memccpy(sufbuf, suffix, '\0', sizeof(sufbuf))) strcpy(sufbuf, "?");
|
||||
strtoupper(sufbuf);
|
||||
|
||||
(fprintf)(stderr,
|
||||
(dprintf)(STDERR_FILENO,
|
||||
"check failed\r\n"
|
||||
"\tCHECK_%s(%s, %s);\r\n"
|
||||
"\t\t → %#lx (%s)\r\n"
|
||||
|
@ -59,27 +61,26 @@ relegated void __check_fail(const char *suffix, const char *opstr,
|
|||
sufbuf, wantstr, gotstr, want, wantstr, opstr, got, gotstr);
|
||||
|
||||
if (!isempty(fmt)) {
|
||||
fputc('\t', stderr);
|
||||
(dprintf)(STDERR_FILENO, "\t");
|
||||
va_start(va, fmt);
|
||||
(vfprintf)(stderr, fmt, va);
|
||||
(vdprintf)(STDERR_FILENO, fmt, va);
|
||||
va_end(va);
|
||||
fputs("\r\n", stderr);
|
||||
(dprintf)(STDERR_FILENO, "\r\n");
|
||||
}
|
||||
|
||||
(fprintf)(stderr, "\t%s\r\n\t%s%s%s%s\r\n", strerror(lasterr), SUBTLE,
|
||||
(dprintf)(STDERR_FILENO, "\t%s\r\n\t%s%s%s%s\r\n", strerror(lasterr), SUBTLE,
|
||||
getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET);
|
||||
|
||||
for (i = 1; i < g_argc; ++i) {
|
||||
(fprintf)(stderr, "\t\t%s%s\r\n", g_argv[i], i < g_argc - 1 ? " \\" : "");
|
||||
(dprintf)(STDERR_FILENO, "\t\t%s%s\r\n", g_argv[i],
|
||||
i < g_argc - 1 ? " \\" : "");
|
||||
}
|
||||
|
||||
if (!IsTiny() && lasterr == ENOMEM) {
|
||||
(fprintf)(stderr, "\r\n");
|
||||
fflush(stderr);
|
||||
PrintMemoryIntervals(fileno(stderr), &_mmi);
|
||||
(dprintf)(STDERR_FILENO, "\r\n");
|
||||
PrintMemoryIntervals(STDERR_FILENO, &_mmi);
|
||||
}
|
||||
|
||||
fflush(stderr);
|
||||
die();
|
||||
unreachable;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
|
|||
char bx[21];
|
||||
int lasterr;
|
||||
lasterr = errno;
|
||||
startfatal_ndebug();
|
||||
__start_fatal_ndebug();
|
||||
__print_string("check failed: 0x");
|
||||
__print(bx, uint64toarray_radix16(want, bx));
|
||||
__print_string(" ");
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_COLOR_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_COLOR_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define CLS (cancolor() ? "\r\e[J" : "")
|
||||
#define RED (cancolor() ? "\e[30;101m" : "")
|
||||
#define GREEN (cancolor() ? "\e[32m" : "")
|
||||
#define UNBOLD (cancolor() ? "\e[22m" : "")
|
||||
#define RED2 (cancolor() ? "\e[91;1m" : "")
|
||||
#define BLUE1 (cancolor() ? "\e[94;49m" : "")
|
||||
#define BLUE2 (cancolor() ? "\e[34m" : "")
|
||||
#define RESET (cancolor() ? "\e[0m" : "")
|
||||
#define SUBTLE (cancolor() ? "\e[35m" : "")
|
||||
|
||||
bool cancolor(void) nothrow nocallback nosideeffect;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LOG_COLOR_H_ */
|
|
@ -1,33 +1,17 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_INTERNAL_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define RED (cancolor() ? "\x1b[30;101m" : "")
|
||||
#define UNBOLD (cancolor() ? "\x1b[22m" : "")
|
||||
#define RED2 (cancolor() ? "\x1b[91;1m" : "")
|
||||
#define BLUE1 (cancolor() ? "\x1b[94;49m" : "")
|
||||
#define BLUE2 (cancolor() ? "\x1b[34m" : "")
|
||||
#define RESET (cancolor() ? "\x1b[0m" : "")
|
||||
#define SUBTLE (cancolor() ? "\x1b[35m" : "")
|
||||
|
||||
enum NtExceptionHandlerActions;
|
||||
struct NtExceptionPointers;
|
||||
|
||||
extern int kCrashSigs[8];
|
||||
extern struct sigaction g_oldcrashacts[8];
|
||||
extern const char kCrashSigNames[8][5] aligned(1);
|
||||
extern const char kGregNames[17][4] aligned(1);
|
||||
extern const char kGregOrder[17] aligned(1);
|
||||
|
||||
void startfatal(const char *, int) hidden;
|
||||
void startfatal_ndebug(void) hidden;
|
||||
void oncrash(int, struct siginfo *, struct ucontext *) relegated;
|
||||
enum NtExceptionHandlerActions wincrash$nt(
|
||||
const struct NtExceptionPointers *) relegated;
|
||||
void __start_fatal(const char *, int) hidden;
|
||||
void __start_fatal_ndebug(void) hidden;
|
||||
void __oncrash(int, struct siginfo *, struct ucontext *) relegated;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -39,7 +39,6 @@ void meminfo(int); /* shows malloc statistics &c. */
|
|||
void memsummary(int); /* light version of same thing */
|
||||
uint16_t getttycols(uint16_t);
|
||||
int getttysize(int, struct winsize *) paramsnonnull();
|
||||
bool cancolor(void) nothrow nocallback;
|
||||
bool isterminalinarticulate(void) nosideeffect;
|
||||
char *commandvenv(const char *, const char *) nodiscard;
|
||||
const char *GetAddr2linePath(void);
|
||||
|
|
|
@ -32,7 +32,6 @@ LIBC_LOG_A_DIRECTDEPS = \
|
|||
LIBC_CALLS_HEFTY \
|
||||
LIBC_CONV \
|
||||
LIBC_ELF \
|
||||
LIBC_ESCAPE \
|
||||
LIBC_FMT \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_NEXGEN32E \
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/backtrace.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -49,18 +50,18 @@ STATIC_YOINK("stoa");
|
|||
|
||||
struct siginfo;
|
||||
|
||||
const char kGregOrder[17] aligned(1) = {
|
||||
static const char kGregOrder[17] aligned(1) = {
|
||||
13, 11, 8, 14, 12, 9, 10, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
};
|
||||
|
||||
const char kGregNames[17][4] aligned(1) = {
|
||||
static const char kGregNames[17][4] aligned(1) = {
|
||||
"R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "RDI",
|
||||
"RSI", "RBP", "RBX", "RDX", "RAX", "RCX", "RSP", "RIP",
|
||||
};
|
||||
|
||||
const char kGodHatesFlags[12] aligned(1) = "CVPRAKZSTIDO";
|
||||
const char kCrashSigNames[8][5] aligned(1) = {"QUIT", "FPE", "ILL", "SEGV",
|
||||
"TRAP", "ABRT", "BUS"};
|
||||
static const char kGodHatesFlags[12] aligned(1) = "CVPRAKZSTIDO";
|
||||
static const char kCrashSigNames[8][5] aligned(1) = {
|
||||
"QUIT", "FPE", "ILL", "SEGV", "TRAP", "ABRT", "BUS"};
|
||||
|
||||
int kCrashSigs[8];
|
||||
struct sigaction g_oldcrashacts[8];
|
||||
|
@ -191,7 +192,7 @@ relegated static void RestoreDefaultCrashSignalHandlers(void) {
|
|||
*
|
||||
* This function never returns, except for traps w/ human supervision.
|
||||
*/
|
||||
relegated void oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
||||
relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
||||
intptr_t rip;
|
||||
int gdbpid, err;
|
||||
static bool once;
|
||||
|
|
|
@ -24,69 +24,69 @@
|
|||
/ caused the crash, particularly in the GDB GUI. They're coded
|
||||
/ into an array to pinch pennies on code size registering them.
|
||||
|
||||
kOncrashThunks:
|
||||
__oncrash_thunks:
|
||||
|
||||
.org 11*0
|
||||
oncrash_sigquit:
|
||||
__oncrash_sigquit:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigquit,globl
|
||||
.endfn __oncrash_sigquit,globl
|
||||
|
||||
.org 11*1
|
||||
oncrash_sigfpe:
|
||||
__oncrash_sigfpe:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigfpe,globl
|
||||
.endfn __oncrash_sigfpe,globl
|
||||
|
||||
.org 11*2
|
||||
oncrash_sigill:
|
||||
__oncrash_sigill:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigill,globl
|
||||
.endfn __oncrash_sigill,globl
|
||||
|
||||
.org 11*3
|
||||
oncrash_sigsegv:
|
||||
__oncrash_sigsegv:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigsegv,globl
|
||||
.endfn __oncrash_sigsegv,globl
|
||||
|
||||
.org 11*4
|
||||
oncrash_sigtrap:
|
||||
__oncrash_sigtrap:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigtrap,globl
|
||||
.endfn __oncrash_sigtrap,globl
|
||||
|
||||
.org 11*5
|
||||
oncrash_sigabrt:
|
||||
__oncrash_sigabrt:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigabrt,globl
|
||||
.endfn __oncrash_sigabrt,globl
|
||||
|
||||
.org 11*6
|
||||
oncrash_sigbus:
|
||||
__oncrash_sigbus:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigbus,globl
|
||||
.endfn __oncrash_sigbus,globl
|
||||
|
||||
.endobj kOncrashThunks,globl
|
||||
.endobj __oncrash_thunks,globl
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
STATIC_YOINK("die");
|
||||
STATIC_YOINK("__ubsan_abort");
|
||||
|
||||
extern const unsigned char kOncrashThunks[7][11];
|
||||
extern const unsigned char __oncrash_thunks[7][11];
|
||||
|
||||
/**
|
||||
* Installs crash signal handlers.
|
||||
|
@ -73,7 +73,7 @@ void showcrashreports(void) {
|
|||
}
|
||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||
if (kCrashSigs[i]) {
|
||||
sa.sa_sigaction = (sigaction_f)kOncrashThunks[i];
|
||||
sa.sa_sigaction = (sigaction_f)__oncrash_thunks[i];
|
||||
sigaction(kCrashSigs[i], &sa, &g_oldcrashacts[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,19 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
/**
|
||||
* Prints initial part of fatal message.
|
||||
*
|
||||
* @note this is support code for __check_fail(), __assert_fail(), etc.
|
||||
* @see startfatal_ndebug()
|
||||
* @see __start_fatal_ndebug()
|
||||
*/
|
||||
relegated void startfatal(const char *file, int line) {
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "%s%s%s:%s:%d:%s%s: ", RED, "error", BLUE1, file, line,
|
||||
program_invocation_short_name, RESET);
|
||||
relegated void __start_fatal(const char *file, int line) {
|
||||
dprintf(STDERR_FILENO, "%s%s%s%s:%s:%d:%s%s: ", CLS, RED, "error", BLUE1,
|
||||
file, line, program_invocation_short_name, RESET);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
|
@ -24,11 +25,10 @@
|
|||
* Prints initial part of fatal message.
|
||||
*
|
||||
* @note this is support code for __check_fail(), __assert_fail(), etc.
|
||||
* @see startfatal()
|
||||
* @see __start_fatal()
|
||||
*/
|
||||
relegated void startfatal_ndebug(void) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
relegated void __start_fatal_ndebug(void) {
|
||||
if (cancolor()) __print_string("\r\e[J");
|
||||
__print_string("error:");
|
||||
__print_string(program_invocation_name);
|
||||
__print_string(": ");
|
||||
|
|
|
@ -55,7 +55,7 @@ void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
|||
}
|
||||
g_runstate |= RUNSTATE_BROKEN;
|
||||
if (IsDebuggerPresent(false)) DebugBreak();
|
||||
startfatal(loc->file, loc->line);
|
||||
__start_fatal(loc->file, loc->line);
|
||||
fprintf(stderr, "%s\r\n", description);
|
||||
die();
|
||||
unreachable;
|
||||
|
@ -74,7 +74,7 @@ void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *type_mismatch,
|
|||
uintptr_t pointer) {
|
||||
struct UbsanSourceLocation *loc = &type_mismatch->location;
|
||||
const char *description;
|
||||
const char *kind = indexdoublenulstring(kUbsanTypeCheckKinds,
|
||||
const char *kind = IndexDoubleNulString(kUbsanTypeCheckKinds,
|
||||
type_mismatch->type_check_kind);
|
||||
if (pointer == 0) {
|
||||
description = "null pointer access";
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
|
@ -113,8 +114,8 @@ void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
|||
va_end(va);
|
||||
fputs("\r\n", f);
|
||||
if (level == kLogFatal) {
|
||||
startfatal(file, line);
|
||||
(fprintf)(stderr, "fatal error see logfile\r\n");
|
||||
__start_fatal(file, line);
|
||||
(dprintf)(STDERR_FILENO, "fatal error see logfile\r\n");
|
||||
die();
|
||||
unreachable;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
|
@ -17,15 +17,15 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.h"
|
||||
|
||||
/**
|
||||
* Single-quotes string for bourne shell.
|
||||
* Releases freed memory back to system.
|
||||
*
|
||||
* @return escaped string which must make its way to free()
|
||||
* @param pad can specify how many bytes of memory to leave available
|
||||
* @return 1 if it actually released any memory, else 0
|
||||
*/
|
||||
char *xaescapeshq(const char *unescaped) {
|
||||
return xasprintf("'%s'", gc(xaescape(unescaped, escapesh)));
|
||||
int malloc_trim(size_t pad) {
|
||||
return dlmalloc_trim(pad);
|
||||
}
|
|
@ -29,7 +29,8 @@
|
|||
/ @param %rcx,%rdx,%r8,%r9
|
||||
/ @return %rax,%xmm0
|
||||
/ @note this is so much slower than sysv2nt()
|
||||
nt2sysv:push %rbp
|
||||
__nt2sysv:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
sub $0x100,%rsp
|
||||
|
@ -53,5 +54,5 @@ nt2sysv:push %rbp
|
|||
pop %rbx
|
||||
leave
|
||||
ret
|
||||
.endfn nt2sysv,globl,hidden
|
||||
.endfn __nt2sysv,globl,hidden
|
||||
.source __FILE__
|
||||
|
|
|
@ -105,15 +105,6 @@ strnlen_s:
|
|||
.leafepilogue
|
||||
.endfn strnlen_s,globl
|
||||
|
||||
/ Returns length of NUL-terminated string.
|
||||
/
|
||||
/ @param rdi is non-null NUL-terminated string pointer
|
||||
/ @return rax is the number of bytes, excluding the NUL
|
||||
/ @asyncsignalsafe
|
||||
strlen: or $-1,%rsi
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn strlen,globl
|
||||
|
||||
/ Returns length of NUL-terminated memory, with limit.
|
||||
/
|
||||
/ @param rdi is non-null memory
|
||||
|
@ -129,7 +120,7 @@ strnlen:.leafprologue
|
|||
.endfn strnlen,globl
|
||||
|
||||
/ Swiss army knife of string character scanning.
|
||||
/ Sixteen fast functions in one.
|
||||
/ Fourteen fast functions in one.
|
||||
/
|
||||
/ @param rdi is non-null string memory
|
||||
/ @param rsi is max number of bytes to consider
|
||||
|
|
|
@ -29,6 +29,7 @@ LIBC_RAND_A_DIRECTDEPS = \
|
|||
LIBC_TINYMATH \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_SYSV
|
||||
|
||||
|
|
|
@ -25,18 +25,18 @@
|
|||
.source __FILE__
|
||||
|
||||
.init.start 400,_init_g_stderr
|
||||
lea g_stderr(%rip),%rax
|
||||
ezlea g_stderr,ax
|
||||
push $_IOLBF
|
||||
pop (%rax) #→ f.fd
|
||||
push STDERR_FILENO
|
||||
pop 12(%rax)
|
||||
mov O_WRONLY,%edx
|
||||
mov %edx,4(%rax) #→ f.iomode
|
||||
lea g_stderr_buf(%rip),%rcx
|
||||
ezlea g_stderr_buf,cx
|
||||
mov %rcx,24(%rax) #→ f.buf
|
||||
movl $BUFSIZ,32(%rax) #→ f.size
|
||||
lea fwritebuf(%rip),%rcx
|
||||
lea fswritebuf(%rip),%rdx
|
||||
ezlea fwritebuf,cx
|
||||
ezlea fswritebuf,dx
|
||||
testb IsMetal()
|
||||
cmove %rcx,%rdx
|
||||
mov %rdx,48(%rax) #→ f.writer
|
||||
|
|
|
@ -25,14 +25,14 @@
|
|||
.source __FILE__
|
||||
|
||||
.init.start 400,_init_g_stdin
|
||||
lea g_stdin(%rip),%rax
|
||||
ezlea g_stdin,ax
|
||||
mov O_RDONLY,%edx
|
||||
mov %edx,4(%rax) #→ f.iomode
|
||||
lea g_stdin_buf(%rip),%rcx
|
||||
ezlea g_stdin_buf,cx
|
||||
mov %rcx,24(%rax) #→ f.buf
|
||||
movl $BUFSIZ,32(%rax) #→ f.size
|
||||
lea freadbuf(%rip),%rcx
|
||||
lea fsreadbuf(%rip),%rdx
|
||||
ezlea freadbuf,cx
|
||||
ezlea fsreadbuf,dx
|
||||
testb IsMetal()
|
||||
cmove %rcx,%rdx
|
||||
mov %rdx,40(%rax) #→ f.reader
|
||||
|
|
|
@ -25,16 +25,16 @@
|
|||
.source __FILE__
|
||||
|
||||
.init.start 400,_init_g_stdout
|
||||
lea g_stdout(%rip),%rax
|
||||
ezlea g_stdout,ax
|
||||
push STDOUT_FILENO
|
||||
pop 12(%rax) #→ f.fd
|
||||
mov O_WRONLY,%edx
|
||||
mov %edx,4(%rax) #→ f.iomode
|
||||
lea g_stdout_buf(%rip),%rcx
|
||||
ezlea g_stdout_buf,cx
|
||||
mov %rcx,24(%rax) #→ f.buf
|
||||
movl $BUFSIZ,32(%rax) #→ f.size
|
||||
lea fwritebuf(%rip),%rcx
|
||||
lea fswritebuf(%rip),%rdx
|
||||
ezlea fwritebuf,cx
|
||||
ezlea fswritebuf,dx
|
||||
testb IsMetal()
|
||||
cmovz %rcx,%rdx
|
||||
mov %rdx,48(%rax) #→ f.writer
|
||||
|
|
|
@ -29,7 +29,6 @@ LIBC_STDIO_A_DIRECTDEPS = \
|
|||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_CONV \
|
||||
LIBC_ESCAPE \
|
||||
LIBC_FMT \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
|
|
|
@ -25,11 +25,10 @@
|
|||
* @param s is a NUL-terminated string
|
||||
* @param suffix is also NUL-terminated
|
||||
*/
|
||||
bool(endswith)(const char *s, const char *suffix) {
|
||||
size_t l1, l2;
|
||||
if (s == suffix) return true;
|
||||
l1 = strlen(s);
|
||||
l2 = strnlen(suffix, l1);
|
||||
if (l2 > l1) return false;
|
||||
return memcmp(s + (l1 - l2) * sizeof(char), suffix, l2 * sizeof(char)) == 0;
|
||||
bool endswith(const char *s, const char *suffix) {
|
||||
size_t n, m;
|
||||
n = strlen(s);
|
||||
m = strlen(suffix);
|
||||
if (m > n) return false;
|
||||
return memcmp(s + n - m, suffix, m) == 0;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static textwindows bool shouldescapedos(const char16_t c) {
|
|
@ -20,11 +20,11 @@
|
|||
#include "libc/str/str.h"
|
||||
|
||||
int getkvlin(const char *name, const char *const unsorted[]) {
|
||||
unsigned i, n;
|
||||
if (unsorted) {
|
||||
unsigned namelen = strlen(name);
|
||||
for (int i = 0; unsorted[i]; ++i) {
|
||||
if (strncmp(unsorted[i], name, namelen) == 0 &&
|
||||
unsorted[i][namelen] == '=') {
|
||||
n = strlen(name);
|
||||
for (i = 0; unsorted[i]; ++i) {
|
||||
if (strncmp(unsorted[i], name, n) == 0 && unsorted[i][n] == '=') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const char *indexdoublenulstring(const char *p, unsigned i) {
|
||||
const char *IndexDoubleNulString(const char *s, unsigned i) {
|
||||
size_t n;
|
||||
while (i--) {
|
||||
const char *p2 = rawmemchr(p, '\0');
|
||||
if (p2 == p) return NULL;
|
||||
p = p2 + 1;
|
||||
if ((n = strlen(s))) {
|
||||
s += n + 1;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -26,27 +26,12 @@
|
|||
|
||||
hidden extern const uint32_t kSha256Tab[64];
|
||||
|
||||
extern const struct TpEncode {
|
||||
uint8_t mark;
|
||||
uint8_t len;
|
||||
} kTpDecoderRing[32];
|
||||
|
||||
forceinline struct TpEncode UseTpDecoderRing(wint_t c) {
|
||||
unsigned msb;
|
||||
if (c) {
|
||||
asm("bsr\t%1,%0" : "=r"(msb) : "rm"(c) : "cc");
|
||||
} else {
|
||||
msb = 0;
|
||||
}
|
||||
return kTpDecoderRing[msb];
|
||||
}
|
||||
|
||||
nodebuginfo forceinline bool32 ismoar(wint_t c) {
|
||||
return (c & 0b11000000) == 0b11000000;
|
||||
return (c & 0300) == 0300;
|
||||
}
|
||||
|
||||
nodebuginfo forceinline bool32 iscont(wint_t c) {
|
||||
return (c & 0b11000000) == 0b10000000;
|
||||
return (c & 0300) == 0200;
|
||||
}
|
||||
|
||||
char *strstr$sse42(const char *, const char *) strlenesque hidden;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
int isascii(int c) {
|
||||
return 0x00 <= c && c <= 0x7F;
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/*-*- 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
/**
|
||||
* Checks if memory address contains non-plain text.
|
||||
*
|
||||
* @param data points to memory that's interpreted as char
|
||||
* @param size is usually strlen(data) and provided by caller
|
||||
* @return NULL if plain text, or pointer to first non-text datum
|
||||
* @type char may be 6/7/8/16/32/64-bit signed/unsigned single/multi
|
||||
* @author Justine Alexandra Roberts Tunney <jtunney@gmail.com>
|
||||
* @see ASA X3.4, ISO/IEC 646, ITU T.50, ANSI X3.64-1979
|
||||
* @perf 27gBps on i7-6700 w/ -O3 -mavx2
|
||||
* @cost 143 bytes of code w/ -Os
|
||||
*/
|
||||
void *isnotplaintext(const void *data, size_t size) {
|
||||
/*
|
||||
* ASCII, EBCDIC, UNICODE, ISO IR-67, etc. all agree upon the
|
||||
* encoding of the NUL, SOH, STX, and ETX characters due to a
|
||||
* longstanding human tradition of using them for the purpose
|
||||
* of delimiting text from non-text, b/c fixed width integers
|
||||
* makes their presence in binary formats nearly unavoidable.
|
||||
*/
|
||||
#define isnotplain(C) (0 <= (C) && (C) < 4)
|
||||
char no;
|
||||
unsigned i;
|
||||
const char *p, *pe;
|
||||
if (CHAR_BIT > 6) {
|
||||
p = (const char *)data;
|
||||
pe = (const char *)(p + size);
|
||||
for (; ((intptr_t)p & 31) && p < pe; ++p) {
|
||||
if (isnotplain(*p)) return p;
|
||||
}
|
||||
for (; p + 64 < pe; p += 64) {
|
||||
no = 0;
|
||||
for (i = 0; i < 64; ++i) {
|
||||
no |= isnotplain(p[i]);
|
||||
}
|
||||
if (no & 1) break;
|
||||
}
|
||||
for (; p < pe; ++p) {
|
||||
if (isnotplain(*p)) return p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#undef isnotplain
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*-*- 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"
|
||||
.source __FILE__
|
||||
|
||||
/ Thompson-Pike Decoder Ring.
|
||||
/
|
||||
/ The IA-32 BSR instruction can be used to turn a 32-bit
|
||||
/ number into an index for this table.
|
||||
/
|
||||
/ @see libc/str/internal.h
|
||||
.rodata
|
||||
.align 2
|
||||
kTpDecoderRing:
|
||||
.rept 7 # MSB≤6 (0x7F)
|
||||
.byte 0b00000000,1 # mark,len
|
||||
/ 0b11000000 # mask
|
||||
.endr
|
||||
.rept 4 # MSB≤10 (0x7FF)
|
||||
.byte 0b11000000,2 # mark,len
|
||||
/ 0b11100000 # mask
|
||||
.endr
|
||||
.rept 5 # MSB≤15 (0xFFFF)
|
||||
.byte 0b11100000,3 # mark,len
|
||||
/ 0b11110000 # mask
|
||||
.endr
|
||||
.rept 5 # MSB≤20 (0x1FFFFF)
|
||||
.byte 0b11110000,4 # mark,len
|
||||
/ 0b11111000 # mask
|
||||
.endr
|
||||
.rept 5 # MSB≤25 (0x3FFFFFF)
|
||||
.byte 0b11111000,5 # mark,len
|
||||
/ 0b11111100 # mask
|
||||
.endr
|
||||
.rept 6 # MSB≤31 (0xffffffff)
|
||||
.byte 0b11111100,6 # mark,len
|
||||
.endr
|
||||
.endobj kTpDecoderRing,globl,hidden
|
||||
.previous
|
|
@ -21,11 +21,11 @@
|
|||
|
||||
/**
|
||||
* Returns true if s has prefix.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param prefix is also NUL-terminated
|
||||
*/
|
||||
bool(startswith)(const char *s, const char *prefix) {
|
||||
if (s == prefix) return true;
|
||||
bool startswith(const char *s, const char *prefix) {
|
||||
for (;;) {
|
||||
if (!*prefix) return true;
|
||||
if (!*s) return false;
|
||||
|
|
|
@ -17,20 +17,45 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/pcmpeqb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Copies string and advances destination pointer.
|
||||
* Copies bytes from 𝑠 to 𝑑 until a NUL is encountered.
|
||||
*
|
||||
* @param 𝑑 is destination memory
|
||||
* @param 𝑠 is a NUL-terminated string
|
||||
* @note 𝑑 and 𝑠 can't overlap
|
||||
* @return pointer to nul byte
|
||||
* @see strcpy(), memccpy()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *stpcpy(char *dst, const char *src) {
|
||||
char c;
|
||||
for (;;) {
|
||||
c = *src;
|
||||
*dst = c;
|
||||
if (!c) break;
|
||||
++src;
|
||||
++dst;
|
||||
char *stpcpy(char *d, const char *s) {
|
||||
size_t i;
|
||||
uint8_t v1[16], v2[16], vz[16];
|
||||
i = 0;
|
||||
while (((uintptr_t)(s + i) & 15)) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d + i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
for (;;) {
|
||||
memset(vz, 0, 16);
|
||||
memcpy(v1, s + i, 16);
|
||||
pcmpeqb(v2, v1, vz);
|
||||
if (!pmovmskb(v2)) {
|
||||
memcpy(d + i, v1, 16);
|
||||
i += 16;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d + i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ int tolower(int);
|
|||
int ispunct(int);
|
||||
int toupper(int);
|
||||
int hextoint(int);
|
||||
|
||||
void *isnotplaintext(const void *, size_t) nothrow nocallback nosideeffect;
|
||||
int cescapec(int);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § characters » thompson-pike encoding ─╬─│┼
|
||||
|
@ -173,7 +172,7 @@ bool wcsstartswith(const wchar_t *, const wchar_t *) strlenesque;
|
|||
bool endswith(const char *, const char *) strlenesque;
|
||||
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;
|
||||
const char *IndexDoubleNulString(const char *, unsigned) strlenesque;
|
||||
int getkvlin(const char *, const char *const[]);
|
||||
wchar_t *wmemset(wchar_t *, wchar_t, size_t) memcpyesque;
|
||||
char16_t *memset16(char16_t *, char16_t, size_t) memcpyesque;
|
||||
|
@ -194,6 +193,8 @@ char *chomp(char *);
|
|||
char16_t *chomp16(char16_t *);
|
||||
wchar_t *wchomp(wchar_t *);
|
||||
|
||||
bool escapedos(char16_t *, unsigned, const char16_t *, unsigned);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » multibyte ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
@ -341,27 +342,6 @@ extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
|
|||
: strncasecmp16, default \
|
||||
: strncasecmp)(s1, s2, n)
|
||||
|
||||
#define startswith(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsstartswith, char16_t \
|
||||
: startswith16, default \
|
||||
: startswith)(s, c)
|
||||
|
||||
#define endswith(s, c) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcsendswith, char16_t \
|
||||
: endswith16, default \
|
||||
: endswith)(s, c)
|
||||
|
||||
#define strclen(s) \
|
||||
_Generic(*(s), wchar_t : wcslen, char16_t : strclen16, default : strclen)(s)
|
||||
|
||||
#define strnclen(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcslen, char16_t \
|
||||
: strnclen16, default \
|
||||
: strnclen)(s, n)
|
||||
|
||||
#define chomp(s) \
|
||||
_Generic(*(s), wchar_t : wchomp, char16_t : chomp16, default : chomp)(s)
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ LIBC_STR_A_CHECKS = \
|
|||
$(LIBC_STR_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_STR_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_STUBS \
|
||||
LIBC_NEXGEN32E
|
||||
|
||||
|
|
|
@ -17,23 +17,23 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns number of characters in UTF-8 string.
|
||||
*/
|
||||
size_t(strclen)(const char *s) { return strnclen(s, -1ull); }
|
||||
size_t strclen(const char *s) {
|
||||
return strnclen(s, -1);
|
||||
}
|
||||
|
||||
noinline size_t(strnclen)(const char *s, size_t n) {
|
||||
const unsigned char *p = (const unsigned char *)s;
|
||||
size_t l = 0;
|
||||
noinline size_t strnclen(const char *s, size_t n) {
|
||||
size_t r = 0;
|
||||
if (n) {
|
||||
while (*p && n && iscont(*p)) ++p, --n;
|
||||
while (*p) {
|
||||
if (!iscont(*p++)) l++;
|
||||
while (n && *s && (*s & 0300) == 0200) ++s, --n;
|
||||
while (*s) {
|
||||
if ((*s++ & 0300) != 0200) r++;
|
||||
if (!--n) break;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/pcmpeqb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
|
@ -31,6 +34,30 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strcpy(char *d, const char *s) {
|
||||
memccpy(d, s, '\0', SIZE_MAX);
|
||||
return d;
|
||||
size_t i;
|
||||
uint8_t v1[16], v2[16], vz[16];
|
||||
i = 0;
|
||||
while (((uintptr_t)(s + i) & 15)) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
for (;;) {
|
||||
memset(vz, 0, 16);
|
||||
memcpy(v1, s + i, 16);
|
||||
pcmpeqb(v2, v1, vz);
|
||||
if (!pmovmskb(v2)) {
|
||||
memcpy(d + i, v1, 16);
|
||||
i += 16;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return d;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,22 +17,34 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/pcmpeqb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Aspects 2-arity memory op with allocating behavior.
|
||||
* Used to turn FOO() into aFOO() without too much duplicated code.
|
||||
* Returns length of NUL-terminated string.
|
||||
*
|
||||
* @param s is non-null NUL-terminated string pointer
|
||||
* @return number of bytes (excluding NUL)
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *xaescape(const char *unescaped,
|
||||
int impl(char *escaped, unsigned size, const char *unescaped,
|
||||
unsigned length)) {
|
||||
char *escaped = NULL;
|
||||
if (aescape(&escaped, 32, unescaped, strlen(unescaped), impl) == -1) {
|
||||
xdie();
|
||||
size_t strlen(const char *s) {
|
||||
const char *p;
|
||||
unsigned k, m;
|
||||
uint8_t v1[16], vz[16];
|
||||
k = (uintptr_t)s & 15;
|
||||
p = (const char *)((uintptr_t)s & -16);
|
||||
memset(vz, 0, 16);
|
||||
memcpy(v1, p, 16);
|
||||
pcmpeqb(v1, v1, vz);
|
||||
m = pmovmskb(v1) >> k << k;
|
||||
while (!m) {
|
||||
p += 16;
|
||||
memcpy(v1, p, 16);
|
||||
pcmpeqb(v1, v1, vz);
|
||||
m = pmovmskb(v1);
|
||||
}
|
||||
return escaped;
|
||||
return p + bsf(m) - s;
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
#define COSMOPOLITAN_LIBC_STR_THOMPIKE_H_
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
|
||||
#define ThomPikeCont(x) (((x)&0b11000000) == 0b10000000)
|
||||
#define ThomPikeCont(x) (((x)&0300) == 0200)
|
||||
#define ThomPikeByte(x) ((x) & (((1 << ThomPikeMsb(x)) - 1) | 3))
|
||||
#define ThomPikeLen(x) (7 - ThomPikeMsb(x))
|
||||
#define ThomPikeMsb(x) (((x)&0xff) < 252 ? bsr(~(x)&0xff) : 1)
|
||||
#define ThomPikeMerge(x, y) ((x) << 6 | (y)&0b00111111)
|
||||
#define ThomPikeMerge(x, y) ((x) << 6 | (y)&077)
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_THOMPIKE_H_ */
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
/ @return is in %rax, %xmm0, or %st
|
||||
/ @note GCC 4.8+ and Clang can avoid this indirection
|
||||
/ @note thunk that jumps here must setup frame
|
||||
/ @note this is so much faster than nt2sysv()
|
||||
/ @note this is so much faster than __nt2sysv()
|
||||
__sysv2nt14:
|
||||
pushq 72(%rbp)
|
||||
pushq 64(%rbp)
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/macros.inc"
|
||||
.scall vfork 0x004200422042003a globl
|
|
@ -293,14 +293,14 @@ syscon spawn POSIX_SPAWN_SETSCHEDPARAM 0x10 0 4 4 0
|
|||
syscon spawn POSIX_SPAWN_SETSCHEDULER 0x20 0 8 8 0
|
||||
syscon spawn POSIX_SPAWN_USEVFORK 0x40 0 0 0 0
|
||||
|
||||
# mprotect(), etc.
|
||||
# mmap(), mprotect(), etc.
|
||||
# digital restrictions management for the people
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD XENIX Commentary
|
||||
syscon mprot PROT_NONE 0 0 0 0 0 # unix consensus (nt needs special business logic here)
|
||||
syscon mprot PROT_READ 1 1 1 1 1 # unix consensus
|
||||
syscon mprot PROT_WRITE 2 2 2 2 2 # unix consensus
|
||||
syscon mprot PROT_EXEC 4 4 4 4 4 # unix consensus
|
||||
syscon mprot PROT_NONE 0 0 0 0 0 # mmap, mprotect, unix consensus (nt needs special business logic here)
|
||||
syscon mprot PROT_READ 1 1 1 1 1 # mmap, mprotect, unix consensus
|
||||
syscon mprot PROT_WRITE 2 2 2 2 2 # mmap, mprotect, unix consensus
|
||||
syscon mprot PROT_EXEC 4 4 4 4 4 # mmap, mprotect, unix consensus
|
||||
syscon mprot PROT_GROWSDOWN 0x01000000 0 0 0 0 # intended for mprotect; see MAP_GROWSDOWN for mmap() (todo: what was 0x01000000 on nt)
|
||||
syscon mprot PROT_GROWSUP 0x02000000 0 0 0 0 # intended for mprotect; see MAP_GROWSDOWN for mmap()
|
||||
|
||||
|
@ -2798,6 +2798,7 @@ syscon nr __NR_access 0x0015 0x2000021 0x0021 0x0021 -1
|
|||
syscon nr __NR_sched_yield 0x0018 0x100003c 0x014b 0x012a -1
|
||||
syscon nr __NR_sendfile 0x0028 0x2000151 0x0189 0xffff -1
|
||||
syscon nr __NR_fork 0x0039 0x2000002 0x0002 0x0002 -1
|
||||
syscon nr __NR_vfork 0x003a 0x2000042 0x0042 0x0042 -1
|
||||
syscon nr __NR_gettimeofday 0x0060 0x2000074 0x0074 0x0043 -1
|
||||
syscon nr __NR_arch_prctl 0x009e 0x000ffff 0x00a5 0x00a5 -1
|
||||
syscon nr __NR_gettid 0x00ba 0x200011e 0xffff 0xffff -1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon mmap MAP_FIXED 16 16 16 16 16
|
||||
.syscon mmap MAP_FIXED 0x10 0x10 0x10 0x10 0x10
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon mmap MAP_NONBLOCK 0x010000 0 0 0 0
|
||||
.syscon mmap MAP_NONBLOCK 0x10000 0 0 0 0
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon nr __NR_vfork 0x003a 0x2000042 0x0042 0x0042 -1
|
|
@ -91,7 +91,7 @@ scall 'socketpair$sysv' 0x0087008720870035 globl hidden
|
|||
scall 'setsockopt$sysv' 0x0069006920690036 globl hidden
|
||||
scall 'getsockopt$sysv' 0x0076007620760037 globl hidden
|
||||
scall 'fork$sysv' 0x0002000220020039 globl hidden
|
||||
scall vfork 0x004200422042003a globl
|
||||
#scall vfork 0x004200422042003a globl # needs to be called via vfork.S
|
||||
scall posix_spawn 0xffffffff20f4ffff globl hidden # TODO: put in spawnve()
|
||||
scall 'execve$sysv' 0x003b003b203b003b globl hidden
|
||||
scall 'wait4$sysv' 0x000b00072007003d globl hidden
|
||||
|
|
|
@ -107,18 +107,18 @@ systemfive.linux:
|
|||
systemfive.error:
|
||||
neg %eax
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn systemfive.error
|
||||
.endfn systemfive.error,globl,hidden
|
||||
systemfive.errno:
|
||||
mov %eax,errno(%rip)
|
||||
push $-1
|
||||
pop %rax
|
||||
stc
|
||||
ret
|
||||
.endfn systemfive.errno
|
||||
.endfn systemfive.errno,globl,hidden
|
||||
systemfive.enosys:
|
||||
mov ENOSYS(%rip),%eax
|
||||
jmp systemfive.errno
|
||||
.endfn systemfive.enosys
|
||||
.endfn systemfive.enosys,globl,hidden
|
||||
systemfive.openbsd:
|
||||
shr $48,%rax
|
||||
jmp systemfive.bsd
|
||||
|
|
|
@ -34,6 +34,7 @@ LIBC_SYSV_A_FILES := \
|
|||
libc/sysv/restorert.S \
|
||||
libc/sysv/syscall.S \
|
||||
libc/sysv/systemfive.S \
|
||||
libc/sysv/vfork.S \
|
||||
$(wildcard libc/sysv/stubs/*) \
|
||||
$(wildcard libc/sysv/consts/*) \
|
||||
$(wildcard libc/sysv/errfuns/*)
|
||||
|
@ -86,6 +87,7 @@ LIBC_SYSV_CALLS_A_DEPS := \
|
|||
$(call uniq,$(foreach x,$(LIBC_SYSV_CALLS_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_SYSV_CALLS_A): \
|
||||
libc/sysv/calls/ \
|
||||
$(LIBC_SYSV_CALLS_A).pkg \
|
||||
$(LIBC_SYSV_CALLS_A_OBJS)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- 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│
|
||||
/*-*- 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 │
|
||||
│ │
|
||||
|
@ -17,12 +17,32 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/**
|
||||
* Delegates to escapesh(), allocating as much memory as needed.
|
||||
* @return bytes written excluding NUL, or -1 on alloc error or overflow
|
||||
*/
|
||||
int aescapesh(char **escaped, const char *unescaped, unsigned length) {
|
||||
return aescape(escaped, 32, unescaped, length, escapesh);
|
||||
}
|
||||
/ Forks process without copying page tables.
|
||||
/
|
||||
/ This is the same as fork() except it's optimized for the case
|
||||
/ where the caller invokes exec() immediately afterwards.
|
||||
/
|
||||
/ @return pid of child process or 0 if forked process
|
||||
/ @returnstwice
|
||||
vfork: mov __NR_vfork(%rip),%eax
|
||||
cmp $-1,%eax
|
||||
je systemfive.enosys
|
||||
pop %rsi
|
||||
testb IsBsd()
|
||||
jnz vfork.bsd
|
||||
syscall
|
||||
push %rsi
|
||||
cmp $-4095,%rax
|
||||
jae systemfive.error
|
||||
ret
|
||||
.endfn vfork,globl
|
||||
|
||||
vfork.bsd:
|
||||
syscall
|
||||
push %rsi
|
||||
jc systemfive.errno
|
||||
ret
|
||||
.endfn vfork.bsd
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/color.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
|
|
|
@ -17,52 +17,65 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/escape/escape.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
|
||||
/**
|
||||
* Escapes memory for inclusion in C string literals (or Python, etc.)
|
||||
* Returns monospace display width of UTF-8 string.
|
||||
*
|
||||
* The outer quotation marks are *not* added.
|
||||
* - Control codes are discounted
|
||||
* - ANSI escape sequences are discounted
|
||||
* - East asian glyphs, emoji, etc. count as two
|
||||
*
|
||||
* @param buf is the output area, which can't overlap and, no matter
|
||||
* what, a NUL-terminator will always be placed in the buffer at
|
||||
* an appropriate place, provided buf!=NULL && size!=0
|
||||
* @param size is the byte-length of the output area
|
||||
* @param s is the data, which may have NUL characters
|
||||
* @param l is the byte-length of s or -1 if s is NUL-terminated
|
||||
* @return number of characters written, excluding NUL terminator; or,
|
||||
* if the output buffer wasn't passed, or was too short, then the
|
||||
* number of characters that *would* have been written is returned;
|
||||
* since that's how the snprintf() API works; or -1 on overflow
|
||||
* @see xaescapec() for an easier api
|
||||
* @param s is NUL-terminated string
|
||||
* @param n is max bytes to consider
|
||||
* @return monospace display width
|
||||
*/
|
||||
int escapec(char *buf, unsigned size, const char *s, unsigned l) {
|
||||
if (l >= INT_MAX) return eoverflow();
|
||||
unsigned i, j = 0;
|
||||
for (i = 0; i < l; ++i) {
|
||||
unsigned t = cescapec(s[i]);
|
||||
if (t) {
|
||||
while (t) {
|
||||
if (j < size) {
|
||||
buf[j] = (unsigned char)t;
|
||||
t >>= 8;
|
||||
}
|
||||
j++;
|
||||
int strnwidth(const char *s, size_t n) {
|
||||
wint_t c, w;
|
||||
unsigned l, r;
|
||||
enum { kAscii, kUtf8, kEsc, kCsi } t;
|
||||
for (w = r = t = l = 0; n--;) {
|
||||
if ((c = *s++ & 0xff)) {
|
||||
switch (t) {
|
||||
case kAscii:
|
||||
if (0x20 <= c && c <= 0x7E || c == '\t') {
|
||||
++l;
|
||||
} else if (c == 033) {
|
||||
t = kEsc;
|
||||
} else if (c >= 0300) {
|
||||
t = kUtf8;
|
||||
w = ThomPikeByte(c);
|
||||
r = ThomPikeLen(c) - 1;
|
||||
}
|
||||
break;
|
||||
case kUtf8:
|
||||
if (ThomPikeCont(c)) {
|
||||
w = ThomPikeMerge(w, c);
|
||||
if (--r) break;
|
||||
}
|
||||
l += MAX(0, wcwidth(w));
|
||||
t = kAscii;
|
||||
break;
|
||||
case kEsc:
|
||||
if (c == '[') {
|
||||
t = kCsi;
|
||||
} else if (!(040 <= c && c < 060)) {
|
||||
t = kAscii;
|
||||
}
|
||||
break;
|
||||
case kCsi:
|
||||
if (!(060 <= c && c < 0100)) {
|
||||
t = kAscii;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
} else {
|
||||
if (l == -1) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buf && size) {
|
||||
if (j < size) {
|
||||
buf[j] = '\0';
|
||||
} else {
|
||||
buf[size - 1] = '\0';
|
||||
}
|
||||
}
|
||||
return j;
|
||||
return l;
|
||||
}
|
|
@ -17,56 +17,18 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpdecode.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
|
||||
#define kOneTrueTabWidth 8
|
||||
|
||||
/**
|
||||
* Returns monospace display width in UTF-8 string.
|
||||
* Returns monospace display width of UTF-8 string.
|
||||
*
|
||||
* - Control codes are discounted
|
||||
* - ANSI escape sequences are discounted
|
||||
* - East asian glyphs, emoji, etc. count as two
|
||||
*
|
||||
* @param s is NUL-terminated string
|
||||
* @return monospace display width
|
||||
*/
|
||||
int(strwidth)(const char *s) {
|
||||
return strnwidth(s, SIZE_MAX);
|
||||
}
|
||||
|
||||
int(strnwidth)(const char *s, size_t n) {
|
||||
/* TODO(jart): Fix this function. */
|
||||
size_t l;
|
||||
wint_t wc;
|
||||
const unsigned char *p, *pe;
|
||||
l = 0;
|
||||
if (n) {
|
||||
p = (const unsigned char *)s;
|
||||
pe = (const unsigned char *)(n == SIZE_MAX ? INTPTR_MAX : (intptr_t)s + n);
|
||||
for (;;) {
|
||||
while (p < pe && iscont(*p)) p++;
|
||||
if (p == pe || !*p) break;
|
||||
if (*p == L'\t') {
|
||||
if (l & (kOneTrueTabWidth - 1)) {
|
||||
l += kOneTrueTabWidth - (l & (kOneTrueTabWidth - 1));
|
||||
} else {
|
||||
l += kOneTrueTabWidth;
|
||||
}
|
||||
++p;
|
||||
} else if (*p == L'\e') {
|
||||
while (++p < pe && *p) {
|
||||
if (*p == '[' || *p == ';' || isdigit(*p)) {
|
||||
continue;
|
||||
} else {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p += abs(tpdecode((const char *)p, &wc));
|
||||
l += max(0, wcwidth(wc));
|
||||
}
|
||||
}
|
||||
}
|
||||
return l;
|
||||
int strwidth(const char *s) {
|
||||
return strnwidth(s, -1);
|
||||
}
|
||||
|
|
|
@ -3,19 +3,6 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § characters » unicode ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
extern const uint8_t kEastAsianWidth[];
|
||||
extern const uint32_t kEastAsianWidthBits;
|
||||
extern const uint8_t kCombiningChars[];
|
||||
extern const uint32_t kCombiningCharsBits;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » multibyte » unicode ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
int wcwidth(wchar_t) pureconst;
|
||||
int wcswidth(const wchar_t *) strlenesque;
|
||||
int wcsnwidth(const wchar_t *, size_t) strlenesque;
|
||||
|
@ -24,26 +11,6 @@ int strnwidth(const char *, size_t) strlenesque;
|
|||
int strwidth16(const char16_t *) strlenesque;
|
||||
int strnwidth16(const char16_t *, size_t) strlenesque;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § unicode » generic typing ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#if __STDC_VERSION__ + 0 >= 201112
|
||||
|
||||
#define strwidth(s) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcswidth, char16_t \
|
||||
: strwidth16, default \
|
||||
: strwidth)(s)
|
||||
|
||||
#define strnwidth(s, n) \
|
||||
_Generic(*(s), wchar_t \
|
||||
: wcswidth, char16_t \
|
||||
: strnwidth16, default \
|
||||
: strnwidth)(s, n)
|
||||
|
||||
#endif /* C11 */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_UNICODE_UNICODE_H_ */
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/unicode/unicode.h"
|
||||
|
||||
extern const uint8_t kEastAsianWidth[];
|
||||
extern const uint32_t kEastAsianWidthBits;
|
||||
extern const uint8_t kCombiningChars[];
|
||||
extern const uint32_t kCombiningCharsBits;
|
||||
|
||||
/**
|
||||
* Returns cell width of monospace character.
|
||||
*/
|
||||
|
|
|
@ -68,11 +68,6 @@ char *xstrcat(const char *, ...) paramsnonnull((1)) nullterminated() _XMAL;
|
|||
char *xstrmul(const char *, size_t) paramsnonnull((1)) _XMAL;
|
||||
char *xjoinpaths(const char *, const char *) paramsnonnull() _XMAL;
|
||||
char *xinet_ntop(int, const void *) _XPNN _XMAL;
|
||||
char *xaescapec(const char *) _XPNN _XMAL;
|
||||
char *xaescapesh(const char *) _XPNN _XMAL;
|
||||
char *xaescapeshq(const char *) _XPNN _XMAL;
|
||||
char *xaescape(const char *, int (*)(char *, unsigned, const char *,
|
||||
unsigned)) _XPNN hidden _XMAL;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § eXtended apis » time ─╬─│┼
|
||||
|
|
|
@ -35,7 +35,6 @@ LIBC_X_A_CHECKS = \
|
|||
|
||||
LIBC_X_A_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_ESCAPE \
|
||||
LIBC_FMT \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*-*- 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/escape/escape.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Delegates NUL-terminated string to escapec() or dies.
|
||||
*
|
||||
* The surrounding quotes are *not* included. Death hapens only on
|
||||
* allocation error or int32 overflow, which are extremely unlikely.
|
||||
*
|
||||
* @return escaped string which must make its way to free()
|
||||
*/
|
||||
char *xaescapec(const char *unescaped) { return xaescape(unescaped, escapec); }
|
|
@ -1,34 +0,0 @@
|
|||
/*-*- 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/escape/escape.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Delegates NUL-terminated string to escapesh() or dies.
|
||||
*
|
||||
* The surrounding single quotes are *not* included. Death hapens only
|
||||
* on allocation error or int32 overflow.
|
||||
*
|
||||
* @return escaped string which must make its way to free()
|
||||
* @see xaescapeshq() which adds quotes
|
||||
*/
|
||||
char *xaescapesh(const char *unescaped) {
|
||||
return xaescape(unescaped, escapesh);
|
||||
}
|
|
@ -38,6 +38,7 @@ NET_HTTP_A_DIRECTDEPS = \
|
|||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue