Add minor improvements and cleanup

main
Justine Tunney 2020-10-27 03:39:46 -07:00
parent 9e3e985ae5
commit feed0d2b0e
163 changed files with 2286 additions and 2245 deletions

View File

@ -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 # │

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -158,6 +158,5 @@ textstartup int ttyraw(enum TtyRawFlags flags) {
} else {
rc = ttyraw_disable();
}
cancolor();
return rc;
}

View File

@ -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"

View File

@ -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"

View File

@ -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",

View File

@ -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;

View File

@ -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__); \

View File

@ -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. */
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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

View File

@ -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 (;;) {

View File

@ -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;

View File

@ -23,5 +23,5 @@
onntconsoleevent$nt:
ezlea onntconsoleevent,ax
jmp nt2sysv
jmp __nt2sysv
.endfn onntconsoleevent$nt,globl,hidden

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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.
/

View File

@ -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(),

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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)

View File

@ -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;
}

View File

@ -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
*

View File

@ -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"

View File

@ -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;

View File

@ -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));

View File

@ -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;
}

View File

@ -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(" ");

20
libc/log/color.h 100644
View File

@ -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_ */

View File

@ -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) */

View File

@ -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);

View File

@ -32,7 +32,6 @@ LIBC_LOG_A_DIRECTDEPS = \
LIBC_CALLS_HEFTY \
LIBC_CONV \
LIBC_ELF \
LIBC_ESCAPE \
LIBC_FMT \
LIBC_TINYMATH \
LIBC_NEXGEN32E \

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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]);
}
}

View File

@ -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);
}

View File

@ -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(": ");

View File

@ -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";

View File

@ -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"

View File

@ -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"

View File

@ -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;
}

View File

@ -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"

View File

@ -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"

View File

@ -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);
}

View File

@ -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__

View 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

View File

@ -29,6 +29,7 @@ LIBC_RAND_A_DIRECTDEPS = \
LIBC_TINYMATH \
LIBC_NEXGEN32E \
LIBC_NT_KERNELBASE \
LIBC_STR \
LIBC_SYSV_CALLS \
LIBC_SYSV

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -29,7 +29,6 @@ LIBC_STDIO_A_DIRECTDEPS = \
LIBC_BITS \
LIBC_CALLS \
LIBC_CONV \
LIBC_ESCAPE \
LIBC_FMT \
LIBC_MEM \
LIBC_NEXGEN32E \

View File

@ -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"

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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
}

View File

@ -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 # MSB6 (0x7F)
.byte 0b00000000,1 # mark,len
/ 0b11000000 # mask
.endr
.rept 4 # MSB10 (0x7FF)
.byte 0b11000000,2 # mark,len
/ 0b11100000 # mask
.endr
.rept 5 # MSB15 (0xFFFF)
.byte 0b11100000,3 # mark,len
/ 0b11110000 # mask
.endr
.rept 5 # MSB20 (0x1FFFFF)
.byte 0b11110000,4 # mark,len
/ 0b11111000 # mask
.endr
.rept 5 # MSB25 (0x3FFFFFF)
.byte 0b11111000,5 # mark,len
/ 0b11111100 # mask
.endr
.rept 6 # MSB31 (0xffffffff)
.byte 0b11111100,6 # mark,len
.endr
.endobj kTpDecoderRing,globl,hidden
.previous

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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)

View File

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.inc"
.scall vfork 0x004200422042003a globl

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,2 @@
.include "libc/sysv/consts/syscon.inc"
.syscon nr __NR_vfork 0x003a 0x2000042 0x0042 0x0042 -1

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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.
*/

View File

@ -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

View File

@ -35,7 +35,6 @@ LIBC_X_A_CHECKS = \
LIBC_X_A_DIRECTDEPS = \
LIBC_CALLS \
LIBC_ESCAPE \
LIBC_FMT \
LIBC_MEM \
LIBC_NEXGEN32E \

View File

@ -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); }

View File

@ -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);
}

View File

@ -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