int erl_iolist_length (const ETERM* term) { int len = 0; while (ERL_IS_CONS(term)) { ETERM* obj = HEAD(term); if (ERL_IS_BYTE(obj)) { len++; } else if (ERL_IS_CONS(obj)) { int i; if ((i = erl_iolist_length(obj)) < 0) return i; len += i; } else if (ERL_IS_BINARY(obj)) { len += ERL_BIN_SIZE(obj); } else if (!ERL_IS_EMPTY_LIST(obj)) { return(-1); } term = TAIL(term); } if (ERL_IS_EMPTY_LIST(term)) return len; else if (ERL_IS_BINARY(term)) return len + ERL_BIN_SIZE(term); else return -1; }
static void iolist_to_buf(const ETERM* term, char** bufp) { char* dest = *bufp; while (ERL_IS_CONS(term)) { ETERM* obj = HEAD(term); if (ERL_IS_BYTE(obj)) { *dest++ = ERL_INT_VALUE(obj); } else if (ERL_IS_CONS(obj)) { iolist_to_buf(obj, &dest); } else if (ERL_IS_BINARY(obj)) { memcpy(dest, ERL_BIN_PTR(obj), ERL_BIN_SIZE(obj)); dest += ERL_BIN_SIZE(obj); } else { /* * Types have been checked by caller. */ if (!ERL_IS_EMPTY_LIST(obj)) return; /* ASSERT(ERL_IS_EMPTY_LIST(obj)); */ } term = TAIL(term); } if (ERL_IS_BINARY(term)) { memcpy(dest, ERL_BIN_PTR(term), ERL_BIN_SIZE(term)); dest += ERL_BIN_SIZE(term); } else { /* * Types have been checked by caller. */ if (!ERL_IS_EMPTY_LIST(term)) return; /* ASSERT(ERL_IS_EMPTY_LIST(term));*/ } *bufp = dest; }
static int process_encode_salt(ETERM *pid, ETERM *data) { int retval = 0; ETERM *pattern, *cslt, *lr; byte *csalt = NULL; long log_rounds = -1; int csaltlen = -1; char ret[64]; pattern = erl_format("{Csalt, LogRounds}"); if (erl_match(pattern, data)) { cslt = erl_var_content(pattern, "Csalt"); csaltlen = ERL_BIN_SIZE(cslt); csalt = ERL_BIN_PTR(cslt); lr = erl_var_content(pattern, "LogRounds"); log_rounds = ERL_INT_UVALUE(lr); if (16 != csaltlen) { retval = process_reply(pid, CMD_SALT, "Invalid salt length"); } else if (log_rounds < 4 || log_rounds > 31) { retval = process_reply(pid, CMD_SALT, "Invalid number of rounds"); } else { encode_salt(ret, (u_int8_t*)csalt, csaltlen, log_rounds); retval = process_reply(pid, CMD_SALT, ret); } erl_free_term(cslt); erl_free_term(lr); }; erl_free_term(pattern); return retval; }
char* erl_iolist_to_string(const ETERM* term) { ETERM* bin; if ((bin = erl_iolist_to_binary(term)) == NULL) { return NULL; } else { char* result = NULL; if (memchr(ERL_BIN_PTR(bin), '\0', ERL_BIN_SIZE(bin)) == NULL) { result = (char *) erl_malloc(ERL_BIN_SIZE(bin)+1); memcpy(result, ERL_BIN_PTR(bin), ERL_BIN_SIZE(bin)); result[ERL_BIN_SIZE(bin)] = '\0'; } erl_free_term(bin); return result; } }
ETERM * surface_create_from_png_stream(ETERM* arg, int c_node) { ETERM* bin = erl_element(1, arg); struct png_data in = {}; in.size = ERL_BIN_SIZE(bin); in.buf = ERL_BIN_PTR(bin); cairo_surface_t *surface = cairo_image_surface_create_from_png_stream(read_cb, &in); erl_free_term(bin); return erl_format("{c_node, ~i, {ok, ~i}}", c_node, surface); }
static int process_hashpw(ETERM *pid, ETERM *data) { int retval = 0; ETERM *pattern, *pwd, *slt, *pwd_bin, *slt_bin; char password[1024]; char salt[1024]; char encrypted[1024] = { 0 }; (void)memset(&password, '\0', sizeof(password)); (void)memset(&salt, '\0', sizeof(salt)); pattern = erl_format("{Pass, Salt}"); if (erl_match(pattern, data)) { pwd = erl_var_content(pattern, "Pass"); pwd_bin = erl_iolist_to_binary(pwd); slt = erl_var_content(pattern, "Salt"); slt_bin = erl_iolist_to_binary(slt); if (ERL_BIN_SIZE(pwd_bin) > sizeof(password)) { retval = process_reply(pid, CMD_HASHPW, "Password too long"); } else if (ERL_BIN_SIZE(slt_bin) > sizeof(salt)) { retval = process_reply(pid, CMD_HASHPW, "Salt too long"); } else { memcpy(password, ERL_BIN_PTR(pwd_bin), ERL_BIN_SIZE(pwd_bin)); memcpy(salt, ERL_BIN_PTR(slt_bin), ERL_BIN_SIZE(slt_bin)); if (bcrypt(encrypted, password, salt)) { retval = process_reply(pid, CMD_HASHPW, "Invalid salt"); } else { retval = process_reply(pid, CMD_HASHPW, encrypted); } } erl_free_term(pwd); erl_free_term(slt); erl_free_term(pwd_bin); erl_free_term(slt_bin); }; erl_free_term(pattern); return retval; }
/* * 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; }
static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { int ret_bytes = 0; ETERM * response = erl_rpc(FERL_DATA->erlang_fd,"file","pread",erl_format("[~s,{bof,~i},~i]",offset,size)); ETERM * pattern = erl_format("{ok,Data}"); if(erl_match(pattern, response)) { ETERM * Data = erl_var_content(pattern, "Data"); if(ERL_IS_BINARY(Data)){ ret_bytes = ERL_BIN_SIZE(Data); char * data = ERL_BIN_PTR(Data); memcpy(buf,data,size); //copy the data over into the buffer } } return ret_bytes; }
void local_add_watch(ETERM* args) { ETERM *pathp = erl_element(1, args); int pathLength = ERL_BIN_SIZE(pathp); char *path = ERL_BIN_PTR(pathp); ETERM *notifyFilterp = erl_element(2, args); unsigned int notifyFilter_ui = ERL_INT_UVALUE(notifyFilterp); long notifyFilter = (long)notifyFilter_ui; ETERM *watchSubdirsp = erl_element(3, args); int watchSubdirs = ERL_INT_VALUE(watchSubdirsp); int watchID = eNotify_addWatch(path, pathLength, notifyFilter, watchSubdirs); // Prepare response ETERM *tuplep; ETERM *tupleArray[2]; if (watchID < 0) { long errorCode = (long)(-watchID); char errorDesc[1024]; eNotify_getErrorDesc(errorCode, errorDesc, 1024); tupleArray[0] = erl_mk_atom("error"); tupleArray[1] = erl_mk_string(errorDesc); } else if (0 == watchID) { // this may happen if there's a problem converting // a path from utf8 to UTF16 tupleArray[0] = erl_mk_atom("error"); tupleArray[1] = erl_mk_string("internal_error"); } else { tupleArray[0] = erl_mk_atom("ok"); tupleArray[1] = erl_mk_int(watchID); } char buf[1024]; tuplep = erl_mk_tuple(tupleArray, 2); erl_encode(tuplep, buf); write_cmd(buf, erl_term_len(tuplep)); erl_free_array(tupleArray, 2); // free contents from tupleArray }
/* * Return the SIZE of a TUPLE or a BINARY. * At failure -1 is returned. */ int erl_size (const ETERM *ep) { if (!ep) return -1; /* ASSERT(ep != NULL); */ switch (ERL_TYPE(ep)) { case ERL_TUPLE: return ERL_TUPLE_SIZE(ep); case ERL_BINARY: return ERL_BIN_SIZE(ep); default: return -1; } }
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; }
int main(int argc, char* argv[]) { ETERM *tuplep, *fnp, *pathp, *binp, *widthp, *heightp; ETERM *res_tuplep; ETERM *res_arrp[2]; ETERM *res_ok_atomp, *res_error_atomp, *res_error_cause_atomp; int idx = 1; byte *buf = malloc(INIT_BUF_SIZE); int buf_len = INIT_BUF_SIZE; int res_len; erl_init(NULL, 0); //Create common atoms(ok, error) res_ok_atomp = erl_mk_atom("ok"); res_error_atomp = erl_mk_atom("error"); res_error_cause_atomp = erl_mk_atom("resize failed"); while (read_cmd(&buf, &buf_len) > 0) { tuplep = erl_decode(buf); fnp = erl_element(idx++, tuplep); pathp = erl_element(idx++, tuplep); binp = erl_element(idx++, tuplep); widthp = erl_element(idx++, tuplep); heightp = erl_element(idx++, tuplep); if (strncmp(ERL_ATOM_PTR(fnp), "resize", 6) == 0) { char* algop = ERL_ATOM_PTR(fnp) + 6; resizerl_handler* rhp = (strncmp(algop, "_opencv", 7) == 0) ? resizerl_impls[0] : NULL; if (rhp == NULL) { exit(1); } // ERL_INT_VALUE, ERL_BIN_PTR, ERL_BIN_SIZE void* dp = NULL; rhp->exec(ERL_BIN_PTR(binp), ERL_BIN_SIZE(binp), ERL_BIN_PTR(pathp), ERL_BIN_SIZE(pathp), ERL_INT_VALUE(widthp), ERL_INT_VALUE(heightp), &dp); if (dp == NULL) { exit(2); } unsigned char* dst; int dst_size; rhp->get_result(dp, &dst, &dst_size); res_arrp[0] = res_ok_atomp; res_arrp[1] = erl_mk_binary((const char*)dst, dst_size); res_tuplep = erl_mk_tuple(res_arrp, 2); res_len = erl_term_len(res_tuplep); if (res_len > buf_len) { byte* new_buf = (byte*)realloc((void*)buf, res_len); if (new_buf == NULL) { exit(3); } buf = new_buf; buf_len = res_len; } erl_encode(res_tuplep, buf); write_cmd(buf, erl_term_len(res_tuplep)); erl_free_term(res_arrp[1]); erl_free_term(res_tuplep); rhp->release(&dp); } else { res_arrp[0] = res_error_atomp; res_arrp[1] = res_error_cause_atomp; res_tuplep = erl_mk_tuple(res_arrp, 2); if (res_len > buf_len) { byte* new_buf = (byte*)realloc((void*)buf, res_len); if (new_buf == NULL) { exit(4); } buf = new_buf; buf_len = res_len; } erl_encode(res_tuplep, buf); write_cmd(buf, erl_term_len(res_tuplep)); erl_free_term(res_tuplep); } erl_free_compound(tuplep); erl_free_term(fnp); erl_free_term(pathp); erl_free_term(binp); erl_free_term(widthp); erl_free_term(heightp); idx = 1; } // normal return 0; }
void *cnode_run() { int fd; /* fd to Erlang node */ int got; /* Result of receive */ unsigned char buf[BUFSIZE]; /* Buffer for incoming message */ ErlMessage emsg; /* Incoming message */ ETERM *uid, *msg; erl_init(NULL, 0); if (erl_connect_init(1, "secretcookie", 0) == -1) erl_err_quit("erl_connect_init"); if ((fd = erl_connect("httpdmaster@localhost")) < 0) erl_err_quit("erl_connect"); fprintf(stderr, "Connected to httpdmaster@localhost\n\r"); struct evbuffer *evbuf; while (1) { got = erl_receive_msg(fd, buf, BUFSIZE, &emsg); if (got == ERL_TICK) { continue; } else if (got == ERL_ERROR) { fprintf(stderr, "ERL_ERROR from erl_receive_msg.\n"); break; } else { if (emsg.type == ERL_REG_SEND) { fprintf(stderr, "type of emsg is ERL_REG_SEND\n"); // get uid and body data from eg: {123, <<"Hello">>} uid = erl_element(1, emsg.msg); msg = erl_element(2, emsg.msg); char *token = (char *) ERL_BIN_PTR(uid); char *body = (char *) ERL_BIN_PTR(msg); int body_len = ERL_BIN_SIZE(msg); char *cached = fetch_memcached(token); int userid = atoi(cached); fprintf(stderr, "memc: %d\n\r", userid); if(clients[userid]){ fprintf(stderr, "Sending %d bytes to token %s\n", body_len, token); evbuf = evbuffer_new(); evbuffer_add(evbuf, (const void*)body, (size_t) body_len); evhttp_send_reply_chunk(clients[userid], evbuf); evhttp_send_reply_end(clients[userid]); evbuffer_free(evbuf); }else{ fprintf(stderr, "Discarding %d bytes to uid %d - user not connected\n", body_len, userid); } free(cached); erl_free_term(emsg.msg); erl_free_term(uid); erl_free_term(msg); } } fprintf(stderr, "."); } pthread_exit(0); }
/* * Dump (print for debugging) a term. Useful if/when things go wrong. */ void dump_term (FILE *fp, ETERM *t) { if (fp == NULL) return; fprintf(fp, "#<%p ", t); if(t != NULL) { fprintf(fp, "count:%d, type:%d", ERL_COUNT(t), ERL_TYPE(t)); switch(ERL_TYPE(t)) { case ERL_UNDEF: fprintf(fp, "==undef"); break; case ERL_INTEGER: fprintf(fp, "==int, val:%d", ERL_INT_VALUE(t)); break; case ERL_U_INTEGER: fprintf(fp, "==uint, val:%u", ERL_INT_UVALUE(t)); break; case ERL_FLOAT: fprintf(fp, "==float, val:%g", ERL_FLOAT_VALUE(t)); break; case ERL_ATOM: fprintf(fp, "==atom, name:%p \"%s\"", ERL_ATOM_PTR(t), ERL_ATOM_PTR(t)); break; case ERL_BINARY: fprintf(fp, "==binary, data:%p,%u", ERL_BIN_PTR(t), ERL_BIN_SIZE(t)); break; case ERL_PID: fprintf(fp, "==pid, node:%p \"%s\"", ERL_PID_NODE(t), ERL_PID_NODE(t)); break; case ERL_PORT: fprintf(fp, "==port, node:%p \"%s\"", ERL_PORT_NODE(t), ERL_PORT_NODE(t)); break; case ERL_REF: fprintf(fp, "==ref, node:%p \"%s\"", ERL_REF_NODE(t), ERL_REF_NODE(t)); break; case ERL_CONS: fprintf(fp, "==cons"); fprintf(fp, ", car:"); dump_term(fp, ERL_CONS_HEAD(t)); fprintf(fp, ", cdr:"); dump_term(fp, ERL_CONS_TAIL(t)); break; case ERL_NIL: fprintf(fp, "==nil"); break; case ERL_TUPLE: fprintf(fp, "==tuple, elems:%p,%u", ERL_TUPLE_ELEMS(t), ERL_TUPLE_SIZE(t)); { size_t i; for(i = 0; i < ERL_TUPLE_SIZE(t); i++) { fprintf(fp, "elem[%u]:", i); dump_term(fp, ERL_TUPLE_ELEMENT(t, i)); } } break; case ERL_VARIABLE: fprintf(fp, "==variable, name:%p \"%s\"", ERL_VAR_NAME(t), ERL_VAR_NAME(t)); fprintf(fp, ", value:"); dump_term(fp, ERL_VAR_VALUE(t)); break; default: break; } } fprintf(fp, ">"); }
/* * 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; }
int erl_print_term(FILE *fp, const ETERM *ep) { int j,i,doquote; int ch_written = 0; /* counter of written chars */ if ((!fp) || (!ep)) return 0; /* ASSERT(ep != NULL); */ j = i = doquote = 0; switch(ERL_TYPE(ep)) { case ERL_ATOM: { char* adata = ERL_ATOM_PTR(ep); /* FIXME: what if some weird locale is in use? */ if (!islower(adata[0])) doquote = 1; for (i = 0; !doquote && i < ERL_ATOM_SIZE(ep); i++) { doquote = !(isalnum(adata[i]) || (adata[i] == '_')); } if (doquote) { putc('\'', fp); ch_written++; } fputs(adata, fp); ch_written += ERL_ATOM_SIZE(ep); if (doquote) { putc('\'', fp); ch_written++; } break; } case ERL_VARIABLE: if (!isupper((int)ERL_VAR_NAME(ep)[0])) { doquote = 1; putc('\'', fp); ch_written++; } fputs(ERL_VAR_NAME(ep), fp); ch_written += ERL_VAR_LEN(ep); if (doquote) { putc('\'', fp); ch_written++; } break; case ERL_PID: ch_written += fprintf(fp, "<%s.%d.%d>", ERL_PID_NODE(ep), ERL_PID_NUMBER(ep), ERL_PID_SERIAL(ep)); break; case ERL_PORT: ch_written += fprintf(fp, "#Port"); break; case ERL_REF: ch_written += fprintf(fp, "#Ref"); break; case ERL_EMPTY_LIST: ch_written += fprintf(fp, "[]"); break; case ERL_LIST: if (is_printable_list(ep)) { ch_written += print_string(fp, ep); } else { putc('[', fp); ch_written++; while (ERL_IS_CONS(ep)) { ch_written += erl_print_term(fp, HEAD(ep)); ep = TAIL(ep); if (ERL_IS_CONS(ep)) { putc(',', fp); ch_written++; } } if (!ERL_IS_EMPTY_LIST(ep)) { putc('|', fp); ch_written++; ch_written += erl_print_term(fp, ep); } putc(']', fp); ch_written++; } break; case ERL_TUPLE: putc('{', fp); ch_written++; for (i=0; i < ERL_TUPLE_SIZE(ep); i++) { ch_written += erl_print_term(fp, ERL_TUPLE_ELEMENT(ep, j++) ); if (i != ERL_TUPLE_SIZE(ep)-1) { putc(',', fp); ch_written++; } } putc('}', fp); ch_written++; break; case ERL_BINARY: { int sz = (ERL_BIN_SIZE(ep) > 20) ? 20 : ERL_BIN_SIZE(ep); unsigned char *ptr = ERL_BIN_PTR(ep); ch_written += fprintf(fp, "#Bin<"); for (i = 0; i < sz; i++) { putc(ptr[i], fp); ch_written++; } if (sz == 20) ch_written += fprintf(fp, "(%d)....>", ERL_BIN_SIZE(ep)-20); else ch_written += fprintf(fp, ">"); break; } case ERL_INTEGER: case ERL_SMALL_BIG: ch_written += fprintf(fp, "%d", ERL_INT_VALUE(ep)); break; case ERL_U_INTEGER: case ERL_U_SMALL_BIG: ch_written += fprintf(fp, "%d", ERL_INT_UVALUE(ep)); break; case ERL_LONGLONG: case ERL_U_LONGLONG: ch_written += fprintf(fp, "%lld", ERL_LL_UVALUE(ep)); break; case ERL_FLOAT: ch_written += fprintf(fp, "%f", ERL_FLOAT_VALUE(ep)); break; case ERL_FUNCTION: ch_written += fprintf(fp, "#Fun<"); ch_written += erl_print_term(fp, ERL_FUN_MODULE(ep)); putc('.', fp); ch_written++; ch_written += erl_print_term(fp, ERL_FUN_INDEX(ep)); putc('.', fp); ch_written++; ch_written += erl_print_term(fp, ERL_FUN_UNIQ(ep)); putc('>', fp); ch_written++; break; default: ch_written = -10000; erl_err_msg("<ERROR> erl_print_term: Bad type of term !"); } return ch_written; }
PyObject *eterm_to_py(ETERM * obj) { int i; int count; ETERM *obj2; PyObject *eobj = NULL; if (obj == NULL) { Py_INCREF(Py_None); return Py_None; } switch (ERL_TYPE(obj)) { case ERL_CONS: case ERL_NIL: count = erl_length(obj); eobj = PyList_New(0); for (i = 0; i < count; i++) { obj2 = erl_hd(obj); PyList_Append(eobj, eterm_to_py(obj2)); obj = erl_tl(obj); } break; case ERL_TUPLE: eobj = PyTuple_New(erl_size(obj)); for (i = 1; i <= erl_size(obj); i++) { obj2 = erl_element(i, obj); PyTuple_SetItem(eobj, i - 1, eterm_to_py(obj2)); } break; case ERL_ATOM: eobj = PyString_FromStringAndSize(ERL_ATOM_PTR(obj), ERL_ATOM_SIZE(obj)); break; case ERL_INTEGER: eobj = PyInt_FromLong(ERL_INT_VALUE(obj)); break; case ERL_BINARY: fprintf(stderr, "FOUND A BINARY %.*s\n", ERL_BIN_SIZE(obj), ERL_BIN_PTR(obj)); break; case ERL_PID: eobj = PyDict_New(); if (PyDict_SetItemString(eobj, "node", PyString_FromString(ERL_PID_NODE(obj)))) { PyErr_Print(); break; } if (PyDict_SetItemString(eobj, "number", PyInt_FromLong(ERL_PID_NUMBER(obj)))) { PyErr_Print(); break; } if (PyDict_SetItemString(eobj, "serial", PyInt_FromLong(ERL_PID_SERIAL(obj)))) { PyErr_Print(); break; } if (PyDict_SetItemString(eobj, "creation", PyInt_FromLong(ERL_PID_CREATION(obj)))) { PyErr_Print(); break; } default: fprintf(stderr, "UNMANAGED ETERM TYPE: %d\n", ERL_TYPE(obj)); break; } if (eobj == NULL) { Py_INCREF(Py_None); return Py_None; } return eobj; }