in lib/erl_interface/src/misc/ei_printterm.c [111:359]
static int print_term(FILE* fp, ei_x_buff* x,
const char* buf, int* index)
{
int i, doquote, n, m, ty, r;
char a[MAXATOMLEN], *p;
int ch_written = 0; /* counter of written chars */
erlang_pid pid;
erlang_port port;
erlang_ref ref;
erlang_fun fun;
double d;
long l;
const char* delim;
int tindex = *index;
/* use temporary index for multiple (and failable) decodes */
if (fp == NULL && x == NULL) return -1;
doquote = 0;
ei_get_type(buf, index, &ty, &n);
switch (ty) {
case ERL_ATOM_EXT:
case ERL_ATOM_UTF8_EXT:
case ERL_SMALL_ATOM_EXT:
case ERL_SMALL_ATOM_UTF8_EXT:
if (ei_decode_atom(buf, index, a) < 0)
goto err;
doquote = !islower((int)a[0]);
for (p = a; !doquote && *p != '\0'; ++p)
doquote = !(isalnum((int)*p) || *p == '_' || *p == '@');
if (doquote) {
xputc('\'', fp, x); ++ch_written;
}
xputs(a, fp, x); ch_written += strlen(a);
if (doquote) {
xputc('\'', fp, x); ++ch_written;
}
break;
case ERL_PID_EXT:
case ERL_NEW_PID_EXT:
if (ei_decode_pid(buf, index, &pid) < 0) goto err;
ch_written += xprintf(fp, x, "<%s.%d.%d>", pid.node,
pid.num, pid.serial);
break;
case ERL_PORT_EXT:
case ERL_NEW_PORT_EXT:
if (ei_decode_port(buf, index, &port) < 0) goto err;
ch_written += xprintf(fp, x, "#Port<%d.%d>", port.id, port.creation);
break;
case ERL_NEW_REFERENCE_EXT:
case ERL_NEWER_REFERENCE_EXT:
case ERL_REFERENCE_EXT:
if (ei_decode_ref(buf, index, &ref) < 0) goto err;
ch_written += xprintf(fp, x, "#Ref<");
for (i = 0; i < ref.len; ++i) {
ch_written += xprintf(fp, x, "%d", ref.n[i]);
if (i < ref.len - 1) {
xputc('.', fp, x); ++ch_written;
}
}
xputc('>', fp, x); ++ch_written;
break;
case ERL_NIL_EXT:
if (ei_decode_list_header(buf, index, &n) < 0) goto err;
ch_written += xprintf(fp, x, "[]");
break;
case ERL_LIST_EXT:
if (ei_decode_list_header(buf, &tindex, &n) < 0) goto err;
xputc('[', fp, x); ch_written++;
for (i = 0; i < n; ++i) {
r = print_term(fp, x, buf, &tindex);
if (r < 0) goto err;
ch_written += r;
if (i < n - 1) {
xputs(", ", fp, x); ch_written += 2;
}
}
if (ei_get_type(buf, &tindex, &ty, &n) < 0) goto err;
if (ty != ERL_NIL_EXT) {
xputs(" | ", fp, x); ch_written += 3;
r = print_term(fp, x, buf, &tindex);
if (r < 0) goto err;
ch_written += r;
} else {
if (ei_decode_list_header(buf, &tindex, &n) < 0) goto err;
}
xputc(']', fp, x); ch_written++;
*index = tindex;
break;
case ERL_STRING_EXT:
p = ei_malloc(n+1);
if (p == NULL) goto err;
if (ei_decode_string(buf, index, p) < 0) {
ei_free(p);
goto err;
}
ch_written += print_string(fp, x, p, n);
ei_free(p);
break;
case ERL_SMALL_TUPLE_EXT:
case ERL_LARGE_TUPLE_EXT:
if (ei_decode_tuple_header(buf, &tindex, &n) < 0) goto err;
xputc('{', fp, x); ch_written++;
for (i = 0; i < n; ++i) {
r = print_term(fp, x, buf, &tindex);
if (r < 0) goto err;
ch_written += r;
if (i < n-1) {
xputs(", ", fp, x); ch_written += 2;
}
}
*index = tindex;
xputc('}', fp, x); ch_written++;
break;
case ERL_BINARY_EXT:
p = ei_malloc(n);
if (p == NULL) goto err;
if (ei_decode_binary(buf, index, p, &l) < 0) {
ei_free(p);
goto err;
}
ch_written += xprintf(fp, x, "#Bin<");
if (l > BINPRINTSIZE)
m = BINPRINTSIZE;
else
m = l;
delim = "";
for (i = 0; i < m; ++i) {
ch_written += xprintf(fp, x, "%s%u", delim, (unsigned char)p[i]);
delim = ",";
}
if (l > BINPRINTSIZE)
ch_written += xprintf(fp, x, ",...");
xputc('>', fp, x); ++ch_written;
ei_free(p);
break;
case ERL_BIT_BINARY_EXT: {
const unsigned char* cp;
size_t bits;
unsigned int bitoffs;
int trunc = 0;
if (ei_decode_bitstring(buf, index, (const char**)&cp, &bitoffs, &bits) < 0
|| bitoffs != 0) {
goto err;
}
ch_written += xprintf(fp, x, "#Bits<");
if ((bits+7) / 8 > BINPRINTSIZE) {
m = BINPRINTSIZE;
trunc = 1;
}
else
m = bits / 8;
delim = "";
for (i = 0; i < m; ++i) {
ch_written += xprintf(fp, x, "%s%u", delim, cp[i]);
delim = ",";
}
if (trunc)
ch_written += xprintf(fp, x, ",...");
else {
bits %= 8;
if (bits)
ch_written += xprintf(fp, x, "%s%u:%u", delim,
(cp[i] >> (8-bits)), bits);
}
xputc('>', fp, x); ++ch_written;
break;
}
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
if (ei_decode_long(buf, index, &l) < 0) goto err;
ch_written += xprintf(fp, x, "%ld", l);
break;
case ERL_SMALL_BIG_EXT:
case ERL_LARGE_BIG_EXT:
{
erlang_big *b;
char *ds;
if ( (b = ei_alloc_big(n)) == NULL) goto err;
if (ei_decode_big(buf, index, b) < 0) {
ei_free_big(b);
goto err;
}
if ( (ds = ei_big_to_str(b)) == NULL ) {
ei_free_big(b);
goto err;
}
ch_written += xprintf(fp, x, ds);
free(ds);
ei_free_big(b);
}
break;
case ERL_FLOAT_EXT:
case NEW_FLOAT_EXT:
if (ei_decode_double(buf, index, &d) < 0) goto err;
ch_written += xprintf(fp, x, "%f", d);
break;
case ERL_MAP_EXT:
if (ei_decode_map_header(buf, &tindex, &n) < 0) goto err;
ch_written += xprintf(fp, x, "#{");
for (i = 0; i < n; ++i) {
r = print_term(fp, x, buf, &tindex);
if (r < 0) goto err;
ch_written += r;
ch_written += xprintf(fp, x, " => ");
r = print_term(fp, x, buf, &tindex);
if (r < 0) goto err;
ch_written += r;
if (i < n-1) {
xputs(", ", fp, x); ch_written += 2;
}
}
*index = tindex;
xputc('}', fp, x); ch_written++;
break;
case ERL_FUN_EXT:
case ERL_NEW_FUN_EXT:
case ERL_EXPORT_EXT:
if (ei_decode_fun(buf, &tindex, &fun) < 0) goto err;
if (fun.type == EI_FUN_EXPORT) {
ch_written += xprintf(fp, x, "fun %s:%s/%ld",
fun.module,
fun.u.exprt.func,
fun.arity);
} else {
ch_written += xprintf(fp, x, "#Fun{%s.%ld.%lu}",
fun.module,
fun.u.closure.index,
fun.u.closure.uniq);
}
*index = tindex;
break;
default:
goto err;
}
return ch_written;
err:
return -1;
}