mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 03:08:31 +00:00
Auto-generate some documentation
This commit is contained in:
parent
117d0111ab
commit
13437dd19b
97 changed files with 2033 additions and 661 deletions
6
third_party/chibicc/README.cosmo
vendored
6
third_party/chibicc/README.cosmo
vendored
|
@ -16,18 +16,22 @@ local enhancements
|
|||
- support __builtin_constant_p, __builtin_likely, etc.
|
||||
- support __builtin_isunordered, __builtin_islessgreater, etc.
|
||||
- support __builtin_ctz, __builtin_bswap, __builtin_popcount, etc.
|
||||
- support __force_align_arg_pointer__, __no_caller_saved_registers__, etc.
|
||||
- support __constructor__, __section__, __cold__, -ffunction-sections, etc.
|
||||
- support building -x assembler-with-cpp a.k.a. .S files
|
||||
- support profiling w/ -mcount / -mfentry / -mnop-mcount
|
||||
- improve error messages to trace macro expansions
|
||||
- reduce #lines of generated assembly by a third
|
||||
- reduce #bytes of generated binary by a third
|
||||
- report divide errors in constexprs
|
||||
|
||||
local bug fixes
|
||||
|
||||
- allow casted values to be lvalues
|
||||
- permit remainder operator in constexprs
|
||||
- permit parentheses around string-initializer
|
||||
- fix 64-bit bug in generated code for struct bitfields
|
||||
- fix struct_designator() so it won't crash on anonymous union members
|
||||
- fix bug where last statement in statement expression couldn't have label
|
||||
- print_tokens (chibicc -E) now works in the case of adjacent string literals
|
||||
- make enums unsigned (like gcc) so we don't suffer the msvc enum bitfield bug
|
||||
|
@ -35,6 +39,8 @@ local bug fixes
|
|||
local changes
|
||||
|
||||
- use tabs in generated output
|
||||
- parse javadoc-style markdown comments
|
||||
- don't fold backslash newline in comments
|
||||
- generated code no longer assumes red zone
|
||||
- emit .size directives for function definitions
|
||||
- use fisttp long double conversions if built w/ -msse3
|
||||
|
|
184
third_party/chibicc/as.c
vendored
184
third_party/chibicc/as.c
vendored
|
@ -177,8 +177,8 @@ struct As {
|
|||
struct Sauces {
|
||||
unsigned long n;
|
||||
struct Sauce {
|
||||
int path; // strings
|
||||
int line; // 1-indexed
|
||||
unsigned path; // strings
|
||||
unsigned line; // 1-indexed
|
||||
} * p;
|
||||
} sauces;
|
||||
struct Things {
|
||||
|
@ -192,14 +192,14 @@ struct As {
|
|||
TT_FORWARD,
|
||||
TT_BACKWARD,
|
||||
} t : 4;
|
||||
int s : 28; // sauces
|
||||
int i; // identity,ints,floats,slices
|
||||
unsigned s : 28; // sauces
|
||||
unsigned i; // identity,ints,floats,slices
|
||||
} * p;
|
||||
} things;
|
||||
struct Sections {
|
||||
unsigned long n;
|
||||
struct Section {
|
||||
int name; // strings
|
||||
unsigned name; // strings
|
||||
int flags;
|
||||
int type;
|
||||
int align;
|
||||
|
@ -210,11 +210,11 @@ struct As {
|
|||
unsigned long n;
|
||||
struct Symbol {
|
||||
bool isused;
|
||||
int name; // slices
|
||||
int section; // sections
|
||||
int stb; // STB_*
|
||||
int stv; // STV_*
|
||||
int type; // STT_*
|
||||
unsigned char stb; // STB_*
|
||||
unsigned char stv; // STV_*
|
||||
unsigned char type; // STT_*
|
||||
unsigned name; // slices
|
||||
unsigned section; // sections
|
||||
long offset;
|
||||
long size;
|
||||
struct ElfWriterSymRef ref;
|
||||
|
@ -223,25 +223,25 @@ struct As {
|
|||
struct HashTable {
|
||||
unsigned i, n;
|
||||
struct HashEntry {
|
||||
int h;
|
||||
int i;
|
||||
unsigned h;
|
||||
unsigned i;
|
||||
} * p;
|
||||
} symbolindex;
|
||||
struct Labels {
|
||||
unsigned long n;
|
||||
struct Label {
|
||||
int id;
|
||||
int tok; // things
|
||||
int symbol; // symbols
|
||||
unsigned id;
|
||||
unsigned tok; // things
|
||||
unsigned symbol; // symbols
|
||||
} * p;
|
||||
} labels;
|
||||
struct Relas {
|
||||
unsigned long n;
|
||||
struct Rela {
|
||||
bool isdead;
|
||||
int kind; // R_X86_64_{16,32,64,PC8,PC32,PLT32,GOTPCRELX,...}
|
||||
int expr; // exprs
|
||||
int section; // sections
|
||||
int kind; // R_X86_64_{16,32,64,PC8,PC32,PLT32,GOTPCRELX,...}
|
||||
unsigned expr; // exprs
|
||||
unsigned section; // sections
|
||||
long offset;
|
||||
long addend;
|
||||
} * p;
|
||||
|
@ -251,7 +251,7 @@ struct As {
|
|||
struct Expr {
|
||||
enum ExprKind {
|
||||
EX_INT, // integer
|
||||
EX_SYM, // slice, forward, backward, then symbol
|
||||
EX_SYM, // things (then symbols after eval)
|
||||
EX_NEG, // unary -
|
||||
EX_NOT, // unary !
|
||||
EX_BITNOT, // unary ~
|
||||
|
@ -276,7 +276,7 @@ struct As {
|
|||
EM_DTPOFF,
|
||||
EM_TPOFF,
|
||||
} em;
|
||||
int tok;
|
||||
unsigned tok;
|
||||
int lhs;
|
||||
int rhs;
|
||||
long x;
|
||||
|
@ -456,7 +456,7 @@ static bool EndsWith(const char *s, const char *suffix) {
|
|||
n = strlen(s);
|
||||
m = strlen(suffix);
|
||||
if (m > n) return false;
|
||||
return memcmp(s + n - m, suffix, m) == 0;
|
||||
return !memcmp(s + n - m, suffix, m);
|
||||
}
|
||||
|
||||
static char *Format(const char *fmt, ...) {
|
||||
|
@ -1192,21 +1192,21 @@ static int ParseMul(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '*')) {
|
||||
y = ParseUnary(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x *= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_MUL, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '/')) {
|
||||
y = ParseUnary(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x /= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_DIV, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '%')) {
|
||||
y = ParseUnary(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x %= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_REM, x, y);
|
||||
|
@ -1225,14 +1225,14 @@ static int ParseAdd(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '+')) {
|
||||
y = ParseMul(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x += a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_ADD, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '-')) {
|
||||
y = ParseMul(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x -= a->exprs.p[y].x;
|
||||
} else if (a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[y].x = -a->exprs.p[y].x;
|
||||
|
@ -1254,14 +1254,14 @@ static int ParseShift(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '<' << 8 | '<')) {
|
||||
y = ParseAdd(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x <<= a->exprs.p[y].x & 63;
|
||||
} else {
|
||||
x = NewBinary(a, EX_SHL, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '>' << 8 | '>')) {
|
||||
y = ParseAdd(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x >>= a->exprs.p[y].x & 63;
|
||||
} else {
|
||||
x = NewBinary(a, EX_SHR, x, y);
|
||||
|
@ -1280,28 +1280,28 @@ static int ParseRelational(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '<')) {
|
||||
y = ParseShift(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x = a->exprs.p[x].x < a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_LT, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '>')) {
|
||||
y = ParseShift(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x = a->exprs.p[y].x < a->exprs.p[x].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_LT, y, x);
|
||||
}
|
||||
} else if (IsPunct(a, i, '<' << 8 | '=')) {
|
||||
y = ParseShift(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x = a->exprs.p[x].x <= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_LE, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '>' << 8 | '=')) {
|
||||
y = ParseShift(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x = a->exprs.p[y].x <= a->exprs.p[x].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_LE, y, x);
|
||||
|
@ -1320,14 +1320,14 @@ static int ParseEquality(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '=' << 8 | '=')) {
|
||||
y = ParseRelational(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x = a->exprs.p[x].x == a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_EQ, x, y);
|
||||
}
|
||||
} else if (IsPunct(a, i, '!' << 8 | '=')) {
|
||||
y = ParseRelational(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x = a->exprs.p[x].x != a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_NE, x, y);
|
||||
|
@ -1346,7 +1346,7 @@ static int ParseAnd(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '&')) {
|
||||
y = ParseEquality(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x &= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_AND, x, y);
|
||||
|
@ -1365,7 +1365,7 @@ static int ParseXor(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '^')) {
|
||||
y = ParseAnd(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x ^= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_XOR, x, y);
|
||||
|
@ -1384,7 +1384,7 @@ static int ParseOr(struct As *a, int *rest, int i) {
|
|||
for (;;) {
|
||||
if (IsPunct(a, i, '|')) {
|
||||
y = ParseXor(a, &i, i + 1);
|
||||
if (a->exprs.p[x].kind == EX_INT || a->exprs.p[y].kind == EX_INT) {
|
||||
if (a->exprs.p[x].kind == EX_INT && a->exprs.p[y].kind == EX_INT) {
|
||||
a->exprs.p[x].x |= a->exprs.p[y].x;
|
||||
} else {
|
||||
x = NewBinary(a, EX_OR, x, y);
|
||||
|
@ -3745,8 +3745,7 @@ static int ResolveSymbol(struct As *a, int i) {
|
|||
case TT_FORWARD:
|
||||
return FindLabelForward(a, a->ints.p[a->things.p[i].i]);
|
||||
default:
|
||||
DebugBreak();
|
||||
Fail(a, "this corruption");
|
||||
Fail(a, "this corruption %d", a->things.p[i].t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3777,15 +3776,6 @@ static void Write32(char b[4], int x) {
|
|||
b[3] = x >> 030;
|
||||
}
|
||||
|
||||
static void MarkUndefinedSymbolsGlobal(struct As *a) {
|
||||
int i;
|
||||
for (i = 0; i < a->symbols.n; ++i) {
|
||||
if (!a->symbols.p[i].section && a->symbols.p[i].stb == STB_LOCAL) {
|
||||
a->symbols.p[i].stb = STB_GLOBAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MarkUsedSymbols(struct As *a, int i) {
|
||||
if (i == -1) return;
|
||||
MarkUsedSymbols(a, a->exprs.p[i].lhs);
|
||||
|
@ -3818,6 +3808,16 @@ static void Evaluate(struct As *a) {
|
|||
}
|
||||
}
|
||||
|
||||
static void MarkUndefinedSymbolsGlobal(struct As *a) {
|
||||
int i;
|
||||
for (i = 0; i < a->symbols.n; ++i) {
|
||||
if (a->symbols.p[i].isused && !a->symbols.p[i].section &&
|
||||
a->symbols.p[i].stb == STB_LOCAL) {
|
||||
a->symbols.p[i].stb = STB_GLOBAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsLocal(struct As *a, int name) {
|
||||
if (name < 0) return true;
|
||||
return a->slices.p[name].n >= 2 && !memcmp(a->slices.p[name].p, ".L", 2);
|
||||
|
@ -3829,17 +3829,18 @@ static bool IsLiveSymbol(struct As *a, int i) {
|
|||
}
|
||||
|
||||
static void Objectify(struct As *a, int path) {
|
||||
int i, j, s;
|
||||
char *p;
|
||||
int i, j, s, e;
|
||||
struct ElfWriter *elf;
|
||||
elf = elfwriter_open(a->strings.p[path], 0644);
|
||||
for (i = 0; i < a->symbols.n; ++i) {
|
||||
if (!IsLiveSymbol(a, i)) continue;
|
||||
p = strndup(a->slices.p[a->symbols.p[i].name].p,
|
||||
a->slices.p[a->symbols.p[i].name].n);
|
||||
a->symbols.p[i].ref = elfwriter_appendsym(
|
||||
elf,
|
||||
strndup(a->slices.p[a->symbols.p[i].name].p,
|
||||
a->slices.p[a->symbols.p[i].name].n),
|
||||
ELF64_ST_INFO(a->symbols.p[i].stb, a->symbols.p[i].type),
|
||||
elf, p, ELF64_ST_INFO(a->symbols.p[i].stb, a->symbols.p[i].type),
|
||||
a->symbols.p[i].stv, a->symbols.p[i].offset, a->symbols.p[i].size);
|
||||
free(p);
|
||||
}
|
||||
for (i = 0; i < a->sections.n; ++i) {
|
||||
elfwriter_align(elf, a->sections.p[i].align, 0);
|
||||
|
@ -3853,24 +3854,24 @@ static void Objectify(struct As *a, int path) {
|
|||
for (j = 0; j < a->relas.n; ++j) {
|
||||
if (a->relas.p[j].isdead) continue;
|
||||
if (a->relas.p[j].section != i) continue;
|
||||
a->i = a->exprs.p[a->relas.p[j].expr].tok;
|
||||
switch (a->exprs.p[a->relas.p[j].expr].kind) {
|
||||
e = a->relas.p[j].expr;
|
||||
a->i = a->exprs.p[e].tok;
|
||||
switch (a->exprs.p[e].kind) {
|
||||
case EX_INT:
|
||||
break;
|
||||
case EX_SYM:
|
||||
elfwriter_appendrela(
|
||||
elf, a->relas.p[j].offset,
|
||||
a->symbols.p[a->exprs.p[a->relas.p[j].expr].x].ref,
|
||||
a->relas.p[j].kind, a->relas.p[j].addend);
|
||||
elfwriter_appendrela(elf, a->relas.p[j].offset,
|
||||
a->symbols.p[a->exprs.p[e].x].ref,
|
||||
a->relas.p[j].kind, a->relas.p[j].addend);
|
||||
break;
|
||||
case EX_ADD:
|
||||
if (a->exprs.p[a->exprs.p[j].lhs].kind == EX_SYM &&
|
||||
a->exprs.p[a->exprs.p[j].rhs].kind == EX_INT) {
|
||||
if (a->exprs.p[a->exprs.p[e].lhs].kind == EX_SYM &&
|
||||
a->exprs.p[a->exprs.p[e].rhs].kind == EX_INT) {
|
||||
elfwriter_appendrela(
|
||||
elf, a->relas.p[j].offset,
|
||||
a->symbols.p[a->exprs.p[a->exprs.p[j].lhs].x].ref,
|
||||
a->symbols.p[a->exprs.p[a->exprs.p[e].lhs].x].ref,
|
||||
a->relas.p[j].kind,
|
||||
a->relas.p[j].addend + a->exprs.p[a->exprs.p[j].rhs].x);
|
||||
a->relas.p[j].addend + a->exprs.p[a->exprs.p[e].rhs].x);
|
||||
} else {
|
||||
Fail(a, "bad addend");
|
||||
}
|
||||
|
@ -3887,6 +3888,58 @@ static void Objectify(struct As *a, int path) {
|
|||
elfwriter_close(elf);
|
||||
}
|
||||
|
||||
static void CheckIntegrity(struct As *a) {
|
||||
int i;
|
||||
for (i = 0; i < a->things.n; ++i) {
|
||||
CHECK_LT((int)a->things.p[i].s, a->sauces.n);
|
||||
switch (a->things.p[i].t) {
|
||||
case TT_INT:
|
||||
case TT_FORWARD:
|
||||
case TT_BACKWARD:
|
||||
CHECK_LT(a->things.p[i].i, a->ints.n);
|
||||
break;
|
||||
case TT_FLOAT:
|
||||
CHECK_LT(a->things.p[i].i, a->floats.n);
|
||||
break;
|
||||
case TT_SLICE:
|
||||
CHECK_LT(a->things.p[i].i, a->slices.n);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < a->sections.n; ++i) {
|
||||
CHECK_LT(a->sections.p[i].name, a->strings.n);
|
||||
}
|
||||
for (i = 0; i < a->symbols.n; ++i) {
|
||||
CHECK_LT(a->symbols.p[i].name, a->slices.n);
|
||||
CHECK_LT(a->symbols.p[i].section, a->sections.n);
|
||||
}
|
||||
for (i = 0; i < a->labels.n; ++i) {
|
||||
CHECK_LT(a->labels.p[i].tok, a->things.n);
|
||||
CHECK_LT(a->labels.p[i].symbol, a->symbols.n);
|
||||
}
|
||||
for (i = 0; i < a->relas.n; ++i) {
|
||||
CHECK_LT(a->relas.p[i].expr, a->exprs.n);
|
||||
CHECK_LT(a->relas.p[i].section, a->sections.n);
|
||||
}
|
||||
for (i = 0; i < a->exprs.n; ++i) {
|
||||
CHECK_LT(a->exprs.p[i].tok, a->things.n);
|
||||
if (a->exprs.p[i].lhs != -1) CHECK_LT(a->exprs.p[i].lhs, a->exprs.n);
|
||||
if (a->exprs.p[i].rhs != -1) CHECK_LT(a->exprs.p[i].rhs, a->exprs.n);
|
||||
switch (a->exprs.p[i].kind) {
|
||||
case EX_SYM:
|
||||
CHECK_LT(a->exprs.p[i].x, a->things.n);
|
||||
CHECK(a->things.p[a->exprs.p[i].x].t == TT_SLICE ||
|
||||
a->things.p[a->exprs.p[i].x].t == TT_FORWARD ||
|
||||
a->things.p[a->exprs.p[i].x].t == TT_BACKWARD);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintThings(struct As *a) {
|
||||
int i;
|
||||
char pbuf[4], fbuf[32];
|
||||
|
@ -3929,17 +3982,18 @@ void Assembler(int argc, char *argv[]) {
|
|||
Tokenize(a, a->inpath);
|
||||
/* PrintThings(a); */
|
||||
Assemble(a);
|
||||
/* CheckIntegrity(a); */
|
||||
Evaluate(a);
|
||||
MarkUndefinedSymbolsGlobal(a);
|
||||
Objectify(a, a->outpath);
|
||||
malloc_stats();
|
||||
/* malloc_stats(); */
|
||||
FreeAssembler(a);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
showcrashreports();
|
||||
if (argc == 1) {
|
||||
system("o//third_party/chibicc/as.com -o /tmp/o third_party/chibicc/hog.s");
|
||||
system("o//third_party/chibicc/as.com -o /tmp/o /home/jart/trash/hog.s");
|
||||
system("objdump -xwd /tmp/o");
|
||||
exit(0);
|
||||
}
|
||||
|
|
49
third_party/chibicc/chibicc.c
vendored
49
third_party/chibicc/chibicc.c
vendored
|
@ -32,6 +32,7 @@ bool opt_verbose;
|
|||
|
||||
static bool opt_A;
|
||||
static bool opt_E;
|
||||
static bool opt_J;
|
||||
static bool opt_M;
|
||||
static bool opt_MD;
|
||||
static bool opt_MMD;
|
||||
|
@ -202,6 +203,8 @@ static void parse_args(int argc, char **argv) {
|
|||
opt_c = true;
|
||||
} else if (!strcmp(argv[i], "-E")) {
|
||||
opt_E = true;
|
||||
} else if (!strcmp(argv[i], "-J")) {
|
||||
opt_J = true;
|
||||
} else if (!strcmp(argv[i], "-A")) {
|
||||
opt_A = true;
|
||||
} else if (!strcmp(argv[i], "-I")) {
|
||||
|
@ -364,7 +367,14 @@ static char *create_tmpfile(void) {
|
|||
return path;
|
||||
}
|
||||
|
||||
static void run_subprocess(char **argv) {
|
||||
static void handle_exit(bool ok) {
|
||||
if (!ok) {
|
||||
opt_save_temps = true;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static bool run_subprocess(char **argv) {
|
||||
// If -### is given, dump the subprocess's command line.
|
||||
if (opt_hash_hash_hash) {
|
||||
fprintf(stderr, "%s", argv[0]);
|
||||
|
@ -384,13 +394,10 @@ static void run_subprocess(char **argv) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (status != 0) {
|
||||
opt_save_temps = true;
|
||||
exit(1);
|
||||
}
|
||||
return !status;
|
||||
}
|
||||
|
||||
static void run_cc1(int argc, char **argv, char *input, char *output) {
|
||||
static bool run_cc1(int argc, char **argv, char *input, char *output) {
|
||||
char **args = calloc(argc + 10, sizeof(char *));
|
||||
memcpy(args, argv, argc * sizeof(char *));
|
||||
args[argc++] = "-cc1";
|
||||
|
@ -402,7 +409,7 @@ static void run_cc1(int argc, char **argv, char *input, char *output) {
|
|||
args[argc++] = "-cc1-output";
|
||||
args[argc++] = output;
|
||||
}
|
||||
run_subprocess(args);
|
||||
return run_subprocess(args);
|
||||
}
|
||||
|
||||
static void print_token(FILE *out, Token *tok) {
|
||||
|
@ -540,6 +547,10 @@ static void cc1(void) {
|
|||
print_ast(stdout, prog);
|
||||
return;
|
||||
}
|
||||
if (opt_J) {
|
||||
output_javadown(output_file, prog);
|
||||
return;
|
||||
}
|
||||
FILE *out = open_file(output_file);
|
||||
codegen(prog, out);
|
||||
fclose(out);
|
||||
|
@ -561,7 +572,7 @@ static void assemble(char *input, char *output) {
|
|||
strarray_push(&arr, "-o");
|
||||
strarray_push(&arr, output);
|
||||
strarray_push(&arr, NULL);
|
||||
run_subprocess(arr.data);
|
||||
handle_exit(run_subprocess(arr.data));
|
||||
}
|
||||
|
||||
static void run_linker(StringArray *inputs, char *output) {
|
||||
|
@ -591,7 +602,7 @@ static void run_linker(StringArray *inputs, char *output) {
|
|||
strarray_push(&arr, inputs->data[i]);
|
||||
}
|
||||
strarray_push(&arr, NULL);
|
||||
run_subprocess(arr.data);
|
||||
handle_exit(run_subprocess(arr.data));
|
||||
}
|
||||
|
||||
int chibicc(int argc, char **argv) {
|
||||
|
@ -608,6 +619,7 @@ int chibicc(int argc, char **argv) {
|
|||
error("cannot specify '-o' with '-c,' '-S' or '-E' with multiple files");
|
||||
}
|
||||
StringArray ld_args = {};
|
||||
StringArray dox_args = {};
|
||||
for (int i = 0; i < input_paths.len; i++) {
|
||||
char *input = input_paths.data[i];
|
||||
if (!strncmp(input, "-l", 2)) {
|
||||
|
@ -647,25 +659,33 @@ int chibicc(int argc, char **argv) {
|
|||
assert(type == FILE_C || type == FILE_ASM_CPP);
|
||||
// Just preprocess
|
||||
if (opt_E || opt_M) {
|
||||
run_cc1(argc, argv, input, NULL);
|
||||
handle_exit(run_cc1(argc, argv, input, NULL));
|
||||
continue;
|
||||
}
|
||||
// Compile
|
||||
if (opt_S) {
|
||||
run_cc1(argc, argv, input, output);
|
||||
handle_exit(run_cc1(argc, argv, input, output));
|
||||
continue;
|
||||
}
|
||||
// Compile and assemble
|
||||
if (opt_c) {
|
||||
char *tmp = create_tmpfile();
|
||||
run_cc1(argc, argv, input, tmp);
|
||||
handle_exit(run_cc1(argc, argv, input, tmp));
|
||||
assemble(tmp, output);
|
||||
continue;
|
||||
}
|
||||
// Dox
|
||||
if (opt_J) {
|
||||
char *tmp = create_tmpfile();
|
||||
if (run_cc1(argc, argv, input, tmp)) {
|
||||
strarray_push(&dox_args, tmp);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Compile, assemble and link
|
||||
char *tmp1 = create_tmpfile();
|
||||
char *tmp2 = create_tmpfile();
|
||||
run_cc1(argc, argv, input, tmp1);
|
||||
handle_exit(run_cc1(argc, argv, input, tmp1));
|
||||
assemble(tmp1, tmp2);
|
||||
strarray_push(&ld_args, tmp2);
|
||||
continue;
|
||||
|
@ -673,5 +693,8 @@ int chibicc(int argc, char **argv) {
|
|||
if (ld_args.len > 0) {
|
||||
run_linker(&ld_args, opt_o ? opt_o : "a.out");
|
||||
}
|
||||
if (dox_args.len > 0) {
|
||||
drop_dox(&dox_args, opt_o ? opt_o : "/dev/stdout");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
56
third_party/chibicc/chibicc.h
vendored
56
third_party/chibicc/chibicc.h
vendored
|
@ -26,6 +26,7 @@
|
|||
#include "libc/unicode/unicode.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "tool/build/lib/javadown.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -35,7 +36,10 @@ typedef struct Asm Asm;
|
|||
typedef struct AsmOperand AsmOperand;
|
||||
typedef struct File File;
|
||||
typedef struct FpClassify FpClassify;
|
||||
typedef struct HashMap HashMap;
|
||||
typedef struct Hideset Hideset;
|
||||
typedef struct Macro Macro;
|
||||
typedef struct MacroParam MacroParam;
|
||||
typedef struct Member Member;
|
||||
typedef struct Node Node;
|
||||
typedef struct Obj Obj;
|
||||
|
@ -47,6 +51,8 @@ typedef struct Token Token;
|
|||
typedef struct TokenStack TokenStack;
|
||||
typedef struct Type Type;
|
||||
|
||||
typedef Token *macro_handler_fn(Token *);
|
||||
|
||||
//
|
||||
// strarray.c
|
||||
//
|
||||
|
@ -64,13 +70,14 @@ void strarray_push(StringArray *, char *);
|
|||
//
|
||||
|
||||
typedef enum {
|
||||
TK_IDENT, // Identifiers
|
||||
TK_PUNCT, // Punctuators
|
||||
TK_KEYWORD, // Keywords
|
||||
TK_STR, // String literals
|
||||
TK_NUM, // Numeric literals
|
||||
TK_PP_NUM, // Preprocessing numbers
|
||||
TK_EOF, // End-of-file markers
|
||||
TK_IDENT, // Identifiers
|
||||
TK_PUNCT, // Punctuators
|
||||
TK_KEYWORD, // Keywords
|
||||
TK_STR, // String literals
|
||||
TK_NUM, // Numeric literals
|
||||
TK_PP_NUM, // Preprocessing numbers
|
||||
TK_JAVADOWN, // /** ... */ comments
|
||||
TK_EOF, // End-of-file markers
|
||||
} TokenKind;
|
||||
|
||||
struct File {
|
||||
|
@ -80,6 +87,7 @@ struct File {
|
|||
// For #line directive
|
||||
char *display_name;
|
||||
int line_delta;
|
||||
struct Javadown *javadown;
|
||||
};
|
||||
|
||||
struct thatispacked Token {
|
||||
|
@ -96,6 +104,7 @@ struct thatispacked Token {
|
|||
char *filename; // Filename
|
||||
Hideset *hideset; // For macro expansion
|
||||
Token *origin; // If this is expanded from a macro, the original token
|
||||
struct Javadown *javadown;
|
||||
union {
|
||||
int64_t val; // If kind is TK_NUM, its value
|
||||
long double fval; // If kind is TK_NUM, its value
|
||||
|
@ -134,6 +143,23 @@ int read_escaped_char(char **, char *);
|
|||
// preprocess.c
|
||||
//
|
||||
|
||||
struct MacroParam {
|
||||
MacroParam *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct Macro {
|
||||
char *name;
|
||||
bool is_objlike; // Object-like or function-like
|
||||
MacroParam *params;
|
||||
char *va_args_name;
|
||||
Token *body;
|
||||
macro_handler_fn *handler;
|
||||
Token *javadown;
|
||||
};
|
||||
|
||||
extern HashMap macros;
|
||||
|
||||
char *search_include_paths(char *);
|
||||
void init_macros(void);
|
||||
void define_macro(char *, char *);
|
||||
|
@ -232,6 +258,7 @@ struct Obj {
|
|||
char *asmname;
|
||||
char *section;
|
||||
char *visibility;
|
||||
Token *javadown;
|
||||
// Global variable
|
||||
bool is_tentative;
|
||||
bool is_string_literal;
|
||||
|
@ -244,6 +271,9 @@ struct Obj {
|
|||
bool is_noreturn;
|
||||
bool is_destructor;
|
||||
bool is_constructor;
|
||||
bool is_ms_abi; /* TODO */
|
||||
bool is_force_align_arg_pointer;
|
||||
bool is_no_caller_saved_registers;
|
||||
int stack_size;
|
||||
Obj *params;
|
||||
Node *body;
|
||||
|
@ -419,6 +449,7 @@ struct Type {
|
|||
int align; // alignment
|
||||
bool is_unsigned; // unsigned or signed
|
||||
bool is_atomic; // true if _Atomic
|
||||
bool is_ms_abi; // microsoft abi
|
||||
Type *origin; // for type compatibility check
|
||||
// Pointer-to or array-of type. We intentionally use the same member
|
||||
// to represent pointer/array duality in C.
|
||||
|
@ -534,11 +565,11 @@ typedef struct {
|
|||
void *val;
|
||||
} HashEntry;
|
||||
|
||||
typedef struct {
|
||||
struct HashMap {
|
||||
HashEntry *buckets;
|
||||
int capacity;
|
||||
int used;
|
||||
} HashMap;
|
||||
};
|
||||
|
||||
void *hashmap_get(HashMap *, char *);
|
||||
void *hashmap_get2(HashMap *, char *, int);
|
||||
|
@ -584,6 +615,13 @@ Token *alloc_token(void);
|
|||
Obj *alloc_obj(void);
|
||||
Type *alloc_type(void);
|
||||
|
||||
//
|
||||
// javadown.c
|
||||
//
|
||||
|
||||
void output_javadown(const char *, Obj *);
|
||||
void drop_dox(const StringArray *, const char *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_CHIBICC_CHIBICC_H_ */
|
||||
|
|
1
third_party/chibicc/chibicc.mk
vendored
1
third_party/chibicc/chibicc.mk
vendored
|
@ -49,6 +49,7 @@ THIRD_PARTY_CHIBICC_A_CHECKS = \
|
|||
$(THIRD_PARTY_CHIBICC_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
THIRD_PARTY_CHIBICC_A_DIRECTDEPS = \
|
||||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_CALLS_HEFTY \
|
||||
|
|
36
third_party/chibicc/codegen.c
vendored
36
third_party/chibicc/codegen.c
vendored
|
@ -2265,7 +2265,7 @@ static void emit_data(Obj *prog) {
|
|||
}
|
||||
}
|
||||
|
||||
static void store_fp(int r, int offset, int sz) {
|
||||
static void store_fp(Obj *fn, int r, int offset, int sz) {
|
||||
switch (sz) {
|
||||
case 4:
|
||||
println("\tmovss\t%%xmm%d,%d(%%rbp)", r, offset);
|
||||
|
@ -2274,7 +2274,8 @@ static void store_fp(int r, int offset, int sz) {
|
|||
println("\tmovsd\t%%xmm%d,%d(%%rbp)", r, offset);
|
||||
return;
|
||||
case 16:
|
||||
println("\tmovaps\t%%xmm%d,%d(%%rbp)", r, offset);
|
||||
println("\t%s\t%%xmm%d,%d(%%rbp)",
|
||||
fn->is_force_align_arg_pointer ? "movups" : "movaps", r, offset);
|
||||
return;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -2381,13 +2382,13 @@ static void emit_text(Obj *prog) {
|
|||
case TY_UNION:
|
||||
assert(ty->size <= 16);
|
||||
if (has_flonum(ty, 0, 8, 0)) {
|
||||
store_fp(fp++, var->offset, MIN(8, ty->size));
|
||||
store_fp(fn, fp++, var->offset, MIN(8, ty->size));
|
||||
} else {
|
||||
store_gp(gp++, var->offset, MIN(8, ty->size));
|
||||
}
|
||||
if (ty->size > 8) {
|
||||
if (has_flonum(ty, 8, 16, 0)) {
|
||||
store_fp(fp++, var->offset + 8, ty->size - 8);
|
||||
store_fp(fn, fp++, var->offset + 8, ty->size - 8);
|
||||
} else {
|
||||
store_gp(gp++, var->offset + 8, ty->size - 8);
|
||||
}
|
||||
|
@ -2395,7 +2396,7 @@ static void emit_text(Obj *prog) {
|
|||
break;
|
||||
case TY_FLOAT:
|
||||
case TY_DOUBLE:
|
||||
store_fp(fp++, var->offset, ty->size);
|
||||
store_fp(fn, fp++, var->offset, ty->size);
|
||||
break;
|
||||
case TY_INT128:
|
||||
store_gp(gp++, var->offset + 0, 8);
|
||||
|
@ -2405,6 +2406,20 @@ static void emit_text(Obj *prog) {
|
|||
store_gp(gp++, var->offset, ty->size);
|
||||
}
|
||||
}
|
||||
if (fn->is_force_align_arg_pointer) {
|
||||
emitlin("\tand\t$-16,%rsp");
|
||||
}
|
||||
if (fn->is_no_caller_saved_registers) {
|
||||
emitlin("\
|
||||
\tpush\t%rdi\n\
|
||||
\tpush\t%rsi\n\
|
||||
\tpush\t%rdx\n\
|
||||
\tpush\t%rcx\n\
|
||||
\tpush\t%r8\n\
|
||||
\tpush\t%r9\n\
|
||||
\tpush\t%r10\n\
|
||||
\tpush\t%r11");
|
||||
}
|
||||
// Emit code
|
||||
gen_stmt(fn->body);
|
||||
assert(!depth);
|
||||
|
@ -2420,6 +2435,17 @@ static void emit_text(Obj *prog) {
|
|||
if (fn->is_noreturn) {
|
||||
emitlin("\tud2");
|
||||
} else {
|
||||
if (fn->is_no_caller_saved_registers) {
|
||||
emitlin("\
|
||||
\tpop\t%r11\n\
|
||||
\tpop\t%r10\n\
|
||||
\tpop\t%r9\n\
|
||||
\tpop\t%r8\n\
|
||||
\tpop\t%rcx\n\
|
||||
\tpop\t%rdx\n\
|
||||
\tpop\t%rsi\n\
|
||||
\tpop\t%rdi");
|
||||
}
|
||||
emitlin("\tleave");
|
||||
emitlin("\tret");
|
||||
}
|
||||
|
|
248
third_party/chibicc/dox1.c
vendored
Normal file
248
third_party/chibicc/dox1.c
vendored
Normal file
|
@ -0,0 +1,248 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
#define APPEND(L) L.p = realloc(L.p, ++L.n * sizeof(*L.p))
|
||||
|
||||
struct DoxWriter {
|
||||
struct Buffer {
|
||||
size_t n;
|
||||
char *p;
|
||||
} buf;
|
||||
struct Macros {
|
||||
size_t n;
|
||||
Macro **p;
|
||||
} macros;
|
||||
struct Objects {
|
||||
size_t n;
|
||||
Obj **p;
|
||||
} objects;
|
||||
};
|
||||
|
||||
static void SerializeData(struct Buffer *buf, const void *p, unsigned long n) {
|
||||
struct Slice *s;
|
||||
buf->p = realloc(buf->p, buf->n + n);
|
||||
memcpy(buf->p + buf->n, p, n);
|
||||
buf->n += n;
|
||||
}
|
||||
|
||||
static int SerializeInt(struct Buffer *buf, int x) {
|
||||
unsigned char b[4];
|
||||
b[0] = x >> 000;
|
||||
b[1] = x >> 010;
|
||||
b[2] = x >> 020;
|
||||
b[3] = x >> 030;
|
||||
SerializeData(buf, b, 4);
|
||||
return x;
|
||||
}
|
||||
|
||||
static void SerializeStr(struct Buffer *buf, const char *s) {
|
||||
size_t n;
|
||||
if (!s) s = "";
|
||||
n = strlen(s);
|
||||
n = MIN(INT_MAX, n);
|
||||
SerializeInt(buf, n);
|
||||
SerializeData(buf, s, n);
|
||||
}
|
||||
|
||||
static void SerializeJavadown(struct Buffer *buf, struct Javadown *jd) {
|
||||
int i;
|
||||
SerializeInt(buf, jd->isfileoverview);
|
||||
SerializeStr(buf, jd->title);
|
||||
SerializeStr(buf, jd->text);
|
||||
SerializeInt(buf, jd->tags.n);
|
||||
for (i = 0; i < jd->tags.n; ++i) {
|
||||
SerializeStr(buf, jd->tags.p[i].tag);
|
||||
SerializeStr(buf, jd->tags.p[i].text);
|
||||
}
|
||||
}
|
||||
|
||||
static char *DescribeScalar(struct Type *ty, char *name) {
|
||||
return xasprintf("%s%s%s", ty->is_atomic ? "_Atomic " : "",
|
||||
ty->is_unsigned ? "unsigned " : "", name);
|
||||
}
|
||||
|
||||
static char *DescribeType(struct Type *ty) {
|
||||
switch (ty->kind) {
|
||||
case TY_VOID:
|
||||
return strdup("void");
|
||||
case TY_BOOL:
|
||||
return strdup("_Bool");
|
||||
case TY_CHAR:
|
||||
return DescribeScalar(ty, "char");
|
||||
case TY_SHORT:
|
||||
return DescribeScalar(ty, "short");
|
||||
case TY_INT:
|
||||
return DescribeScalar(ty, "int");
|
||||
case TY_LONG:
|
||||
return DescribeScalar(ty, "long");
|
||||
case TY_INT128:
|
||||
return DescribeScalar(ty, "__int128");
|
||||
case TY_FLOAT:
|
||||
return DescribeScalar(ty, "float");
|
||||
case TY_DOUBLE:
|
||||
return DescribeScalar(ty, "double");
|
||||
case TY_LDOUBLE:
|
||||
return DescribeScalar(ty, "long double");
|
||||
case TY_PTR:
|
||||
return xasprintf("%s*", gc(DescribeType(ty->base)));
|
||||
case TY_ARRAY:
|
||||
return xasprintf("%s[%d]", gc(DescribeType(ty->base)), ty->array_len);
|
||||
case TY_ENUM:
|
||||
if (ty->name_pos) {
|
||||
return xasprintf("enum %.*s", ty->name_pos->len, ty->name_pos->loc);
|
||||
} else {
|
||||
return strdup("ANONYMOUS-ENUM");
|
||||
}
|
||||
case TY_STRUCT:
|
||||
if (ty->name_pos) {
|
||||
return xasprintf("struct %.*s", ty->name_pos->len, ty->name_pos->loc);
|
||||
} else {
|
||||
return strdup("ANONYMOUS-STRUCT");
|
||||
}
|
||||
case TY_UNION:
|
||||
if (ty->name_pos) {
|
||||
return xasprintf("union %.*s", ty->name_pos->len, ty->name_pos->loc);
|
||||
} else {
|
||||
return strdup("ANONYMOUS-UNION");
|
||||
}
|
||||
case TY_FUNC:
|
||||
return xasprintf("%s(*)()", gc(DescribeType(ty->return_ty)));
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static int CountParams(Obj *params) {
|
||||
int n;
|
||||
for (n = 0; params; params = params->next) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static const char *GetFileName(Obj *obj) {
|
||||
if (obj->javadown && obj->javadown->file) return obj->javadown->file->name;
|
||||
if (obj->tok && obj->tok->file) return obj->tok->file->name;
|
||||
return "missingno.c";
|
||||
}
|
||||
|
||||
static int GetLine(Obj *obj) {
|
||||
if (obj->javadown && obj->javadown->file) return obj->javadown->line_no;
|
||||
if (obj->tok && obj->tok->file) return obj->tok->line_no;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SerializeDox(struct DoxWriter *dox, Obj *prog) {
|
||||
int i;
|
||||
char *s;
|
||||
Obj *param;
|
||||
MacroParam *mparam;
|
||||
SerializeInt(&dox->buf, dox->objects.n);
|
||||
for (i = 0; i < dox->objects.n; ++i) {
|
||||
s = DescribeType(dox->objects.p[i]->ty);
|
||||
SerializeStr(&dox->buf, s);
|
||||
free(s);
|
||||
SerializeStr(&dox->buf, dox->objects.p[i]->name);
|
||||
SerializeStr(&dox->buf, GetFileName(dox->objects.p[i]));
|
||||
SerializeInt(&dox->buf, GetLine(dox->objects.p[i]));
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_function);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_weak);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_inline);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_noreturn);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_destructor);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_constructor);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_force_align_arg_pointer);
|
||||
SerializeInt(&dox->buf, dox->objects.p[i]->is_no_caller_saved_registers);
|
||||
SerializeStr(&dox->buf, dox->objects.p[i]->visibility);
|
||||
SerializeJavadown(&dox->buf, dox->objects.p[i]->javadown->javadown);
|
||||
SerializeInt(&dox->buf, CountParams(dox->objects.p[i]->params));
|
||||
for (param = dox->objects.p[i]->params; param; param = param->next) {
|
||||
s = DescribeType(param->ty);
|
||||
SerializeStr(&dox->buf, s);
|
||||
free(s);
|
||||
SerializeStr(&dox->buf, param->name);
|
||||
}
|
||||
}
|
||||
SerializeInt(&dox->buf, dox->macros.n);
|
||||
for (i = 0; i < dox->macros.n; ++i) {
|
||||
SerializeStr(&dox->buf, dox->macros.p[i]->name);
|
||||
SerializeStr(&dox->buf, dox->macros.p[i]->javadown->file->name);
|
||||
SerializeInt(&dox->buf, dox->macros.p[i]->javadown->line_no);
|
||||
SerializeJavadown(&dox->buf, dox->macros.p[i]->javadown->javadown);
|
||||
}
|
||||
SerializeInt(&dox->buf, 31337);
|
||||
}
|
||||
|
||||
static void LoadPublicDefinitions(struct DoxWriter *dox, Obj *prog) {
|
||||
int i;
|
||||
Obj *obj;
|
||||
Macro *macro;
|
||||
for (obj = prog; obj; obj = obj->next) {
|
||||
if (obj->is_static) continue;
|
||||
if (*obj->name == '_') continue;
|
||||
if (!obj->javadown) continue;
|
||||
if (obj->is_string_literal) continue;
|
||||
if (obj->visibility && !strcmp(obj->visibility, "hidden")) continue;
|
||||
if (strchr(obj->name, '$')) continue;
|
||||
APPEND(dox->objects);
|
||||
dox->objects.p[dox->objects.n - 1] = obj;
|
||||
}
|
||||
for (i = 0; i < macros.capacity; ++i) {
|
||||
if (!macros.buckets[i].key) continue;
|
||||
if (macros.buckets[i].key == (char *)-1) continue;
|
||||
macro = macros.buckets[i].val;
|
||||
if (!macro->javadown) continue;
|
||||
if (!macro->javadown->javadown) continue;
|
||||
if (*macro->name == '_') continue;
|
||||
if (strchr(macro->name, '$')) continue;
|
||||
APPEND(dox->macros);
|
||||
dox->macros.p[dox->macros.n - 1] = macro;
|
||||
}
|
||||
}
|
||||
|
||||
static struct DoxWriter *NewDoxWriter(void) {
|
||||
return calloc(1, sizeof(struct DoxWriter));
|
||||
}
|
||||
|
||||
static void FreeDoxWriter(struct DoxWriter *dox) {
|
||||
if (dox) {
|
||||
free(dox->buf.p);
|
||||
free(dox->macros.p);
|
||||
free(dox->objects.p);
|
||||
free(dox);
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteDox(struct DoxWriter *dox, const char *path) {
|
||||
int fd;
|
||||
CHECK_NE(-1, (fd = creat(path, 0644)));
|
||||
CHECK_EQ(dox->buf.n, write(fd, dox->buf.p, dox->buf.n));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits documentation datum for compilation unit just parsed.
|
||||
*/
|
||||
void output_javadown(const char *path, Obj *prog) {
|
||||
struct DoxWriter *dox = NewDoxWriter();
|
||||
LoadPublicDefinitions(dox, prog);
|
||||
SerializeDox(dox, prog);
|
||||
WriteDox(dox, path);
|
||||
FreeDoxWriter(dox);
|
||||
}
|
392
third_party/chibicc/dox2.c
vendored
Normal file
392
third_party/chibicc/dox2.c
vendored
Normal file
|
@ -0,0 +1,392 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
#define APPEND(L) L.p = realloc(L.p, ++L.n * sizeof(*L.p))
|
||||
|
||||
struct Dox {
|
||||
unsigned char *p;
|
||||
struct Freelist {
|
||||
size_t n;
|
||||
void **p;
|
||||
} freelist;
|
||||
struct Set {
|
||||
size_t n;
|
||||
struct SetEntry {
|
||||
unsigned h;
|
||||
char *s;
|
||||
} * p;
|
||||
} names;
|
||||
struct DoxObjects {
|
||||
size_t n;
|
||||
struct DoxObject {
|
||||
bool ignore;
|
||||
char *type;
|
||||
char *name;
|
||||
char *path;
|
||||
int line;
|
||||
bool is_function;
|
||||
bool is_weak;
|
||||
bool is_inline;
|
||||
bool is_noreturn;
|
||||
bool is_destructor;
|
||||
bool is_constructor;
|
||||
bool is_force_align_arg_pointer;
|
||||
bool is_no_caller_saved_registers;
|
||||
char *visibility;
|
||||
struct Javadown *javadown;
|
||||
struct DoxObjectParams {
|
||||
size_t n;
|
||||
struct DoxObjectParam {
|
||||
char *type;
|
||||
char *name;
|
||||
} * p;
|
||||
} params;
|
||||
} * p;
|
||||
} objects;
|
||||
struct {
|
||||
size_t n;
|
||||
int *p;
|
||||
} objectindex;
|
||||
};
|
||||
|
||||
static unsigned Hash(const void *p, unsigned long n) {
|
||||
unsigned h, i;
|
||||
for (h = i = 0; i < n; i++) {
|
||||
h += ((unsigned char *)p)[i];
|
||||
h *= 0x9e3779b1;
|
||||
}
|
||||
return MAX(1, h);
|
||||
}
|
||||
|
||||
static struct Dox *NewDox(void) {
|
||||
return calloc(1, sizeof(struct Dox));
|
||||
}
|
||||
|
||||
static void FreeDox(struct Dox *dox) {
|
||||
int i;
|
||||
if (dox) {
|
||||
for (i = 0; i < dox->freelist.n; ++i) {
|
||||
free(dox->freelist.p[i]);
|
||||
}
|
||||
free(dox->names.p);
|
||||
free(dox->freelist.p);
|
||||
free(dox->objects.p);
|
||||
free(dox);
|
||||
}
|
||||
}
|
||||
|
||||
static void *FreeLater(struct Dox *dox, void *p) {
|
||||
APPEND(dox->freelist);
|
||||
dox->freelist.p[dox->freelist.n - 1] = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
static int DeserializeInt(struct Dox *dox) {
|
||||
int x;
|
||||
x = (unsigned)dox->p[0] << 000 | (unsigned)dox->p[1] << 010 |
|
||||
(unsigned)dox->p[2] << 020 | (unsigned)dox->p[3] << 030;
|
||||
dox->p += 4;
|
||||
return x;
|
||||
}
|
||||
|
||||
static char *DeserializeStr(struct Dox *dox) {
|
||||
char *s;
|
||||
size_t n;
|
||||
n = DeserializeInt(dox);
|
||||
s = malloc(n + 1);
|
||||
memcpy(s, dox->p, n);
|
||||
s[n] = '\0';
|
||||
dox->p += n;
|
||||
return FreeLater(dox, s);
|
||||
}
|
||||
|
||||
static struct Javadown *DeserializeJavadown(struct Dox *dox) {
|
||||
int i;
|
||||
struct Javadown *jd;
|
||||
jd = FreeLater(dox, calloc(1, sizeof(struct Javadown)));
|
||||
jd->isfileoverview = DeserializeInt(dox);
|
||||
jd->title = DeserializeStr(dox);
|
||||
jd->text = DeserializeStr(dox);
|
||||
jd->tags.n = DeserializeInt(dox);
|
||||
jd->tags.p = FreeLater(dox, malloc(jd->tags.n * sizeof(*jd->tags.p)));
|
||||
for (i = 0; i < jd->tags.n; ++i) {
|
||||
jd->tags.p[i].tag = DeserializeStr(dox);
|
||||
jd->tags.p[i].text = DeserializeStr(dox);
|
||||
}
|
||||
return jd;
|
||||
}
|
||||
|
||||
static void DeserializeObject(struct Dox *dox, struct DoxObject *o) {
|
||||
int i;
|
||||
o->ignore = false;
|
||||
o->type = DeserializeStr(dox);
|
||||
o->name = DeserializeStr(dox);
|
||||
o->path = DeserializeStr(dox);
|
||||
o->line = DeserializeInt(dox);
|
||||
o->is_function = DeserializeInt(dox);
|
||||
o->is_weak = DeserializeInt(dox);
|
||||
o->is_inline = DeserializeInt(dox);
|
||||
o->is_noreturn = DeserializeInt(dox);
|
||||
o->is_destructor = DeserializeInt(dox);
|
||||
o->is_constructor = DeserializeInt(dox);
|
||||
o->is_force_align_arg_pointer = DeserializeInt(dox);
|
||||
o->is_no_caller_saved_registers = DeserializeInt(dox);
|
||||
o->visibility = DeserializeStr(dox);
|
||||
o->javadown = DeserializeJavadown(dox);
|
||||
o->params.n = DeserializeInt(dox);
|
||||
o->params.p = FreeLater(dox, malloc(o->params.n * sizeof(*o->params.p)));
|
||||
for (i = 0; i < o->params.n; ++i) {
|
||||
o->params.p[i].type = DeserializeStr(dox);
|
||||
o->params.p[i].name = DeserializeStr(dox);
|
||||
}
|
||||
}
|
||||
|
||||
static void DeserializeDox(struct Dox *dox) {
|
||||
int i, j, n;
|
||||
i = dox->objects.n;
|
||||
n = DeserializeInt(dox);
|
||||
dox->objects.p =
|
||||
realloc(dox->objects.p, (dox->objects.n + n) * sizeof(*dox->objects.p));
|
||||
for (j = 0; j < n; ++j) {
|
||||
DeserializeObject(dox, dox->objects.p + i + j);
|
||||
}
|
||||
dox->objects.n += n;
|
||||
}
|
||||
|
||||
static void ReadDox(struct Dox *dox, const StringArray *files) {
|
||||
int i, fd;
|
||||
void *map;
|
||||
struct stat st;
|
||||
for (i = 0; i < files->len; ++i) {
|
||||
CHECK_NE(-1, (fd = open(files->data[i], O_RDONLY)));
|
||||
CHECK_NE(-1, fstat(fd, &st));
|
||||
if (st.st_size) {
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
|
||||
dox->p = map;
|
||||
DeserializeDox(dox);
|
||||
munmap(map, st.st_size);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static bool AddSet(struct Set *set, char *s) {
|
||||
unsigned i, h, k;
|
||||
h = Hash(s, strlen(s));
|
||||
k = 0;
|
||||
for (k = 0;; ++k) {
|
||||
i = (h + k + ((k + 1) >> 1)) & (set->n - 1);
|
||||
if (!set->p[i].h) {
|
||||
set->p[i].h = h;
|
||||
set->p[i].s = s;
|
||||
return true;
|
||||
}
|
||||
if (h == set->p[i].h && !strcmp(s, set->p[i].s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int CompareObjectNames(const void *a, const void *b, void *arg) {
|
||||
int *i1, *i2;
|
||||
struct Dox *dox;
|
||||
i1 = a, i2 = b, dox = arg;
|
||||
return strcmp(dox->objects.p[*i1].name, dox->objects.p[*i2].name);
|
||||
}
|
||||
|
||||
static void IndexDox(struct Dox *dox) {
|
||||
size_t i, j, n;
|
||||
dox->names.n = roundup2pow(dox->objects.n) << 1;
|
||||
dox->names.p = calloc(dox->names.n, sizeof(*dox->names.p));
|
||||
for (n = i = 0; i < dox->objects.n; ++i) {
|
||||
if (AddSet(&dox->names, dox->objects.p[i].name)) {
|
||||
++n;
|
||||
} else {
|
||||
dox->objects.p[i].ignore = true;
|
||||
}
|
||||
}
|
||||
dox->objectindex.n = n;
|
||||
dox->objectindex.p = malloc(n * sizeof(*dox->objectindex.p));
|
||||
for (j = i = 0; i < dox->objects.n; ++i) {
|
||||
if (dox->objects.p[i].ignore) continue;
|
||||
dox->objectindex.p[j++] = i;
|
||||
}
|
||||
qsort_r(dox->objectindex.p, dox->objectindex.n, sizeof(*dox->objectindex.p),
|
||||
CompareObjectNames, dox);
|
||||
}
|
||||
|
||||
static void PrintText(FILE *f, const char *s) {
|
||||
int c;
|
||||
bool bol, pre;
|
||||
for (pre = false, bol = true;;) {
|
||||
switch ((c = *s++)) {
|
||||
case '\0':
|
||||
if (pre) {
|
||||
fprintf(f, "</pre>");
|
||||
}
|
||||
return;
|
||||
case '&':
|
||||
fprintf(f, "&");
|
||||
bol = false;
|
||||
break;
|
||||
case '<':
|
||||
fprintf(f, "<");
|
||||
bol = false;
|
||||
break;
|
||||
case '>':
|
||||
fprintf(f, ">");
|
||||
bol = false;
|
||||
break;
|
||||
case '"':
|
||||
fprintf(f, """);
|
||||
bol = false;
|
||||
break;
|
||||
case '\'':
|
||||
fprintf(f, "'");
|
||||
bol = false;
|
||||
break;
|
||||
case '\n':
|
||||
if (!pre && *s == '\n') {
|
||||
++s;
|
||||
fprintf(f, "\n<p>");
|
||||
} else if (pre &&
|
||||
(s[0] != ' ' || s[1] != ' ' || s[2] != ' ' || s[3] != ' ')) {
|
||||
fprintf(f, "</pre>\n");
|
||||
pre = false;
|
||||
} else {
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
bol = true;
|
||||
break;
|
||||
case ' ':
|
||||
if (bol && !pre && s[0] == ' ' && s[1] == ' ' && s[2] == ' ') {
|
||||
pre = true;
|
||||
fprintf(f, "<pre>");
|
||||
}
|
||||
fprintf(f, " ");
|
||||
bol = false;
|
||||
break;
|
||||
default:
|
||||
fprintf(f, "%c", c);
|
||||
bol = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintDox(struct Dox *dox, FILE *f) {
|
||||
int i, j, k;
|
||||
char *prefix;
|
||||
struct DoxObject *o;
|
||||
fprintf(f, "\
|
||||
<!doctype html>\n\
|
||||
<meta charset=\"utf-8\">\n\
|
||||
<style>\n\
|
||||
.indent {\n\
|
||||
padding-left: 1em;\n\
|
||||
}\n\
|
||||
</style>\n\
|
||||
\n\
|
||||
<table width=\"100%%\"><tr><td width=\"33%%\" valign=\"top\">\n\
|
||||
<p class=\"toc\">\n\
|
||||
");
|
||||
for (i = 0; i < dox->objectindex.n; ++i) {
|
||||
o = dox->objects.p + dox->objectindex.p[i];
|
||||
if (o->ignore || !o->is_function) continue;
|
||||
fprintf(f, "<a href=\"#%s\">%s</a><br>\n", o->name, o->name);
|
||||
fprintf(f, "<br>\n");
|
||||
}
|
||||
fprintf(f, "<td width=\"67%%\" valign=\"top\">\n");
|
||||
for (i = 0; i < dox->objectindex.n; ++i) {
|
||||
o = dox->objects.p + dox->objectindex.p[i];
|
||||
if (o->ignore || !o->is_function) continue;
|
||||
fprintf(f, "\n<div id=\"%s\" class=\"func\">\n", o->name, o->name);
|
||||
fprintf(f, "<h3><a href=\"#%s\">", o->name);
|
||||
fprintf(f, "<strong class=\"name\">%s</strong></a></h3>", o->name);
|
||||
fprintf(f, "<p>");
|
||||
PrintText(f, o->javadown->title);
|
||||
fprintf(f, "\n");
|
||||
if (*o->javadown->text) {
|
||||
fprintf(f, "<p>");
|
||||
PrintText(f, o->javadown->text);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
fprintf(f, "<p><strong>@param</strong>\n");
|
||||
fprintf(f, "<div class=\"params indent\">\n");
|
||||
if (o->params.n) {
|
||||
fprintf(f, "<dl>\n");
|
||||
for (j = 0; j < o->params.n; ++j) {
|
||||
fprintf(f, "<dt>");
|
||||
PrintText(f, o->params.p[j].type);
|
||||
fprintf(f, " <em>");
|
||||
PrintText(f, o->params.p[j].name);
|
||||
fprintf(f, "</em>\n");
|
||||
prefix = xasprintf("%s ", o->params.p[j].name);
|
||||
for (k = 0; k < o->javadown->tags.n; ++k) {
|
||||
if (!strcmp(o->javadown->tags.p[k].tag, "param") &&
|
||||
startswith(o->javadown->tags.p[k].text, prefix)) {
|
||||
fprintf(f, "<dd>");
|
||||
PrintText(f, o->javadown->tags.p[k].text + strlen(prefix));
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(prefix);
|
||||
}
|
||||
fprintf(f, "</dl>\n");
|
||||
} else {
|
||||
fprintf(f, "<p>None.\n");
|
||||
}
|
||||
fprintf(f, "</div>\n");
|
||||
for (k = 0; k < o->javadown->tags.n; ++k) {
|
||||
if (!strcmp(o->javadown->tags.p[k].tag, "param")) continue;
|
||||
fprintf(f, "<p><strong>@");
|
||||
PrintText(f, o->javadown->tags.p[k].tag);
|
||||
fprintf(f, "</strong>\n");
|
||||
if (*o->javadown->tags.p[k].text) {
|
||||
PrintText(f, o->javadown->tags.p[k].text);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
fprintf(f, "</div>\n");
|
||||
}
|
||||
fprintf(f, "</table>\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges documentation data and outputs HTML.
|
||||
*/
|
||||
void drop_dox(const StringArray *files, const char *path) {
|
||||
FILE *f;
|
||||
struct Dox *dox;
|
||||
dox = NewDox();
|
||||
ReadDox(dox, files);
|
||||
IndexDox(dox);
|
||||
f = fopen(path, "w");
|
||||
PrintDox(dox, f);
|
||||
fclose(f);
|
||||
FreeDox(dox);
|
||||
}
|
107
third_party/chibicc/parse.c
vendored
107
third_party/chibicc/parse.c
vendored
|
@ -16,6 +16,7 @@
|
|||
// So it is very easy to lookahead arbitrary number of tokens in this
|
||||
// parser.
|
||||
|
||||
#include "libc/nexgen32e/ffs.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
|
@ -50,11 +51,14 @@ typedef struct {
|
|||
bool is_const;
|
||||
bool is_tls;
|
||||
bool is_weak;
|
||||
bool is_ms_abi;
|
||||
bool is_aligned;
|
||||
bool is_noreturn;
|
||||
bool is_destructor;
|
||||
bool is_constructor;
|
||||
bool is_externally_visible;
|
||||
bool is_force_align_arg_pointer;
|
||||
bool is_no_caller_saved_registers;
|
||||
int align;
|
||||
char *section;
|
||||
char *visibility;
|
||||
|
@ -113,6 +117,8 @@ static Node *current_switch;
|
|||
|
||||
static Obj *builtin_alloca;
|
||||
|
||||
static Token *current_javadown;
|
||||
|
||||
static Initializer *initializer(Token **, Token *, Type *, Type **);
|
||||
static Member *get_struct_member(Type *, Token *);
|
||||
static Node *binor(Token **, Token *);
|
||||
|
@ -382,6 +388,10 @@ static Token *type_attributes(Token *tok, void *arg) {
|
|||
ty->is_packed = true;
|
||||
return tok;
|
||||
}
|
||||
if (consume_attribute(&tok, tok, "ms_abi")) {
|
||||
ty->is_ms_abi = true;
|
||||
return tok;
|
||||
}
|
||||
if (consume_attribute(&tok, tok, "aligned")) {
|
||||
ty->is_aligned = true;
|
||||
if (CONSUME(&tok, tok, "(")) {
|
||||
|
@ -466,6 +476,18 @@ static Token *thing_attributes(Token *tok, void *arg) {
|
|||
attr->is_externally_visible = true;
|
||||
return tok;
|
||||
}
|
||||
if (consume_attribute(&tok, tok, "force_align_arg_pointer")) {
|
||||
attr->is_force_align_arg_pointer = true;
|
||||
return tok;
|
||||
}
|
||||
if (consume_attribute(&tok, tok, "no_caller_saved_registers")) {
|
||||
attr->is_no_caller_saved_registers = true;
|
||||
return tok;
|
||||
}
|
||||
if (consume_attribute(&tok, tok, "ms_abi")) {
|
||||
attr->is_ms_abi = true;
|
||||
return tok;
|
||||
}
|
||||
if (consume_attribute(&tok, tok, "constructor")) {
|
||||
attr->is_constructor = true;
|
||||
if (CONSUME(&tok, tok, "(")) {
|
||||
|
@ -1080,6 +1102,7 @@ static Node *declaration(Token **rest, Token *tok, Type *basety,
|
|||
// even if ty is not VLA because ty may be a pointer to VLA
|
||||
// (e.g. int (*foo)[n][m] where n and m are variables.)
|
||||
cur = cur->next = new_unary(ND_EXPR_STMT, compute_vla_size(ty, tok), tok);
|
||||
tok = attribute_list(tok, attr, thing_attributes);
|
||||
if (ty->kind == TY_VLA) {
|
||||
if (EQUAL(tok, "="))
|
||||
error_tok(tok, "variable-sized object may not be initialized");
|
||||
|
@ -1198,7 +1221,8 @@ static Member *struct_designator(Token **rest, Token *tok, Type *ty) {
|
|||
if (tok->kind != TK_IDENT) error_tok(tok, "expected a field designator");
|
||||
for (Member *mem = ty->members; mem; mem = mem->next) {
|
||||
// Anonymous struct member
|
||||
if (mem->ty->kind == TY_STRUCT && !mem->name) {
|
||||
if ((mem->ty->kind == TY_STRUCT || mem->ty->kind == TY_UNION) &&
|
||||
!mem->name) {
|
||||
if (get_struct_member(mem->ty, tok)) {
|
||||
*rest = start;
|
||||
return mem;
|
||||
|
@ -1920,6 +1944,7 @@ int64_t eval(Node *node) {
|
|||
// number. The latter form is accepted only as an initialization
|
||||
// expression for a global variable.
|
||||
int64_t eval2(Node *node, char ***label) {
|
||||
int64_t x, y;
|
||||
add_type(node);
|
||||
if (is_flonum(node->ty)) return eval_double(node);
|
||||
switch (node->kind) {
|
||||
|
@ -1930,15 +1955,25 @@ int64_t eval2(Node *node, char ***label) {
|
|||
case ND_MUL:
|
||||
return eval(node->lhs) * eval(node->rhs);
|
||||
case ND_DIV:
|
||||
if (node->ty->is_unsigned)
|
||||
return (uint64_t)eval(node->lhs) / eval(node->rhs);
|
||||
return eval(node->lhs) / eval(node->rhs);
|
||||
y = eval(node->rhs);
|
||||
if (!y) error_tok(node->rhs->tok, "constexpr div by zero");
|
||||
if (node->ty->is_unsigned) {
|
||||
return (uint64_t)eval(node->lhs) / y;
|
||||
}
|
||||
x = eval(node->lhs);
|
||||
if (x == 0x8000000000000000 && y == -1) {
|
||||
error_tok(node->rhs->tok, "constexpr divide error");
|
||||
}
|
||||
return x / y;
|
||||
case ND_NEG:
|
||||
return -eval(node->lhs);
|
||||
case ND_REM:
|
||||
if (node->ty->is_unsigned)
|
||||
return (uint64_t)eval(node->lhs) % eval(node->rhs);
|
||||
return eval(node->lhs) % eval(node->rhs);
|
||||
y = eval(node->rhs);
|
||||
if (!y) error_tok(node->rhs->tok, "constexpr rem by zero");
|
||||
if (node->ty->is_unsigned) {
|
||||
return (uint64_t)eval(node->lhs) % y;
|
||||
}
|
||||
return eval(node->lhs) % y;
|
||||
case ND_BINAND:
|
||||
return eval(node->lhs) & eval(node->rhs);
|
||||
case ND_BINOR:
|
||||
|
@ -2044,8 +2079,9 @@ int64_t eval2(Node *node, char ***label) {
|
|||
static int64_t eval_rval(Node *node, char ***label) {
|
||||
switch (node->kind) {
|
||||
case ND_VAR:
|
||||
if (node->var->is_local)
|
||||
if (node->var->is_local) {
|
||||
error_tok(node->tok, "not a compile-time constant");
|
||||
}
|
||||
*label = &node->var->name;
|
||||
return 0;
|
||||
case ND_DEREF:
|
||||
|
@ -2063,6 +2099,7 @@ bool is_const_expr(Node *node) {
|
|||
case ND_SUB:
|
||||
case ND_MUL:
|
||||
case ND_DIV:
|
||||
case ND_REM:
|
||||
case ND_BINAND:
|
||||
case ND_BINOR:
|
||||
case ND_BINXOR:
|
||||
|
@ -2884,8 +2921,9 @@ static Node *postfix(Token **rest, Token *tok) {
|
|||
static Node *funcall(Token **rest, Token *tok, Node *fn) {
|
||||
add_type(fn);
|
||||
if (fn->ty->kind != TY_FUNC &&
|
||||
(fn->ty->kind != TY_PTR || fn->ty->base->kind != TY_FUNC))
|
||||
(fn->ty->kind != TY_PTR || fn->ty->base->kind != TY_FUNC)) {
|
||||
error_tok(fn->tok, "not a function");
|
||||
}
|
||||
Type *ty = (fn->ty->kind == TY_FUNC) ? fn->ty : fn->ty->base;
|
||||
Type *param_ty = ty->params;
|
||||
Node head = {};
|
||||
|
@ -2896,8 +2934,9 @@ static Node *funcall(Token **rest, Token *tok, Node *fn) {
|
|||
add_type(arg);
|
||||
if (!param_ty && !ty->is_variadic) error_tok(tok, "too many arguments");
|
||||
if (param_ty) {
|
||||
if (param_ty->kind != TY_STRUCT && param_ty->kind != TY_UNION)
|
||||
if (param_ty->kind != TY_STRUCT && param_ty->kind != TY_UNION) {
|
||||
arg = new_cast(arg, param_ty);
|
||||
}
|
||||
param_ty = param_ty->next;
|
||||
} else if (arg->ty->kind == TY_FLOAT) {
|
||||
// If parameter type is omitted (e.g. in "..."), float
|
||||
|
@ -2914,8 +2953,9 @@ static Node *funcall(Token **rest, Token *tok, Node *fn) {
|
|||
node->args = head.next;
|
||||
// If a function returns a struct, it is caller's responsibility
|
||||
// to allocate a space for the return value.
|
||||
if (node->ty->kind == TY_STRUCT || node->ty->kind == TY_UNION)
|
||||
if (node->ty->kind == TY_STRUCT || node->ty->kind == TY_UNION) {
|
||||
node->ret_buffer = new_lvar("", node->ty);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -3138,13 +3178,37 @@ static Node *primary(Token **rest, Token *tok) {
|
|||
*rest = skip(tok, ')');
|
||||
return node;
|
||||
}
|
||||
if (EQUAL(tok, "__builtin_popcount") || EQUAL(tok, "__builtin_popcountl") ||
|
||||
if (EQUAL(tok, "__builtin_popcount")) {
|
||||
Token *t = skip(tok->next, '(');
|
||||
Node *node = assign(&t, t);
|
||||
if (is_const_expr(node)) {
|
||||
*rest = skip(t, ')');
|
||||
return new_num(__builtin_popcount(eval(node)), t);
|
||||
}
|
||||
}
|
||||
if (EQUAL(tok, "__builtin_popcountl") ||
|
||||
EQUAL(tok, "__builtin_popcountll")) {
|
||||
Token *t = skip(tok->next, '(');
|
||||
Node *node = assign(&t, t);
|
||||
if (is_const_expr(node)) {
|
||||
*rest = skip(t, ')');
|
||||
return new_num(popcnt(eval(node)), t);
|
||||
return new_num(__builtin_popcountl(eval(node)), t);
|
||||
}
|
||||
}
|
||||
if (EQUAL(tok, "__builtin_ffs")) {
|
||||
Token *t = skip(tok->next, '(');
|
||||
Node *node = assign(&t, t);
|
||||
if (is_const_expr(node)) {
|
||||
*rest = skip(t, ')');
|
||||
return new_num(__builtin_ffs(eval(node)), t);
|
||||
}
|
||||
}
|
||||
if (EQUAL(tok, "__builtin_ffsl") || EQUAL(tok, "__builtin_ffsll")) {
|
||||
Token *t = skip(tok->next, '(');
|
||||
Node *node = assign(&t, t);
|
||||
if (is_const_expr(node)) {
|
||||
*rest = skip(t, ')');
|
||||
return new_num(__builtin_ffsl(eval(node)), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3328,15 +3392,19 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
|||
fn->is_static = attr->is_static || (attr->is_inline && !attr->is_extern);
|
||||
fn->is_inline = attr->is_inline;
|
||||
fn->is_weak = attr->is_weak;
|
||||
fn->is_ms_abi = attr->is_ms_abi;
|
||||
fn->is_aligned = attr->is_aligned;
|
||||
fn->is_noreturn = attr->is_noreturn;
|
||||
fn->is_destructor = attr->is_destructor;
|
||||
fn->is_constructor = attr->is_constructor;
|
||||
fn->is_externally_visible = attr->is_externally_visible;
|
||||
fn->is_force_align_arg_pointer = attr->is_force_align_arg_pointer;
|
||||
fn->is_no_caller_saved_registers = attr->is_no_caller_saved_registers;
|
||||
fn->align = attr->align;
|
||||
fn->section = attr->section;
|
||||
fn->visibility = attr->visibility;
|
||||
}
|
||||
fn->javadown = fn->javadown ?: current_javadown;
|
||||
fn->is_root = !(fn->is_static && fn->is_inline);
|
||||
if (consume_attribute(&tok, tok, "asm")) {
|
||||
tok = skip(tok, '(');
|
||||
|
@ -3352,11 +3420,13 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
|||
// A buffer for a struct/union return value is passed
|
||||
// as the hidden first parameter.
|
||||
Type *rty = ty->return_ty;
|
||||
if ((rty->kind == TY_STRUCT || rty->kind == TY_UNION) && rty->size > 16)
|
||||
if ((rty->kind == TY_STRUCT || rty->kind == TY_UNION) && rty->size > 16) {
|
||||
new_lvar("", pointer_to(rty));
|
||||
}
|
||||
fn->params = locals;
|
||||
if (ty->is_variadic)
|
||||
if (ty->is_variadic) {
|
||||
fn->va_area = new_lvar("__va_area__", array_of(ty_char, 136));
|
||||
}
|
||||
fn->alloca_bottom = new_lvar("__alloca_size__", pointer_to(ty_char));
|
||||
tok = skip(tok, '{');
|
||||
// [https://www.sigbus.info/n1570#6.4.2.2p1] "__func__" is
|
||||
|
@ -3382,6 +3452,7 @@ static Token *global_variable(Token *tok, Type *basety, VarAttr *attr) {
|
|||
Type *ty = declarator(&tok, tok, basety);
|
||||
if (!ty->name) error_tok(ty->name_pos, "variable name omitted");
|
||||
Obj *var = new_gvar(get_ident(ty->name), ty);
|
||||
var->javadown = current_javadown;
|
||||
if (consume_attribute(&tok, tok, "asm")) {
|
||||
tok = skip(tok, '(');
|
||||
var->asmname = ConsumeStringLiteral(&tok, tok);
|
||||
|
@ -3528,6 +3599,12 @@ Obj *parse(Token *tok) {
|
|||
tok = static_assertion(tok);
|
||||
continue;
|
||||
}
|
||||
if (tok->kind == TK_JAVADOWN) {
|
||||
current_javadown = tok;
|
||||
tok = tok->next;
|
||||
} else {
|
||||
current_javadown = NULL;
|
||||
}
|
||||
VarAttr attr = {};
|
||||
tok = attribute_list(tok, &attr, thing_attributes);
|
||||
Type *basety = declspec(&tok, tok, &attr);
|
||||
|
|
44
third_party/chibicc/preprocess.c
vendored
44
third_party/chibicc/preprocess.c
vendored
|
@ -26,11 +26,7 @@
|
|||
|
||||
typedef struct CondIncl CondIncl;
|
||||
typedef struct Hideset Hideset;
|
||||
typedef struct Macro Macro;
|
||||
typedef struct MacroArg MacroArg;
|
||||
typedef struct MacroParam MacroParam;
|
||||
|
||||
typedef Token *macro_handler_fn(Token *);
|
||||
|
||||
typedef enum {
|
||||
STR_NONE,
|
||||
|
@ -40,11 +36,6 @@ typedef enum {
|
|||
STR_WIDE,
|
||||
} StringKind;
|
||||
|
||||
struct MacroParam {
|
||||
MacroParam *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct MacroArg {
|
||||
MacroArg *next;
|
||||
char *name;
|
||||
|
@ -52,15 +43,6 @@ struct MacroArg {
|
|||
Token *tok;
|
||||
};
|
||||
|
||||
struct Macro {
|
||||
char *name;
|
||||
bool is_objlike; // Object-like or function-like
|
||||
MacroParam *params;
|
||||
char *va_args_name;
|
||||
Token *body;
|
||||
macro_handler_fn *handler;
|
||||
};
|
||||
|
||||
// `#if` can be nested, so we use a stack to manage nested `#if`s.
|
||||
struct CondIncl {
|
||||
CondIncl *next;
|
||||
|
@ -74,7 +56,8 @@ struct Hideset {
|
|||
char *name;
|
||||
};
|
||||
|
||||
static HashMap macros;
|
||||
HashMap macros;
|
||||
|
||||
static CondIncl *cond_incl;
|
||||
static HashMap pragma_once;
|
||||
static int include_next_idx;
|
||||
|
@ -338,21 +321,24 @@ static MacroParam *read_macro_params(Token **rest, Token *tok,
|
|||
return head.next;
|
||||
}
|
||||
|
||||
static void read_macro_definition(Token **rest, Token *tok) {
|
||||
static Macro *read_macro_definition(Token **rest, Token *tok) {
|
||||
Macro *m;
|
||||
char *name;
|
||||
if (tok->kind != TK_IDENT) error_tok(tok, "macro name must be an identifier");
|
||||
char *name = strndup(tok->loc, tok->len);
|
||||
name = strndup(tok->loc, tok->len);
|
||||
tok = tok->next;
|
||||
if (!tok->has_space && EQUAL(tok, "(")) {
|
||||
// Function-like macro
|
||||
char *va_args_name = NULL;
|
||||
MacroParam *params = read_macro_params(&tok, tok->next, &va_args_name);
|
||||
Macro *m = add_macro(name, false, copy_line(rest, tok));
|
||||
m = add_macro(name, false, copy_line(rest, tok));
|
||||
m->params = params;
|
||||
m->va_args_name = va_args_name;
|
||||
} else {
|
||||
// Object-like macro
|
||||
add_macro(name, true, copy_line(rest, tok));
|
||||
m = add_macro(name, true, copy_line(rest, tok));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static MacroArg *read_macro_arg_one(Token **rest, Token *tok, bool read_rest) {
|
||||
|
@ -742,6 +728,12 @@ static Token *preprocess2(Token *tok) {
|
|||
while (tok->kind != TK_EOF) {
|
||||
// If it is a macro, expand it.
|
||||
if (expand_macro(&tok, tok)) continue;
|
||||
// make sure javadown is removed if it's for a macro definition
|
||||
if (tok->kind == TK_JAVADOWN && is_hash(tok->next) &&
|
||||
EQUAL(tok->next->next, "define")) {
|
||||
read_macro_definition(&tok, tok->next->next->next)->javadown = tok;
|
||||
continue;
|
||||
}
|
||||
// Pass through if it is not a "#".
|
||||
if (!is_hash(tok)) {
|
||||
tok->line_delta = tok->file->line_delta;
|
||||
|
@ -936,6 +928,8 @@ __GNUC_PATCHLEVEL__\000\
|
|||
0\000\
|
||||
__NO_INLINE__\000\
|
||||
16\000\
|
||||
__GNUC_STDC_INLINE__\000\
|
||||
1\000\
|
||||
__BIGGEST_ALIGNMENT__\000\
|
||||
16\000\
|
||||
__C99_MACRO_WITH_VA_ARGS\000\
|
||||
|
@ -1010,6 +1004,10 @@ __UINT32_MAX__\000\
|
|||
0xffffffffu\000\
|
||||
__INT64_MAX__\000\
|
||||
0x7fffffffffffffffl\000\
|
||||
__LONG_MAX__\000\
|
||||
0x7fffffffffffffffl\000\
|
||||
__LONG_LONG_MAX__\000\
|
||||
0x7fffffffffffffffl\000\
|
||||
__UINT64_MAX__\000\
|
||||
0xfffffffffffffffful\000\
|
||||
__SIZE_MAX__\000\
|
||||
|
|
3
third_party/chibicc/test/attribute_test.c
vendored
3
third_party/chibicc/test/attribute_test.c
vendored
|
@ -12,7 +12,8 @@ __attribute__((__nonnull__(1))) void cate2(char *);
|
|||
__attribute__((__section__(".data.var"))) int var2;
|
||||
__attribute__((__section__(".data.var"))) int ar2[4];
|
||||
|
||||
int main() {
|
||||
__attribute__((__force_align_arg_pointer__, __no_caller_saved_registers__)) int
|
||||
main() {
|
||||
int2 a;
|
||||
ASSERT(64, _Alignof(int2));
|
||||
ASSERT(64, _Alignof(a));
|
||||
|
|
6
third_party/chibicc/test/vla_test.c
vendored
6
third_party/chibicc/test/vla_test.c
vendored
|
@ -1,3 +1,4 @@
|
|||
#include "libc/macros.h"
|
||||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
int main() {
|
||||
|
@ -6,6 +7,11 @@ int main() {
|
|||
int x[n];
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
int n = 5;
|
||||
int x[n];
|
||||
ARRAYLEN(x);
|
||||
}));
|
||||
ASSERT((5 + 1) * (8 * 2) * 4, ({
|
||||
int m = 5, n = 8;
|
||||
int x[m + 1][n * 2];
|
||||
|
|
47
third_party/chibicc/tokenize.c
vendored
47
third_party/chibicc/tokenize.c
vendored
|
@ -470,6 +470,7 @@ Token *tokenize(File *file) {
|
|||
char *p = file->contents;
|
||||
Token head = {};
|
||||
Token *cur = &head;
|
||||
struct Javadown *javadown;
|
||||
at_bol = true;
|
||||
has_space = false;
|
||||
while (*p) {
|
||||
|
@ -480,6 +481,22 @@ Token *tokenize(File *file) {
|
|||
has_space = true;
|
||||
continue;
|
||||
}
|
||||
// Javadoc-style markdown comments.
|
||||
if (LOOKINGAT(p, "/**") && p[3] != '/' && p[3] != '*') {
|
||||
char *q = strstr(p + 3, "*/");
|
||||
if (!q) error_at(p, "unclosed javadown");
|
||||
javadown = ParseJavadown(p + 3, q - p - 3 - 2);
|
||||
if (javadown->isfileoverview) {
|
||||
FreeJavadown(file->javadown);
|
||||
file->javadown = javadown;
|
||||
} else {
|
||||
cur = cur->next = new_token(TK_JAVADOWN, p, q + 2);
|
||||
cur->javadown = javadown;
|
||||
}
|
||||
p = q + 2;
|
||||
has_space = true;
|
||||
continue;
|
||||
}
|
||||
// Skip block comments.
|
||||
if (LOOKINGAT(p, "/*")) {
|
||||
char *q = strstr(p + 2, "*/");
|
||||
|
@ -505,12 +522,13 @@ Token *tokenize(File *file) {
|
|||
if (isdigit(*p) || (*p == '.' && isdigit(p[1]))) {
|
||||
char *q = p++;
|
||||
for (;;) {
|
||||
if (p[0] && p[1] && strchr("eEpP", p[0]) && strchr("+-", p[1]))
|
||||
if (p[0] && p[1] && strchr("eEpP", p[0]) && strchr("+-", p[1])) {
|
||||
p += 2;
|
||||
else if (isalnum(*p) || *p == '.')
|
||||
} else if (isalnum(*p) || *p == '.') {
|
||||
p++;
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur = cur->next = new_token(TK_PP_NUM, q, p);
|
||||
continue;
|
||||
|
@ -663,7 +681,30 @@ void remove_backslash_newline(char *p) {
|
|||
// the logical line number matches the physical one.
|
||||
// This counter maintain the number of newlines we have removed.
|
||||
int n = 0;
|
||||
bool instring = false;
|
||||
while (p[i]) {
|
||||
if (instring) {
|
||||
if (p[i] == '"' && p[i - 1] != '\\') {
|
||||
instring = false;
|
||||
}
|
||||
} else {
|
||||
if (p[i] == '"') {
|
||||
instring = true;
|
||||
} else if (p[i] == '/' && p[i + 1] == '*') {
|
||||
p[j++] = p[i++];
|
||||
p[j++] = p[i++];
|
||||
while (p[i]) {
|
||||
if (p[i] == '*' && p[i + 1] == '/') {
|
||||
p[j++] = p[i++];
|
||||
p[j++] = p[i++];
|
||||
break;
|
||||
} else {
|
||||
p[j++] = p[i++];
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (p[i] == '\\' && p[i + 1] == '\n') {
|
||||
i += 2;
|
||||
n++;
|
||||
|
|
35
third_party/dlmalloc/mallinfo.c
vendored
35
third_party/dlmalloc/mallinfo.c
vendored
|
@ -4,19 +4,28 @@
|
|||
/**
|
||||
* Returns (by copy) a struct containing various summary statistics:
|
||||
*
|
||||
* arena: current total non-mmapped bytes allocated from system
|
||||
* ordblks: the number of free chunks
|
||||
* smblks: always zero.
|
||||
* hblks: current number of mmapped regions
|
||||
* hblkhd: total bytes held in mmapped regions
|
||||
* usmblks: the maximum total allocated space. This will be greater
|
||||
* than current total if trimming has occurred.
|
||||
* fsmblks: always zero
|
||||
* uordblks: current total allocated space (normal or mmapped)
|
||||
* fordblks: total free space
|
||||
* keepcost: the maximum number of bytes that could ideally be released
|
||||
* back to system via malloc_trim. ("ideally" means that
|
||||
* it ignores page restrictions etc.)
|
||||
* - arena: current total non-mmapped bytes allocated from system
|
||||
*
|
||||
* - ordblks: the number of free chunks
|
||||
*
|
||||
* - smblks: always zero.
|
||||
*
|
||||
* - hblks: current number of mmapped regions
|
||||
*
|
||||
* - hblkhd: total bytes held in mmapped regions
|
||||
*
|
||||
* - usmblks: the maximum total allocated space. This will be greater
|
||||
* than current total if trimming has occurred.
|
||||
*
|
||||
* - fsmblks: always zero
|
||||
*
|
||||
* - uordblks: current total allocated space (normal or mmapped)
|
||||
*
|
||||
* - fordblks: total free space
|
||||
*
|
||||
* - keepcost: the maximum number of bytes that could ideally be
|
||||
* released back to system via malloc_trim. ("ideally" means that it
|
||||
* ignores page restrictions etc.)
|
||||
*
|
||||
* Because these fields are ints, but internal bookkeeping may
|
||||
* be kept as longs, the reported values may wrap around zero and
|
||||
|
|
14
third_party/musl/glob.c
vendored
14
third_party/musl/glob.c
vendored
|
@ -227,13 +227,13 @@ static int GlobPredicate(const void *a, const void *b) {
|
|||
*
|
||||
* For example:
|
||||
*
|
||||
* glob_t g = {.gl_offs = 2};
|
||||
* glob("*.*", GLOB_DOOFFS, NULL, &g);
|
||||
* glob("../.*", GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
|
||||
* g.gl_pathv[0] = "ls";
|
||||
* g.gl_pathv[1] = "-l";
|
||||
* execvp("ls", &g.gl_pathv[0]);
|
||||
* globfree(g);
|
||||
* glob_t g = {.gl_offs = 2};
|
||||
* glob("*.*", GLOB_DOOFFS, NULL, &g);
|
||||
* glob("../.*", GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
|
||||
* g.gl_pathv[0] = "ls";
|
||||
* g.gl_pathv[1] = "-l";
|
||||
* execvp("ls", &g.gl_pathv[0]);
|
||||
* globfree(g);
|
||||
*
|
||||
* @param pat can have star wildcard see fnmatch()
|
||||
* @param g will receive matching entries and needs globfree()
|
||||
|
|
8
third_party/regex/regcomp.c
vendored
8
third_party/regex/regcomp.c
vendored
|
@ -2387,10 +2387,10 @@ static reg_errcode_t tre_ast_to_tnfa(tre_ast_node_t *node,
|
|||
/**
|
||||
* Compiles regular expression, e.g.
|
||||
*
|
||||
* regex_t rx;
|
||||
* EXPECT_EQ(REG_OK, regcomp(&rx, "^[A-Za-z\x7f-\uFFFF]{2}$", REG_EXTENDED));
|
||||
* EXPECT_EQ(REG_OK, regexec(&rx, "→A", 0, NULL, 0));
|
||||
* regfree(&rx);
|
||||
* regex_t rx;
|
||||
* EXPECT_EQ(REG_OK, regcomp(&rx, "^[A-Za-z]{2}$", REG_EXTENDED));
|
||||
* EXPECT_EQ(REG_OK, regexec(&rx, "→A", 0, NULL, 0));
|
||||
* regfree(&rx);
|
||||
*
|
||||
* @param preg points to state, and needs regfree() afterwards
|
||||
* @param regex is utf-8 regular expression string
|
||||
|
|
80
third_party/zlib/zlib.h
vendored
80
third_party/zlib/zlib.h
vendored
|
@ -38,11 +38,11 @@
|
|||
* even in the case of corrupted input.
|
||||
*/
|
||||
|
||||
#define ZLIB_VERSION "1.2.11"
|
||||
#define ZLIB_VERNUM 0x12b0
|
||||
#define ZLIB_VER_MAJOR 1
|
||||
#define ZLIB_VER_MINOR 2
|
||||
#define ZLIB_VER_REVISION 11
|
||||
#define ZLIB_VERSION "1.2.11"
|
||||
#define ZLIB_VERNUM 0x12b0
|
||||
#define ZLIB_VER_MAJOR 1
|
||||
#define ZLIB_VER_MINOR 2
|
||||
#define ZLIB_VER_REVISION 11
|
||||
#define ZLIB_VER_SUBREVISION 0
|
||||
|
||||
/**
|
||||
|
@ -81,25 +81,25 @@
|
|||
* (particularly if the decompressor wants to decompress everything in a
|
||||
* single step).
|
||||
*/
|
||||
#define Z_NO_FLUSH 0
|
||||
#define Z_NO_FLUSH 0
|
||||
#define Z_PARTIAL_FLUSH 1
|
||||
#define Z_SYNC_FLUSH 2
|
||||
#define Z_FULL_FLUSH 3
|
||||
#define Z_FINISH 4
|
||||
#define Z_BLOCK 5
|
||||
#define Z_TREES 6
|
||||
#define Z_SYNC_FLUSH 2
|
||||
#define Z_FULL_FLUSH 3
|
||||
#define Z_FINISH 4
|
||||
#define Z_BLOCK 5
|
||||
#define Z_TREES 6
|
||||
|
||||
/**
|
||||
* Allowed flush values; see deflate() and inflate() below for details.
|
||||
*/
|
||||
#define Z_OK 0
|
||||
#define Z_STREAM_END 1
|
||||
#define Z_NEED_DICT 2
|
||||
#define Z_ERRNO (-1)
|
||||
#define Z_STREAM_ERROR (-2)
|
||||
#define Z_DATA_ERROR (-3)
|
||||
#define Z_MEM_ERROR (-4)
|
||||
#define Z_BUF_ERROR (-5)
|
||||
#define Z_OK 0
|
||||
#define Z_STREAM_END 1
|
||||
#define Z_NEED_DICT 2
|
||||
#define Z_ERRNO (-1)
|
||||
#define Z_STREAM_ERROR (-2)
|
||||
#define Z_DATA_ERROR (-3)
|
||||
#define Z_MEM_ERROR (-4)
|
||||
#define Z_BUF_ERROR (-5)
|
||||
#define Z_VERSION_ERROR (-6)
|
||||
|
||||
/**
|
||||
|
@ -107,26 +107,26 @@
|
|||
* values are errors, positive values are used for special but normal
|
||||
* events.
|
||||
*/
|
||||
#define Z_NO_COMPRESSION 0
|
||||
#define Z_BEST_SPEED 1
|
||||
#define Z_BEST_COMPRESSION 9
|
||||
#define Z_NO_COMPRESSION 0
|
||||
#define Z_BEST_SPEED 1
|
||||
#define Z_BEST_COMPRESSION 9
|
||||
#define Z_DEFAULT_COMPRESSION (-1)
|
||||
|
||||
/**
|
||||
* Compression levels.
|
||||
*/
|
||||
#define Z_FILTERED 1
|
||||
#define Z_HUFFMAN_ONLY 2
|
||||
#define Z_RLE 3
|
||||
#define Z_FIXED 4
|
||||
#define Z_FILTERED 1
|
||||
#define Z_HUFFMAN_ONLY 2
|
||||
#define Z_RLE 3
|
||||
#define Z_FIXED 4
|
||||
#define Z_DEFAULT_STRATEGY 0
|
||||
|
||||
/**
|
||||
* Compression strategy; see deflateInit2() below for details
|
||||
*/
|
||||
#define Z_BINARY 0
|
||||
#define Z_TEXT 1
|
||||
#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
|
||||
#define Z_BINARY 0
|
||||
#define Z_TEXT 1
|
||||
#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
|
||||
#define Z_UNKNOWN 2
|
||||
|
||||
/**
|
||||
|
@ -1139,7 +1139,7 @@ int inflateBack(z_streamp strm, in_func in, void *in_desc, out_func out,
|
|||
*/
|
||||
int inflateBackEnd(z_streamp strm);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Return flags indicating compile-time options.
|
||||
*
|
||||
* Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
|
||||
|
@ -1160,10 +1160,13 @@ int inflateBackEnd(z_streamp strm);
|
|||
* 14,15: 0 (reserved)
|
||||
*
|
||||
* Library content (indicates missing functionality):
|
||||
*
|
||||
* 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
|
||||
* deflate code when not needed)
|
||||
* 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
|
||||
* and decode gzip streams (to avoid linking crc code)
|
||||
* deflate code when not needed)
|
||||
*
|
||||
* 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't
|
||||
* detect and decode gzip streams (to avoid linking crc code)
|
||||
*
|
||||
* 18-19: 0 (reserved)
|
||||
*
|
||||
* Operation variations (changes in library functionality):
|
||||
|
@ -1685,12 +1688,11 @@ uLong adler32_combine(uLong adler1, uLong adler2, int64_t len2);
|
|||
*
|
||||
* Usage example:
|
||||
*
|
||||
* uLong crc = crc32(0L, Z_NULL, 0);
|
||||
*
|
||||
* while (read_buffer(buffer, length) != EOF) {
|
||||
* crc = crc32(crc, buffer, length);
|
||||
* }
|
||||
* if (crc != original_crc) error();
|
||||
* uLong crc = crc32(0L, Z_NULL, 0);
|
||||
* while (read_buffer(buffer, length) != EOF) {
|
||||
* crc = crc32(crc, buffer, length);
|
||||
* }
|
||||
* if (crc != original_crc) error();
|
||||
*/
|
||||
uLong crc32(uLong crc, const Bytef *buf, uInt len);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue