ETERM *erl_mk_estring(const char *s, int len) { ETERM *ep; int i; if ((!s) || (len < 0)) return NULL; /* * ASSERT(s != NULL); * ASSERT(len >= 0); */ ep = erl_mk_empty_list(); for (i = len-1; i >= 0; i--) { ETERM* integer; ETERM* cons; integer = erl_alloc_eterm(ERL_INTEGER); ERL_COUNT(integer) = 1; ERL_INT_VALUE(integer) = (unsigned char)s[i]; cons = erl_alloc_eterm(ERL_LIST); ERL_COUNT(cons) = 1; HEAD(cons) = integer; TAIL(cons) = ep; ep = cons; } return ep; }
/* * Create any kind of reference. */ ETERM *__erl_mk_reference (ETERM* t, const char *node, size_t len, unsigned int n[], unsigned int creation) { if (t == NULL) { if (node == NULL) return NULL; t = erl_alloc_eterm(ERL_REF); ERL_COUNT(t) = 1; if (erl_atom_init_latin1(&t->uval.refval.node, node) == NULL) { erl_free_term(t); erl_errno = ENOMEM; return NULL; } } ERL_REF_LEN(t) = len; ERL_REF_NUMBERS(t)[0] = n[0] & 0x3ffff; /* 18 bits */ ERL_REF_NUMBERS(t)[1] = n[1]; ERL_REF_NUMBERS(t)[2] = n[2]; ERL_REF_CREATION(t) = creation; /* 32 bits */ return t; }
ETERM *erl_mk_empty_list(void) { ETERM *ep; ep = erl_alloc_eterm(ERL_EMPTY_LIST); ERL_COUNT(ep) = 1; return ep; }
/* * Create a FLOAT. */ ETERM *erl_mk_float (double d) { ETERM *ep; ep = erl_alloc_eterm(ERL_FLOAT); ERL_COUNT(ep) = 1; ERL_FLOAT_VALUE(ep) = d; return ep; }
/* * Create an INTEGER. Depending on its value it * may end up as a BigNum. */ ETERM *erl_mk_int (int i) { ETERM *ep; ep = erl_alloc_eterm(ERL_INTEGER); ERL_COUNT(ep) = 1; ERL_INT_VALUE(ep) = i; return ep; }
ETERM *erl_mk_ulonglong (unsigned long long i) { ETERM *ep; ep = erl_alloc_eterm(ERL_U_LONGLONG); ERL_COUNT(ep) = 1; ERL_LL_UVALUE(ep) = i; return ep; }
ETERM *erl_mk_uint (unsigned int u) { ETERM *ep; ep = erl_alloc_eterm(ERL_U_INTEGER); ERL_COUNT(ep) = 1; ERL_INT_UVALUE(ep) = u; return ep; }
ETERM *erl_mk_longlong (long long i) { ETERM *ep; ep = erl_alloc_eterm(ERL_LONGLONG); ERL_COUNT(ep) = 1; ERL_LL_VALUE(ep) = i; return ep; }
/* * Create a BINARY. */ ETERM *erl_mk_binary (const char *b, int size) { ETERM *ep; if ((!b) || (size < 0)) return NULL; /* ASSERT(b != NULL); */ ep = erl_alloc_eterm(ERL_BINARY); ERL_COUNT(ep) = 1; ERL_BIN_SIZE(ep) = size; ERL_BIN_PTR(ep) = (unsigned char *) erl_malloc(size); memcpy(ERL_BIN_PTR(ep), b, size); return ep; }
/* * Create an ATOM */ ETERM *erl_mk_atom (const char *s) { ETERM *ep; /* ASSERT(s != NULL); */ if (!s) return NULL; ep = erl_alloc_eterm(ERL_ATOM); ERL_COUNT(ep) = 1; if (erl_atom_init_latin1(&ep->uval.aval.d, s) == NULL) { erl_free_term(ep); erl_errno = ENOMEM; return NULL; } return ep; }
/* * Create a FLOAT. */ ETERM *erl_mk_float (double d) { ETERM *ep; #if defined(HAVE_ISFINITE) /* Erlang does not handle Inf and NaN, so we return an error * rather than letting the Erlang VM complain about a bad external * term. */ if(!isfinite(d)) { return NULL; } #endif ep = erl_alloc_eterm(ERL_FLOAT); ERL_COUNT(ep) = 1; ERL_FLOAT_VALUE(ep) = d; return ep; }
/* * Construct a new list by CONS'ing a HEAD on * to the TAIL. Bump the reference counter on * the head and tail object. Note that we allow * non-well formed lists to be created. */ ETERM *erl_cons(ETERM *hd, ETERM *tl) { ETERM *ep; if ((!hd) || (!tl)) return NULL; /* * ASSERT(hd != NULL); * ASSERT(tl != NULL); */ ep = erl_alloc_eterm(ERL_LIST); ERL_COUNT(ep) = 1; HEAD(ep) = hd; TAIL(ep) = tl; ERL_COUNT(hd)++; ERL_COUNT(tl)++; return ep; }
/* * Create an empty VARIABLE. */ ETERM *erl_mk_var(const char *s) { ETERM *ep; if (!s) return NULL; /* ASSERT(s != NULL); */ ep = erl_alloc_eterm(ERL_VARIABLE); ERL_COUNT(ep) = 1; ERL_VAR_LEN(ep) = strlen(s); if ((ERL_VAR_NAME(ep) = strsave(s)) == NULL) { erl_free_term(ep); erl_errno = ENOMEM; return NULL; } ERL_VAR_VALUE(ep) = (ETERM *) NULL; return ep; }
/* * Create a TUPLE. For each element in the tuple * bump its reference counter. */ ETERM *erl_mk_tuple (ETERM **arr,int size) { ETERM *ep; int i; if ((!arr) || (size < 0)) return NULL; for (i=0; i<size; i++) if (!arr[i]) return NULL; /* ASSERT(arr != NULL); */ ep = erl_alloc_eterm(ERL_TUPLE); ERL_COUNT(ep) = 1; ERL_TUPLE_SIZE(ep) = size; ERL_TUPLE_ELEMS(ep) = (ETERM**) erl_malloc((size) * (sizeof(ETERM*))); for (i = 0; i < size; i++) { /* ASSERT(arr[i] != NULL); */ ERL_COUNT(arr[i])++; ERL_TUPLE_ELEMENT(ep, i) = arr[i]; } return ep; }
/* * Create a PORT. */ ETERM *erl_mk_port(const char *node, unsigned int number, unsigned char creation) { ETERM *ep; if (!node) return NULL; /* ASSERT(node != NULL); */ ep = erl_alloc_eterm(ERL_PORT); ERL_COUNT(ep) = 1; if (erl_atom_init_latin1(&ep->uval.portval.node, node) == NULL) { erl_free_term(ep); erl_errno = ENOMEM; return NULL; } erl_mk_port_helper(ep, number, creation); return ep; }
ETERM *erl_iolist_to_binary (const ETERM* term) { ETERM *dest; int size; char* ptr; if (!term) return NULL; /* ASSERT(term != NULL); */ /* * Verify that the term is an I/O list and get its length. */ size = erl_iolist_length(term); if (size == -1) { return NULL; } /* * Allocate the binary and copy the contents of the I/O list into it. */ dest = erl_alloc_eterm(ERL_BINARY); ERL_COUNT(dest) = 1; ERL_BIN_SIZE(dest) = size; ptr = (char *)erl_malloc(size); ERL_BIN_PTR(dest) = (unsigned char *)ptr; iolist_to_buf(term, &ptr); /* * If ptr doesn't point exactly one byte beyond the end of the * binary, something must be seriously wrong. */ if (ERL_BIN_PTR(dest) + size != (unsigned char *) ptr) return NULL; /* ASSERT(ERL_BIN_PTR(dest) + size == (unsigned char *) ptr); */ return dest; }
int main(void) #endif { ei_x_buff eix; int index = 0; ETERM **etermpp = NULL, *etermp = NULL; char *charp = NULL; unsigned char uchar, **ucharpp = NULL, *ucharp = NULL; void *voidp = NULL; Erl_Heap *erl_heapp = NULL; int intx = 0; int *intp = NULL; unsigned int uintx, *uintp; unsigned long *ulongp = NULL; long longx = 0; double doublex = 0.0; short shortx = 42; FILE *filep = NULL; Erl_IpAddr erl_ipaddr = NULL; ErlMessage *erlmessagep = NULL; ErlConnect *erlconnectp = NULL; struct hostent *hostp = NULL; struct in_addr *inaddrp = NULL; /* Converion to erl_interface format is in liberl_interface */ intx = erl_errno; ei_encode_term(charp, &index, voidp); ei_x_encode_term(&eix, voidp); ei_decode_term(charp, &index, voidp); erl_init(voidp, longx); erl_connect_init(intx, charp,shortx); erl_connect_xinit(charp,charp,charp,erl_ipaddr,charp,shortx); erl_connect(charp); erl_xconnect(erl_ipaddr,charp); erl_close_connection(intx); erl_receive(intx, ucharp, intx); erl_receive_msg(intx, ucharp, intx, erlmessagep); erl_xreceive_msg(intx, ucharpp, intp, erlmessagep); erl_send(intx, etermp, etermp); erl_reg_send(intx, charp, etermp); erl_rpc(intx,charp,charp,etermp); erl_rpc_to(intx,charp,charp,etermp); erl_rpc_from(intx,intx,erlmessagep); erl_publish(intx); erl_accept(intx,erlconnectp); erl_thiscookie(); erl_thisnodename(); erl_thishostname(); erl_thisalivename(); erl_thiscreation(); erl_unpublish(charp); erl_err_msg(charp); erl_err_quit(charp); erl_err_ret(charp); erl_err_sys(charp); erl_cons(etermp,etermp); erl_copy_term(etermp); erl_element(intx,etermp); erl_hd(etermp); erl_iolist_to_binary(etermp); erl_iolist_to_string(etermp); erl_iolist_length(etermp); erl_length(etermp); erl_mk_atom(charp); erl_mk_binary(charp,intx); erl_mk_empty_list(); erl_mk_estring(charp, intx); erl_mk_float(doublex); erl_mk_int(intx); erl_mk_list(etermpp,intx); erl_mk_pid(charp,uintx,uintx,uchar); erl_mk_port(charp,uintx,uchar); erl_mk_ref(charp,uintx,uchar); erl_mk_long_ref(charp,uintx,uintx,uintx,uchar); erl_mk_string(charp); erl_mk_tuple(etermpp,intx); erl_mk_uint(uintx); erl_mk_var(charp); erl_print_term(filep,etermp); /* erl_sprint_term(charp,etermp); */ erl_size(etermp); erl_tl(etermp); erl_var_content(etermp, charp); erl_format(charp); erl_match(etermp, etermp); erl_global_names(intx, intp); erl_global_register(intx, charp, etermp); erl_global_unregister(intx, charp); erl_global_whereis(intx, charp, charp); erl_init_malloc(erl_heapp,longx); erl_alloc_eterm(uchar); erl_eterm_release(); erl_eterm_statistics(ulongp,ulongp); erl_free_array(etermpp,intx); erl_free_term(etermp); erl_free_compound(etermp); erl_malloc(longx); erl_free(voidp); erl_compare_ext(ucharp, ucharp); erl_decode(ucharp); erl_decode_buf(ucharpp); erl_encode(etermp,ucharp); erl_encode_buf(etermp,ucharpp); erl_ext_size(ucharp); erl_ext_type(ucharp); erl_peek_ext(ucharp,intx); erl_term_len(etermp); erl_gethostbyname(charp); erl_gethostbyaddr(charp, intx, intx); erl_gethostbyname_r(charp, hostp, charp, intx, intp); erl_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp); erl_init_resolve(); erl_distversion(intx); erl_epmd_connect(inaddrp); erl_epmd_port(inaddrp, charp, intp); charp = ERL_ATOM_PTR(etermp); intx = ERL_ATOM_SIZE(etermp); ucharp = ERL_BIN_PTR(etermp); intx = ERL_BIN_SIZE(etermp); etermp = ERL_CONS_HEAD(etermp); etermp = ERL_CONS_TAIL(etermp); intx = ERL_COUNT(etermp); doublex= ERL_FLOAT_VALUE(etermp); uintx = ERL_INT_UVALUE(etermp); intx = ERL_INT_VALUE(etermp); intx = ERL_IS_ATOM(etermp); intx = ERL_IS_BINARY(etermp); intx = ERL_IS_CONS(etermp); intx = ERL_IS_EMPTY_LIST(etermp); intx = ERL_IS_FLOAT(etermp); intx = ERL_IS_INTEGER(etermp); intx = ERL_IS_LIST(etermp); intx = ERL_IS_PID(etermp); intx = ERL_IS_PORT(etermp); intx = ERL_IS_REF(etermp); intx = ERL_IS_TUPLE(etermp); intx = ERL_IS_UNSIGNED_INTEGER(etermp); uchar = ERL_PID_CREATION(etermp); charp = ERL_PID_NODE(etermp); uintx = ERL_PID_NUMBER(etermp); uintx = ERL_PID_SERIAL(etermp); uchar = ERL_PORT_CREATION(etermp); charp = ERL_PORT_NODE(etermp); uintx = ERL_PORT_NUMBER(etermp); uchar = ERL_REF_CREATION(etermp); intx = ERL_REF_LEN(etermp); charp = ERL_REF_NODE(etermp); uintx = ERL_REF_NUMBER(etermp); uintp = ERL_REF_NUMBERS(etermp); etermp = ERL_TUPLE_ELEMENT(etermp,intx); intx = ERL_TUPLE_SIZE(etermp); return BUFSIZ + EAGAIN + EHOSTUNREACH + EINVAL + EIO + EMSGSIZE + ENOMEM + ERL_ATOM + ERL_BINARY + ERL_ERROR + ERL_EXIT + ERL_FLOAT + ERL_INTEGER + ERL_LINK + ERL_LIST + ERL_MSG + ERL_NO_TIMEOUT + ERL_PID + ERL_PORT + ERL_REF + ERL_REG_SEND + ERL_SEND + ERL_SMALL_BIG + ERL_TICK + ERL_TIMEOUT + ERL_TUPLE + ERL_UNLINK + ERL_U_INTEGER + ERL_U_SMALL_BIG + ERL_VARIABLE + ETIMEDOUT + MAXNODELEN + MAXREGLEN; }
/* * FIXME: Deep (the whole tree) or shallow (just the top term) copy? * The documentation never says, but the code as written below will * make a deep copy. This should be documented. */ ETERM *erl_copy_term(const ETERM *ep) { int i; ETERM *cp; if (!ep) return NULL; /* ASSERT(ep != NULL); */ cp = erl_alloc_eterm(ERL_TYPE(ep)); ERL_COUNT(cp) = 1; switch(ERL_TYPE(cp)) { case ERL_INTEGER: case ERL_SMALL_BIG: ERL_INT_VALUE(cp) = ERL_INT_VALUE(ep); break; case ERL_U_INTEGER: case ERL_U_SMALL_BIG: ERL_INT_UVALUE(cp) = ERL_INT_UVALUE(ep); break; case ERL_LONGLONG: ERL_LL_VALUE(cp) = ERL_LL_VALUE(ep); break; case ERL_U_LONGLONG: ERL_LL_UVALUE(cp) = ERL_LL_UVALUE(ep); break; case ERL_FLOAT: ERL_FLOAT_VALUE(cp) = ERL_FLOAT_VALUE(ep); break; case ERL_ATOM: if (!erl_atom_copy(&cp->uval.aval.d, &ep->uval.aval.d)) { erl_free_term(cp); erl_errno = ENOMEM; return NULL; } break; case ERL_PID: /* FIXME: First copy the bit pattern, then duplicate the node name and plug in. Somewhat ugly (also done with port and ref below). */ memcpy(&cp->uval.pidval, &ep->uval.pidval, sizeof(Erl_Pid)); erl_atom_copy(&cp->uval.pidval.node, &ep->uval.pidval.node); ERL_COUNT(cp) = 1; break; case ERL_PORT: memcpy(&cp->uval.portval, &ep->uval.portval, sizeof(Erl_Port)); erl_atom_copy(&cp->uval.portval.node, &ep->uval.portval.node); ERL_COUNT(cp) = 1; break; case ERL_REF: memcpy(&cp->uval.refval, &ep->uval.refval, sizeof(Erl_Ref)); erl_atom_copy(&cp->uval.refval.node, &ep->uval.refval.node); ERL_COUNT(cp) = 1; break; case ERL_LIST: HEAD(cp) = erl_copy_term(HEAD(ep)); TAIL(cp) = erl_copy_term(TAIL(ep)); break; case ERL_EMPTY_LIST: break; case ERL_TUPLE: i = ERL_TUPLE_SIZE(cp) = ERL_TUPLE_SIZE(ep); ERL_TUPLE_ELEMS(cp) = (ETERM**) erl_malloc(i * sizeof(ETERM*)); for(i=0; i < ERL_TUPLE_SIZE(ep); i++) ERL_TUPLE_ELEMENT(cp,i) = erl_copy_term(ERL_TUPLE_ELEMENT(ep, i)); break; case ERL_BINARY: ERL_BIN_SIZE(cp) = ERL_BIN_SIZE(ep); ERL_BIN_PTR(cp) = (unsigned char *) erl_malloc(ERL_BIN_SIZE(ep)); memcpy(ERL_BIN_PTR(cp), ERL_BIN_PTR(ep), ERL_BIN_SIZE(ep)); break; case ERL_FUNCTION: i = ERL_CLOSURE_SIZE(cp) = ERL_CLOSURE_SIZE(ep); ERL_FUN_ARITY(cp) = ERL_FUN_ARITY(ep); ERL_FUN_NEW_INDEX(cp) = ERL_FUN_NEW_INDEX(ep); ERL_FUN_INDEX(cp) = erl_copy_term(ERL_FUN_INDEX(ep)); ERL_FUN_UNIQ(cp) = erl_copy_term(ERL_FUN_UNIQ(ep)); ERL_FUN_CREATOR(cp) = erl_copy_term(ERL_FUN_CREATOR(ep)); ERL_FUN_MODULE(cp) = erl_copy_term(ERL_FUN_MODULE(ep)); memcpy(ERL_FUN_MD5(cp), ERL_FUN_MD5(ep), sizeof(ERL_FUN_MD5(ep))); ERL_CLOSURE(cp) = (ETERM**) erl_malloc(i * sizeof(ETERM*)); for(i=0; i < ERL_CLOSURE_SIZE(ep); i++) ERL_CLOSURE_ELEMENT(cp,i) = erl_copy_term(ERL_CLOSURE_ELEMENT(ep, i)); break; default: erl_err_msg("<ERROR> erl_copy_term: wrong type encountered !"); erl_free_term(cp); return (ETERM *) NULL; } return cp; }