Decode printer options into a printer_options struct

This commit is contained in:
Lassi Kortela 2019-08-25 17:19:47 +03:00
parent 49e0a3ad1f
commit 726b7cad29
2 changed files with 86 additions and 71 deletions

View File

@ -2622,7 +2622,7 @@ static void lisp_init(size_t initial_heapsize)
Fsym = symbol("F"); Fsym = symbol("F");
set(printprettysym = symbol("*print-pretty*"), FL_T); set(printprettysym = symbol("*print-pretty*"), FL_T);
set(printreadablysym = symbol("*print-readably*"), FL_T); set(printreadablysym = symbol("*print-readably*"), FL_T);
set(printwidthsym = symbol("*print-width*"), fixnum(print_width)); set(printwidthsym = symbol("*print-width*"), fixnum(80));
set(printlengthsym = symbol("*print-length*"), FL_F); set(printlengthsym = symbol("*print-length*"), FL_F);
set(printlevelsym = symbol("*print-level*"), FL_F); set(printlevelsym = symbol("*print-level*"), FL_F);
builtins_table_sym = symbol("*builtins*"); builtins_table_sym = symbol("*builtins*");

155
c/print.h
View File

@ -1,28 +1,34 @@
extern void *memrchr(const void *s, int c, size_t n); extern void *memrchr(const void *s, int c, size_t n);
// Printer state struct printer_options {
static struct printer { // *print-readably* -- use `write` repr instead of `display` repr
int readably;
// *print-pretty* -- indent instead of printing everything on one
// *long line
int pretty;
// *print-width* -- maximum line length when indenting, ignored when not
int width;
// *print-length* -- truncate lists after N items and write "..."
fixnum_t length;
// *print-level* -- print only the outermost N levels of nested structures
fixnum_t level;
};
struct printer {
int line; int line;
int column; int column;
unsigned int level; unsigned int level;
unsigned int cycle_labels; unsigned int cycle_labels;
struct htable cycle_traversed; struct htable cycle_traversed;
} pr; struct printer_options opts;
};
// *print-readably* -- use `write` repr instead of `display` repr // Printer state during one printer run
static int print_readably; static struct printer pr;
// *print-pretty* -- indent instead of printing everything on one long line
static int print_pretty;
// *print-width* -- maximum line length when indenting, ignored when not
static int print_width;
// *print-length* -- truncate lists after N items and write "..."
static fixnum_t print_length;
// *print-level* -- print only the outermost N levels of nested structures
static fixnum_t print_level;
static void outc(char c, struct ios *f) static void outc(char c, struct ios *f)
{ {
@ -50,7 +56,7 @@ static int outindent(int n, struct ios *f)
int n0; int n0;
// move back to left margin if we get too indented // move back to left margin if we get too indented
if (n > print_width - 12) if (n > pr.opts.width - 12)
n = 2; n = 2;
n0 = n; n0 = n;
ios_putc('\n', f); ios_putc('\n', f);
@ -310,7 +316,7 @@ static void print_pair(struct ios *f, value_t v)
n_unindented = 1; n_unindented = 1;
while (1) { while (1) {
cd = cdr_(v); cd = cdr_(v);
if (print_length >= 0 && n >= print_length && cd != NIL) { if (pr.opts.length >= 0 && n >= pr.opts.length && cd != NIL) {
outsn("...)", f, 4); outsn("...)", f, 4);
break; break;
} }
@ -326,7 +332,7 @@ static void print_pair(struct ios *f, value_t v)
break; break;
} }
if (!print_pretty || ((head == LAMBDA) && n == 0)) { if (!pr.opts.pretty || ((head == LAMBDA) && n == 0)) {
// never break line before lambda-list // never break line before lambda-list
ind = 0; ind = 0;
} else { } else {
@ -334,12 +340,12 @@ static void print_pair(struct ios *f, value_t v)
nextsmall = smallp(car_(cd)); nextsmall = smallp(car_(cd));
thistiny = tinyp(car_(v)); thistiny = tinyp(car_(v));
ind = ind =
(((pr.line > last_line) || (pr.column > print_width / 2 && (((pr.line > last_line) || (pr.column > pr.opts.width / 2 &&
!nextsmall && !thistiny && n > 0)) || !nextsmall && !thistiny && n > 0)) ||
(pr.column > print_width - 4) || (pr.column > pr.opts.width - 4) ||
(est != -1 && (pr.column + est > print_width - 2)) || (est != -1 && (pr.column + est > pr.opts.width - 2)) ||
((head == LAMBDA) && !nextsmall) || ((head == LAMBDA) && !nextsmall) ||
@ -395,7 +401,7 @@ void fl_print_child(struct ios *f, value_t v)
{ {
char *name; char *name;
if (print_level >= 0 && pr.level >= print_level && if (pr.opts.level >= 0 && pr.level >= pr.opts.level &&
(iscons(v) || isvector(v) || isclosure(v))) { (iscons(v) || isvector(v) || isclosure(v))) {
outc('#', f); outc('#', f);
return; return;
@ -408,7 +414,7 @@ void fl_print_child(struct ios *f, value_t v)
break; break;
case TAG_SYM: case TAG_SYM:
name = symbol_name(v); name = symbol_name(v);
if (!print_readably) if (!pr.opts.readably)
outs(name, f); outs(name, f);
else if (ismanaged(v)) { else if (ismanaged(v)) {
outsn("#:", f, 2); outsn("#:", f, 2);
@ -426,12 +432,12 @@ void fl_print_child(struct ios *f, value_t v)
} else if (v == FL_EOF) { } else if (v == FL_EOF) {
outsn("#<eof>", f, 6); outsn("#<eof>", f, 6);
} else if (isbuiltin(v)) { } else if (isbuiltin(v)) {
if (print_readably) if (pr.opts.readably)
outsn("#.", f, 2); outsn("#.", f, 2);
outs(builtin_names[uintval(v)], f); outs(builtin_names[uintval(v)], f);
} else { } else {
assert(isclosure(v)); assert(isclosure(v));
if (print_readably) { if (pr.opts.readably) {
struct function *fn; struct function *fn;
char *data; char *data;
size_t i, sz; size_t i, sz;
@ -472,7 +478,7 @@ void fl_print_child(struct ios *f, value_t v)
case TAG_CVALUE: case TAG_CVALUE:
case TAG_VECTOR: case TAG_VECTOR:
case TAG_CONS: case TAG_CONS:
if (print_readably && write_cycle_prefix(f, v)) if (pr.opts.readably && write_cycle_prefix(f, v))
break; break;
if (isvector(v)) { if (isvector(v)) {
int newindent, est, sz, i; int newindent, est, sz, i;
@ -481,20 +487,21 @@ void fl_print_child(struct ios *f, value_t v)
newindent = pr.column; newindent = pr.column;
sz = vector_size(v); sz = vector_size(v);
for (i = 0; i < sz; i++) { for (i = 0; i < sz; i++) {
if (print_length >= 0 && i >= print_length && i < sz - 1) { if (pr.opts.length >= 0 && i >= pr.opts.length &&
i < sz - 1) {
outsn("...", f, 3); outsn("...", f, 3);
break; break;
} }
fl_print_child(f, vector_elt(v, i)); fl_print_child(f, vector_elt(v, i));
if (i < sz - 1) { if (i < sz - 1) {
if (!print_pretty) { if (!pr.opts.pretty) {
outc(' ', f); outc(' ', f);
} else { } else {
est = lengthestimate(vector_elt(v, i + 1)); est = lengthestimate(vector_elt(v, i + 1));
if (pr.column > print_width - 4 || if (pr.column > pr.opts.width - 4 ||
(est != -1 && (est != -1 &&
(pr.column + est > print_width - 2)) || (pr.column + est > pr.opts.width - 2)) ||
(pr.column > print_width / 2 && (pr.column > pr.opts.width / 2 &&
!smallp(vector_elt(v, i + 1)) && !smallp(vector_elt(v, i + 1)) &&
!tinyp(vector_elt(v, i)))) !tinyp(vector_elt(v, i))))
newindent = outindent(newindent, f); newindent = outindent(newindent, f);
@ -644,7 +651,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
{ {
if (type == bytesym) { if (type == bytesym) {
unsigned char ch = *(unsigned char *)data; unsigned char ch = *(unsigned char *)data;
if (!print_readably) if (!pr.opts.readably)
outc(ch, f); outc(ch, f);
else if (weak) else if (weak)
pr.column += ios_printf(f, "#x%hhx", ch); pr.column += ios_printf(f, "#x%hhx", ch);
@ -656,7 +663,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
size_t nb = u8_toutf8(seq, sizeof(seq), &wc, 1); size_t nb = u8_toutf8(seq, sizeof(seq), &wc, 1);
seq[nb] = '\0'; seq[nb] = '\0';
if (!print_readably) { if (!pr.opts.readably) {
// TODO: better multibyte handling // TODO: better multibyte handling
if (wc == 0) if (wc == 0)
ios_putc(0, f); ios_putc(0, f);
@ -710,7 +717,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
rep = sign_bit(d) ? "-nan.0" : "+nan.0"; rep = sign_bit(d) ? "-nan.0" : "+nan.0";
else else
rep = sign_bit(d) ? "-inf.0" : "+inf.0"; rep = sign_bit(d) ? "-inf.0" : "+inf.0";
if (type == floatsym && print_readably && !weak) if (type == floatsym && pr.opts.readably && !weak)
pr.column += ios_printf(f, "#%s(%s)", symbol_name(type), rep); pr.column += ios_printf(f, "#%s(%s)", symbol_name(type), rep);
else else
outs(rep, f); outs(rep, f);
@ -719,7 +726,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
outsn("-0.0", f, 4); outsn("-0.0", f, 4);
else else
outsn("0.0", f, 3); outsn("0.0", f, 3);
if (type == floatsym && print_readably && !weak) if (type == floatsym && pr.opts.readably && !weak)
outc('f', f); outc('f', f);
} else { } else {
int hasdec; int hasdec;
@ -729,7 +736,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
outs(buf, f); outs(buf, f);
if (!hasdec) if (!hasdec)
outsn(".0", f, 2); outsn(".0", f, 2);
if (type == floatsym && print_readably && !weak) if (type == floatsym && pr.opts.readably && !weak)
outc('f', f); outc('f', f);
} }
} else if (type == uint64sym } else if (type == uint64sym
@ -738,7 +745,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
#endif #endif
) { ) {
uint64_t ui64 = *(uint64_t *)data; uint64_t ui64 = *(uint64_t *)data;
if (weak || !print_readably) if (weak || !pr.opts.readably)
pr.column += ios_printf(f, "%llu", ui64); pr.column += ios_printf(f, "%llu", ui64);
else else
pr.column += ios_printf(f, "#%s(%llu)", symbol_name(type), ui64); pr.column += ios_printf(f, "#%s(%llu)", symbol_name(type), ui64);
@ -750,7 +757,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
pr.column += ios_printf(f, "#<%s>", symbol_name(type)); pr.column += ios_printf(f, "#<%s>", symbol_name(type));
} else { } else {
int64_t i64 = conv_to_int64(data, nt); int64_t i64 = conv_to_int64(data, nt);
if (weak || !print_readably) if (weak || !pr.opts.readably)
pr.column += ios_printf(f, "%lld", i64); pr.column += ios_printf(f, "%lld", i64);
else else
pr.column += pr.column +=
@ -771,7 +778,7 @@ static void cvalue_printdata(struct ios *f, void *data, size_t len,
cnt = elsize ? len / elsize : 0; cnt = elsize ? len / elsize : 0;
} }
if (eltype == bytesym) { if (eltype == bytesym) {
if (!print_readably) { if (!pr.opts.readably) {
ios_write(f, data, len); ios_write(f, data, len);
/* /*
char *nl = memrchr(data, '\n', len); char *nl = memrchr(data, '\n', len);
@ -843,7 +850,7 @@ static void cvalue_print(struct ios *f, value_t v)
pr.column += pr.column +=
ios_printf(f, "#<builtin @#x%08zx>", (size_t)(builtin_t)fptr); ios_printf(f, "#<builtin @#x%08zx>", (size_t)(builtin_t)fptr);
} else { } else {
if (!print_readably) { if (!pr.opts.readably) {
outs(symbol_name(label), f); outs(symbol_name(label), f);
} else { } else {
outsn("#fn(", f, 4); outsn("#fn(", f, 4);
@ -861,42 +868,19 @@ static void cvalue_print(struct ios *f, value_t v)
} }
} }
void fl_print(struct ios *f, value_t v) void print_with_options(struct ios *f, value_t v,
struct printer_options *opts)
{ {
value_t pl; memcpy(&pr.opts, opts, sizeof(pr.opts));
print_pretty = (symbol_value(printprettysym) != FL_F);
print_readably = (symbol_value(printreadablysym) != FL_F);
pl = symbol_value(printlengthsym);
if (isfixnum(pl))
print_length = numval(pl);
else
print_length = -1;
pl = symbol_value(printlevelsym);
if (isfixnum(pl))
print_level = numval(pl);
else
print_level = -1;
pl = symbol_value(printwidthsym);
if (isfixnum(pl))
print_width = numval(pl);
else
print_width = 80;
if (print_width < 20)
print_width = 20;
pr.level = 0; pr.level = 0;
pr.cycle_labels = 0; pr.cycle_labels = 0;
if (print_readably) if (pr.opts.readably)
print_traverse(v); print_traverse(v);
pr.line = pr.column = 0; pr.line = pr.column = 0;
fl_print_child(f, v); fl_print_child(f, v);
if (print_level >= 0 || print_length >= 0) { if (pr.opts.level >= 0 || pr.opts.length >= 0) {
memset(consflags, 0, memset(consflags, 0,
4 * bitvector_nwords(heapsize / sizeof(struct cons))); 4 * bitvector_nwords(heapsize / sizeof(struct cons)));
} }
@ -906,3 +890,34 @@ void fl_print(struct ios *f, value_t v)
htable_reset(&pr.cycle_traversed, 32); htable_reset(&pr.cycle_traversed, 32);
} }
} }
void fl_print(struct ios *f, value_t v)
{
struct printer_options opts;
value_t pl;
opts.pretty = (symbol_value(printprettysym) != FL_F);
opts.readably = (symbol_value(printreadablysym) != FL_F);
pl = symbol_value(printlengthsym);
if (isfixnum(pl))
opts.length = numval(pl);
else
opts.length = -1;
pl = symbol_value(printlevelsym);
if (isfixnum(pl))
opts.level = numval(pl);
else
opts.level = -1;
pl = symbol_value(printwidthsym);
if (isfixnum(pl))
opts.width = numval(pl);
else
opts.width = 80;
if (opts.width < 20)
opts.width = 20;
print_with_options(f, v, &opts);
}