diff options
Diffstat (limited to 'lib/erl_interface/src/misc/ei_printterm.c')
-rw-r--r-- | lib/erl_interface/src/misc/ei_printterm.c | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c new file mode 100644 index 0000000000..8d0eef5e79 --- /dev/null +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -0,0 +1,342 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + * + + */ +/* + * Function: + * ei_print_term to print out a binary coded term + */ + +#ifdef VXWORKS +#include <vxWorks.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> + +#ifdef VRTX +#define __READY_EXTENSIONS__ +#include <errno.h> +#endif + +#include "eidef.h" +#include "eiext.h" +#include "ei_printterm.h" +#include "ei_malloc.h" + +#define BINPRINTSIZE 30 + +/* + * PRINT out a binary term (hacked from 'erl'_print_term) + */ + +static int print_string(FILE* fp, ei_x_buff* x, char* s, int len); +static int print_term(FILE* fp, ei_x_buff* x, + const char* buf, int* index); + +static void xputc(char c, FILE* fp, ei_x_buff* x) +{ + if (fp != NULL) + putc(c, fp); + else + ei_x_append_buf(x, &c, 1); +} + +static void xputs(const char* s, FILE* fp, ei_x_buff* x) +{ + if (fp != NULL) + fputs(s, fp); + else + ei_x_append_buf(x, s, strlen(s)); +} + +static int xprintf(FILE* fp, ei_x_buff* x, const char* fmt, ...) +{ + int r = 0; + va_list ap; + va_start(ap, fmt); + if (fp != NULL) { + r = vfprintf(fp, fmt, ap); + } else { + /* FIXME always enough in buffer??? */ + char tmpbuf[2000]; + r = vsprintf(tmpbuf, fmt, ap); + ei_x_append_buf(x, tmpbuf, strlen(tmpbuf)); + } + va_end(ap); + return r; +} + +static char *ei_big_to_str(erlang_big *b) +{ + int buf_len; + char *s,*buf; + unsigned short *sp; + int i; + + buf_len = 64+b->is_neg+10*b->arity; + if ( (buf=malloc(buf_len)) == NULL) return NULL; + + memset(buf,(char)0,buf_len); + + s = buf; + if ( b->is_neg ) + s += sprintf(s,"-"); + s += sprintf(s,"#integer(%d) = {",b->arity); + for(sp=b->digits,i=0;i<b->arity;i++) { + s += sprintf(s,"%d",sp[i]); + if ( (i+1) != b->arity ) + s += sprintf(s,","); + } + s += sprintf(s,"}"); + return buf; +} + +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+1], *p; + int ch_written = 0; /* counter of written chars */ + erlang_pid pid; + erlang_port port; + erlang_ref ref; + double d; + long l; + + int tindex = *index; + + /* use temporary index for multiple (and failable) decodes */ + + if (fp == NULL && x == NULL) return -1; + + doquote = 0; + ei_get_type_internal(buf, index, &ty, &n); + switch (ty) { + case ERL_ATOM_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: + 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: + 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_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_internal(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; + --m; + for (i = 0; i < m; ++i) { + ch_written += xprintf(fp, x, "%d,", p[i]); + } + ch_written += xprintf(fp, x, "%d", p[i]); + if (l > BINPRINTSIZE) + ch_written += xprintf(fp, x, ",..."); + xputc('>', fp, x); ++ch_written; + ei_free(p); + 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; + + b = ei_alloc_big(n); + 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: + if (ei_decode_double(buf, index, &d) < 0) goto err; + ch_written += xprintf(fp, x, "%f", d); + break; + default: + goto err; + } + return ch_written; + err: + return -1; +} + +static int print_string(FILE* fp, ei_x_buff* x, char* s, int len) +{ + int ch_written = 0; /* counter of written chars */ + + xputc('"', fp, x); + ++ch_written; + for (; len > 0; ++s, --len) { + int c = *s; + if (c >= ' ') { + xputc((char)c, fp, x); ++ch_written; } + else { + switch (c) { + case '\n': xputs("\\n", fp, x); ch_written += 2; break; + case '\r': xputs("\\r", fp, x); ch_written += 2; break; + case '\t': xputs("\\t", fp, x); ch_written += 2; break; + case '\v': xputs("\\v", fp, x); ch_written += 2; break; + case '\b': xputs("\\b", fp, x); ch_written += 2; break; + case '\f': xputs("\\f", fp, x); ch_written += 2; break; + break; + default: + ch_written += xprintf(fp, x, "\\x%x", c); + break; + } + } + } + xputc('"', fp, x); ch_written++; + return ch_written; +} + +/* ------------------------------------------ */ + +/* + * skip a binary term + */ + + +int ei_print_term(FILE *fp, const char* buf, int* index) +{ + return print_term(fp, NULL, buf, index); +} + +int ei_s_print_term(char** s, const char* buf, int* index) +{ + int r; + ei_x_buff x; + if (*s != NULL) { + x.buff = *s; + x.index = 0; + x.buffsz = BUFSIZ; + } else { + ei_x_new(&x); + } + r = print_term(NULL, &x, buf, index); + ei_x_append_buf(&x, "", 1); /* append '\0' */ + *s = x.buff; + return r; +} |