int ei_x_new(ei_x_buff* x) { x->buff = ei_malloc(ei_x_extra); x->buffsz = ei_x_extra; x->index = 0; return x->buff != NULL ? 0 : -1; }
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; 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: 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_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; 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; default: goto err; } return ch_written; err: return -1; }
static int read_args(const char* fmt, va_list ap, union arg **argp) { const char* p = fmt; int arg_count = 0; union arg* args; int i = 0; /* Count the number of format strings. Assume null terminated string. */ *argp = NULL; while (*p) if (*p++ == '~') arg_count++; if (!arg_count) { return 0; } /* Allocate space for the arguments */ args = (union arg*)ei_malloc(arg_count * sizeof(union arg)); if (!args) return -1; p = fmt; /* Start again and fill array */ while (*p) { if (*p++ == '~') { if (!*p) { ei_free(args); return -1; /* Error, string not complete */ } switch (*p++) { case 'c': args[i++].c = (char) va_arg(ap, int); break; case 'a': case 's': args[i++].s = va_arg(ap, char*); break; case 'i': #ifdef EI_64BIT args[i++].l = (long) va_arg(ap, int); break; #endif case 'l': args[i++].l = va_arg(ap, long); break; case 'u': args[i++].u = va_arg(ap, unsigned long); break; case 'f': /* float is expanded to double (C calling conventions) */ case 'd': args[i++].d = va_arg(ap, double); break; case 'p': args[i++].pid = va_arg(ap, erlang_pid*); break; default: ei_free(args); /* Invalid specifier */ return -1; } } } *argp = args; return 0; }
int ei_decode_fun(const char *buf, int *index, erlang_fun *p) { const char *s = buf + *index; const char *s0 = s; int i, ix, ix0, n; switch (get8(s)) { case ERL_FUN_EXT: /* mark as old (R7 and older) external fun */ if (p != NULL) p->arity = -1; /* first number of free vars (environment) */ n = get32be(s); /* then the pid */ ix = 0; if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0) return -1; /* then the module (atom) */ if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0) return -1; /* then the index */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->index)) < 0) return -1; /* then the uniq */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0) return -1; /* finally the free vars */ ix0 = ix; for (i = 0; i < n; ++i) { if (ei_skip_term(s, &ix) < 0) return -1; } if (p != NULL) { p->n_free_vars = n; p->free_var_len = ix - ix0; p->free_vars = ei_malloc(ix - ix0); /* FIXME check result */ memcpy(p->free_vars, s + ix0, ix - ix0); } s += ix; *index += s-s0; return 0; break; case ERL_NEW_FUN_EXT: /* first total size */ n = get32be(s); /* then the arity */ i = get8(s); if (p != NULL) p->arity = i; /* then md5 */ if (p != NULL) memcpy(p->md5, s, 16); s += 16; /* then index */ i = get32be(s); if (p != NULL) p->index = i; /* then the number of free vars (environment) */ i = get32be(s); if (p != NULL) p->n_free_vars = i; /* then the module (atom) */ ix = 0; if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0) return -1; /* then the old_index */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->old_index)) < 0) return -1; /* then the old_uniq */ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0) return -1; /* the the pid */ if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0) return -1; /* finally the free vars */ s += ix; n = n - (s - s0) + 1; if (p != NULL) { p->free_var_len = n; if (n > 0) { p->free_vars = malloc(n); /* FIXME check result */ memcpy(p->free_vars, s, n); } } *index += s-s0; return 0; break; default: return -1; } }
int ei_decode_fun(const char *buf, int *index, erlang_fun *p) { const char *s = buf + *index; const char *s0 = s; int i, ix, ix0, n; erlang_pid* p_pid; char* p_module; erlang_char_encoding* p_module_org_enc; long* p_index; long* p_uniq; long* p_old_index; if (p != NULL) { p_pid = &p->pid; p_module = &p->module[0]; p_module_org_enc = &p->module_org_enc; p_index = &p->index; p_uniq = &p->uniq; p_old_index = &p->old_index; } else { p_pid = NULL; p_module = NULL; p_module_org_enc = NULL; p_index = NULL; p_uniq = NULL; p_old_index = NULL; } switch (get8(s)) { case ERL_FUN_EXT: /* mark as old (R7 and older) external fun */ if (p != NULL) p->arity = -1; /* first number of free vars (environment) */ n = get32be(s); /* then the pid */ ix = 0; if (ei_decode_pid(s, &ix, p_pid) < 0) return -1; /* then the module (atom) */ if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, p_module_org_enc, NULL) < 0) return -1; /* then the index */ if (ei_decode_long(s, &ix, p_index) < 0) return -1; /* then the uniq */ if (ei_decode_long(s, &ix, p_uniq) < 0) return -1; /* finally the free vars */ ix0 = ix; for (i = 0; i < n; ++i) { if (ei_skip_term(s, &ix) < 0) return -1; } if (p != NULL) { p->n_free_vars = n; p->free_var_len = ix - ix0; p->free_vars = ei_malloc(ix - ix0); if (!(p->free_vars)) return -1; memcpy(p->free_vars, s + ix0, ix - ix0); } s += ix; *index += s-s0; return 0; break; case ERL_NEW_FUN_EXT: /* first total size */ n = get32be(s); /* then the arity */ i = get8(s); if (p != NULL) p->arity = i; /* then md5 */ if (p != NULL) memcpy(p->md5, s, 16); s += 16; /* then index */ i = get32be(s); if (p != NULL) p->index = i; /* then the number of free vars (environment) */ i = get32be(s); if (p != NULL) p->n_free_vars = i; /* then the module (atom) */ ix = 0; if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8, p_module_org_enc, NULL) < 0) return -1; /* then the old_index */ if (ei_decode_long(s, &ix, p_old_index) < 0) return -1; /* then the old_uniq */ if (ei_decode_long(s, &ix, p_uniq) < 0) return -1; /* the the pid */ if (ei_decode_pid(s, &ix, p_pid) < 0) return -1; /* finally the free vars */ s += ix; n = n - (s - s0) + 1; if (n < 0) return -1; if (p != NULL) { p->free_var_len = n; if (n > 0) { p->free_vars = malloc(n); if (!(p->free_vars)) return -1; memcpy(p->free_vars, s, n); } } s += n; *index += s-s0; return 0; break; default: return -1; } }