ETERM *body_set_position(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *idp = erl_element(2, argp); ETERM *vectorp = erl_element(3, argp); ETERM *xp = erl_element(1, vectorp); ETERM *yp = erl_element(2, vectorp); erlmunk_space *s = NULL; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); int body_id = ERL_INT_VALUE(idp); erlmunk_body *b = NULL; HASH_FIND_INT(s->bodies, &body_id, b); if (b == NULL) return NULL; cpBodySetPosition(b->body, cpv(ERL_FLOAT_VALUE(xp), ERL_FLOAT_VALUE(yp))); // DEBUGF(("body_set_position(x: %f, y: %f) has succeeded", // ERL_FLOAT_VALUE(xp), ERL_FLOAT_VALUE(yp))); return NULL; }
ETERM *body_update_position(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *idp = erl_element(2, argp); ETERM *deltap = erl_element(3, argp); erlmunk_space *s = NULL; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); int body_id = ERL_INT_VALUE(idp); erlmunk_body *b = NULL; HASH_FIND_INT(s->bodies, &body_id, b); if (b == NULL) return NULL; cpVect position = cpBodyGetPosition(b->body); float angle = deg_to_rad(cpBodyGetAngle(b->body)); cpVect angleV = cpvforangle(angle); cpVect projection = cpvmult(angleV, ERL_FLOAT_VALUE(deltap)); cpVect new_position = cpvadd(projection, position); cpBodySetPosition(b->body, new_position); // DEBUGF(("body_update_position(x: %f, y: %f, delta: %f) has succeeded (x: %f, y: %f)", // position.x, position.y, ERL_FLOAT_VALUE(deltap), // new_position.x, new_position.y)); return NULL; }
ETERM *space_add_body(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *idp = erl_element(2, argp); ETERM *massp = erl_element(3, argp); // ETERM *inertiap = erl_element(4, argp); erlmunk_space *s; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); int object_id = ERL_INT_VALUE(idp); cpBody *body = cpSpaceAddBody(s->space, cpBodyNew(ERL_FLOAT_VALUE(massp), INFINITY)); // the body is created inactive, it is explicitly activated // when all it's values have been set. cpBodySleep(body); erlmunk_body_data *data = malloc(sizeof(erlmunk_body_data)); data->id = object_id; data->term = NULL; cpBodySetUserData(body, (cpDataPointer) data); space_add_body_hash(s, object_id, body); return NULL; }
ETERM *body_apply_impulse(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *idp = erl_element(2, argp); ETERM *impulsep = erl_element(3, argp); erlmunk_space *s; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); int body_id = ERL_INT_VALUE(idp); erlmunk_body *b; HASH_FIND_INT(s->bodies, &body_id, b); if (b == NULL) return NULL; // apply the impulse at the center of the body and along it's current angle float angle = deg_to_rad(cpBodyGetAngle(b->body)); cpVect angleV = cpvforangle(angle); cpVect impulse = cpvmult(angleV, ERL_FLOAT_VALUE(impulsep)); cpBodyApplyImpulseAtWorldPoint(b->body, impulse, angleV); return NULL; }
static VALUE erlix_float_to_fix(VALUE self){ ErlixTerm *efloat; double l; Data_Get_Struct(self,ErlixTerm,efloat); l=ERL_FLOAT_VALUE(efloat->term); return rb_float_new(l); }
ETERM *body_set_collision_circle(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *idp = erl_element(2, argp); ETERM *radiusp = erl_element(3, argp); ETERM *collision_typep = erl_element(4, argp); erlmunk_space *s; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); int body_id = ERL_INT_VALUE(idp); erlmunk_body *b; HASH_FIND_INT(s->bodies, &body_id, b); if (b == NULL) return NULL; cpShape *shape = cpSpaceAddShape(s->space, cpCircleShapeNew(b->body, ERL_FLOAT_VALUE(radiusp), cpvzero)); cpShapeSetCollisionType(shape, ERL_INT_VALUE(collision_typep)); // DEBUGF(("body_set_collision_circle has succeeded")); return NULL; }
/* * 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; }
double val(ETERM *arg) { if (ERL_IS_INTEGER(arg)) return ERL_INT_VALUE(arg); else if (ERL_IS_FLOAT(arg)) return ERL_FLOAT_VALUE(arg); else { exit(EXIT_FAILURE); return 0; } }
ETERM *space_add_boundaries(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *lower_leftp = erl_element(2, argp); ETERM *lower_rightp = erl_element(3, argp); ETERM *upper_leftp = erl_element(4, argp); ETERM *upper_rightp = erl_element(5, argp); ETERM *collision_categoryp = erl_element(6, argp); ETERM *datap = erl_element(7, argp); erlmunk_space *s; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); cpVect lowerLeft = cpv(ERL_FLOAT_VALUE(erl_element(1, lower_leftp)), ERL_FLOAT_VALUE(erl_element(2, lower_leftp))); cpVect lowerRight = cpv(ERL_FLOAT_VALUE(erl_element(1, lower_rightp)), ERL_FLOAT_VALUE(erl_element(2, lower_rightp))); cpVect upperLeft = cpv(ERL_FLOAT_VALUE(erl_element(1, upper_leftp)), ERL_FLOAT_VALUE(erl_element(2, upper_leftp))); cpVect upperRight = cpv(ERL_FLOAT_VALUE(erl_element(1, upper_rightp)), ERL_FLOAT_VALUE(erl_element(2, upper_rightp))); // get the static body that comes with the space cpBody *static_body = cpSpaceGetStaticBody(s->space); erlmunk_body_data *data = malloc(sizeof(erlmunk_body_data)); data->id = BOUNDARY_BODY_ID; data->term = erl_copy_term(datap); cpBodySetUserData(static_body, (cpDataPointer) data); // bottom cpShape *bottomBoundaryShape = cpSegmentShapeNew(static_body, lowerLeft, lowerRight, 0.0f); cpShapeSetCollisionType(bottomBoundaryShape, ERL_INT_VALUE(collision_categoryp)); cpSpaceAddShape(s->space, bottomBoundaryShape); // top cpShape *topBoundaryShape = cpSegmentShapeNew(static_body, upperLeft, upperRight, 0.0f); cpShapeSetCollisionType(topBoundaryShape, ERL_INT_VALUE(collision_categoryp)); cpSpaceAddShape(s->space, topBoundaryShape); // left cpShape *leftBoundaryShape = cpSegmentShapeNew(static_body, lowerLeft, upperLeft, 0.0f); cpShapeSetCollisionType(leftBoundaryShape, ERL_INT_VALUE(collision_categoryp)); cpSpaceAddShape(s->space, leftBoundaryShape); // right cpShape *rightBoundaryShape = cpSegmentShapeNew(static_body, lowerRight, upperRight, 0.0f); cpShapeSetCollisionType(rightBoundaryShape, ERL_INT_VALUE(collision_categoryp)); cpSpaceAddShape(s->space, rightBoundaryShape); return NULL; }
ETERM *space_new(ETERM *fromp, ETERM *argp) { // get the args ETERM *iterationsp = erl_element(1, argp); ETERM *gravityp = erl_element(2, argp); ETERM *gravityxp = erl_element(1, gravityp); ETERM *gravityyp = erl_element(2, gravityp); // create the new space cpSpace *space = cpSpaceNew(); cpSpaceSetIterations(space, ERL_INT_VALUE(iterationsp)); cpSpaceSetGravity(space, cpv(ERL_FLOAT_VALUE(gravityxp), ERL_FLOAT_VALUE(gravityyp))); cpSpaceSetSleepTimeThreshold(space, 5.0); // add it to the hash table ETERM *ref = erl_mk_node_ref(); erlmunk_space *s = (erlmunk_space *) malloc(sizeof(erlmunk_space)); s->id = ERL_REF_NUMBER(ref); s->space = space; s->subscriber_count = 0; s->subscribers = NULL; s->bodies = NULL; HASH_ADD_INT(erlmunk_spaces, id, s); ETERM *atom_ok = erl_mk_atom("ok"); ETERM **space_new_array = (ETERM **) malloc(sizeof(ETERM*) * 2); space_new_array[0] = atom_ok; space_new_array[1] = ref; ETERM *space_new_tuple = erl_mk_tuple(space_new_array, 2); free(space_new_array); ETERM *reply_tuple = erl_mk_reply(fromp, space_new_tuple); ETERM *gen_cast_tuple = erl_mk_gen_cast(reply_tuple); return gen_cast_tuple; }
ETERM *space_subscribe_box(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *subscriber_pidp = erl_element(2, argp); ETERM *bounding_boxp = erl_element(3, argp); ETERM *leftp = erl_element(1, bounding_boxp); ETERM *bottomp = erl_element(2, bounding_boxp); ETERM *rightp = erl_element(3, bounding_boxp); ETERM *topp = erl_element(4, bounding_boxp); erlmunk_space *s; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); erlmunk_client *client = get_current_client(); space_add_subscriber(s, client, erl_copy_term(subscriber_pidp), ERL_FLOAT_VALUE(leftp), ERL_FLOAT_VALUE(bottomp), ERL_FLOAT_VALUE(rightp), ERL_FLOAT_VALUE(topp)); // DEBUGF(("space_subscribe_box(client fd: %d) has succeeded", // client->fd)); return NULL; }
/* * 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; }
ETERM * set_source_rgba(ETERM* arg, int c_node) { ETERM *r, *g, *b, *a; cairo_context *ctx = get_cairo_context(arg); if (ctx) { r = erl_element(2, arg); g = erl_element(3, arg); b = erl_element(4, arg); a = erl_element(5, arg); cairo_set_source_rgba(ctx->cr, ERL_FLOAT_VALUE(r), val(g), val(b), val(a)); erl_free_term(r); erl_free_term(g); erl_free_term(b); erl_free_term(a); return erl_format("{c_node, ~i, ok}", c_node); } else { return erl_format("{c_node, ~i, {error, '~s'}}", c_node, ERR_CONTEXT); } }
ETERM *body_set_angle(ETERM *fromp, ETERM *argp) { // get the args ETERM *space_refp = erl_element(1, argp); ETERM *idp = erl_element(2, argp); ETERM *anglep = erl_element(3, argp); erlmunk_space *s; int space_id = ERL_REF_NUMBER(space_refp); HASH_FIND_INT(erlmunk_spaces, &space_id, s); int body_id = ERL_INT_VALUE(idp); erlmunk_body *b; HASH_FIND_INT(s->bodies, &body_id, b); if (b == NULL) return NULL; cpBodySetAngle(b->body, ERL_FLOAT_VALUE(anglep)); // DEBUGF(("body_set_angle(%f) has succeeded", ERL_FLOAT_VALUE(anglep))); return NULL; }
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; }
/* * 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_sprint_term(char *buf, const ETERM *ep) { int j,i,doquote; int ch_written = 0; /* counter of written chars */ if ((!buf) || (!ep)) return 0; /* ASSERT(ep != NULL); */ j = i = doquote = 0; switch(ERL_TYPE(ep)) { case ERL_ATOM: /* FIXME: what if some weird locale is in use? */ if (!islower((int)ERL_ATOM_PTR(ep)[0])) doquote = 1; for (i = 0; !doquote && i < ERL_ATOM_SIZE(ep); i++) { doquote = !(isalnum((int)ERL_ATOM_PTR(ep)[i]) || (ERL_ATOM_PTR(ep)[i] == '_')); } if (doquote) { *buf++ = '\''; ch_written++; } { int len = ERL_ATOM_SIZE(ep); strncpy(buf, ERL_ATOM_PTR(ep), len); buf += len; ch_written += len; } if (doquote) { *buf++ = '\''; ch_written++; } break; case ERL_VARIABLE: if (!isupper((int)ERL_VAR_NAME(ep)[0])) { doquote = 1; *buf++ = '\''; ch_written++; } len = ERL_VAR_LEN(ep); strncpy(buf, ERL_VAR_NAME(ep), len); buf += len; ch_written += len; if (doquote) { *buf++ = '\''; ch_written++; } break; case ERL_PID: len = sprintf(buf, "<%s.%d.%d>", ERL_PID_NODE(ep), ERL_PID_NUMBER(ep), ERL_PID_SERIAL(ep)); buf += len; ch_written += len; break; case ERL_PORT: len = sprintf(buf , "#Port"); buf += len; ch_written += len; break; case ERL_REF: len = sprintf(buf , "#Ref"); buf += len; ch_written += len; break; case ERL_EMPTY_LIST: len = sprintf(buf , "[]"); buf += len; ch_written += len; 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_sprint_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_sprint_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_sprint_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: len = sprintf(buf , "#Bin"); buf += len; ch_written += len; break; case ERL_INTEGER: case ERL_SMALL_BIG: len = sprintf(buf , "%d", ERL_INT_VALUE(ep)); buf += len; ch_written += len; break; case ERL_U_INTEGER: case ERL_U_SMALL_BIG: len = sprintf(buf , "%d", ERL_INT_UVALUE(ep)); buf += len; ch_written += len; break; case ERL_FLOAT: len = sprintf(buf , "%f", ERL_FLOAT_VALUE(ep)); buf += len; ch_written += len; break; case ERL_FUNCTION: len = sprintf(buf , "#Fun<"); buf += len; ch_written += len; ch_written += erl_sprint_term(fp, ERL_FUN_MODULE(ep)); putc('.', fp); ch_written++; ch_written += erl_sprint_term(fp, ERL_FUN_INDEX(ep)); putc('.', fp); ch_written++; ch_written += erl_sprint_term(fp, ERL_FUN_UNIQ(ep)); putc('>', fp); ch_written++; break; default: ch_written = -10000; erl_err_msg("<ERROR> erl_sprint_term: Bad type of term !"); } return ch_written; }
/* * 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, ">"); }
/* * http://dev.mysql.com/doc/refman/5.1/en/mysql-stmt-execute.html * * 6 > odbc:param_query(Ref, * "INSERT INTO EMPLOYEE (NR, FIRSTNAME, " * "LASTNAME, GENDER) VALUES(?, ?, ?, ?)", * [{sql_integer,[2,3,4,5,6,7,8]}, * {{sql_varchar, 20}, * ["John", "Monica", "Ross", "Rachel", * "Piper", "Prue", "Louise"]}, * {{sql_varchar, 20}, * ["Doe","Geller","Geller", "Green", * "Halliwell", "Halliwell", "Lane"]}, * {{sql_char, 1}, ["M","F","M","F","T","F","F"]}]). * {updated, 7} */ void handle_param_query(ETERM *msg) { ETERM *query, *params, *p, *tmp, *resp; MYSQL_STMT *handle; MYSQL_BIND *bind; char *q; int param_count, i; query = erl_element(2, msg); q = erl_iolist_to_string(query); erl_free_term(query); logmsg("INFO: got param query: %s", q); params = erl_element(3, msg); erl_free_term(params); handle = mysql_stmt_init(&dbh); if (mysql_stmt_prepare(handle, q, strlen(q))) { resp = erl_format("{error, {mysql_error, ~i, ~s}}", mysql_stmt_errno(handle), mysql_stmt_error(handle)); } else { param_count = mysql_stmt_param_count(handle); if (param_count != erl_length(params)) { resp = erl_format("{error, {mysql_error, -1, [expected_params, %d, got_params, %d]}}", param_count, erl_length(params)); } else { bind = safe_malloc(param_count * sizeof(MYSQL_BIND)); memset(bind, 0, param_count * sizeof(MYSQL_BIND)); for (i = 0, tmp = params; i < param_count && (p = erl_hd(tmp)) != NULL; i++, tmp = erl_tl(tmp)) { ETERM *type, *value; type = erl_element(1, p); value = erl_element(2, p); if (ERL_IS_TUPLE(type)) { // Parameter Type + Size: {Type, Size} ETERM *t_type, *t_size; char *t; unsigned long size; t_size = erl_element(2, type); size = ERL_INT_VALUE(t_size); bind[i].buffer_length = size; erl_free_term(t_size); t_type = erl_element(1, type); t = (char *)ERL_ATOM_PTR(t_type); bind[i].length = safe_malloc(sizeof(unsigned long)); if (strncmp(t, NUMERIC_SQL, strlen(NUMERIC_SQL)) == 0) { int val; bind[i].buffer_type = MYSQL_TYPE_LONG; *bind[i].length = sizeof(int); bind[i].buffer = safe_malloc(*bind[i].length); memset(bind[i].buffer, 0, *bind[i].length); val = ERL_INT_VALUE(value); memcpy(bind[i].buffer, &val, *bind[i].length); } else if (strncmp(t, DECIMAL_SQL, strlen(DECIMAL_SQL)) == 0) { char *val; bind[i].buffer_type = MYSQL_TYPE_STRING; *bind[i].length = bind[i].buffer_length * sizeof(char); bind[i].buffer = safe_malloc(*bind[i].length); memset(bind[i].buffer, 0, *bind[i].length); val = erl_iolist_to_string(value); if (val) { memcpy(bind[i].buffer, val, *bind[i].length); free(val); } } else if (strncmp(t, FLOAT_SQL, strlen(FLOAT_SQL)) == 0) { float val; bind[i].buffer_type = MYSQL_TYPE_FLOAT; *bind[i].length = sizeof(float); bind[i].buffer = safe_malloc(*bind[i].length); memset(bind[i].buffer, 0, *bind[i].length); val = ERL_FLOAT_VALUE(value); memcpy(bind[i].buffer, &val, *bind[i].length); } else if (strncmp(t, CHAR_SQL, strlen(CHAR_SQL)) == 0) { char *val; bind[i].buffer_type = MYSQL_TYPE_STRING; *bind[i].length = bind[i].buffer_length * sizeof(char); bind[i].buffer = safe_malloc(*bind[i].length); memset(bind[i].buffer, 0, *bind[i].length); val = erl_iolist_to_string(value); if (val) { memcpy(bind[i].buffer, val, *bind[i].length); free(val); } } else if (strncmp(t, VARCHAR_SQL, strlen(VARCHAR_SQL)) == 0) { (void)bind_string(&bind[i], value, size); } else { ETERM *resp; resp = erl_format("{error, {unknown_sized_type, ~s, ~i}}", t, bind[i].buffer_length); write_msg(resp); erl_free_term(resp); } erl_free_term(t_type); } else { char *t; t = (char *)ERL_ATOM_PTR(type); if (strncmp(t, TIMESTAMP_SQL, strlen(TIMESTAMP_SQL)) == 0) { bind[i].buffer_type = MYSQL_TYPE_TIMESTAMP; *bind[i].length = sizeof(MYSQL_TIME); bind[i].buffer = safe_malloc(*bind[i].length); memset(bind[i].buffer, 0, *bind[i].length); memcpy(bind[i].buffer, value, *bind[i].length); } else if (strncmp(t, INTEGER_SQL, strlen(INTEGER_SQL)) == 0) { int val; bind[i].buffer_type = MYSQL_TYPE_LONG; *bind[i].length = sizeof(int); bind[i].buffer = safe_malloc(*bind[i].length); memset(bind[i].buffer, 0, *bind[i].length); val = ERL_INT_VALUE(value); memcpy(bind[i].buffer, &val, *bind[i].length); } else { ETERM *resp; resp = erl_format("{error, {unknown_type, ~s}}", t); write_msg(resp); erl_free_term(resp); } } if (ERL_IS_ATOM(value) && strncmp((char *)ERL_ATOM_PTR(value), NULL_SQL, strlen(NULL_SQL)) == 0) bind[i].is_null = &TRUTHY; else bind[i].is_null = &FALSY; erl_free_term(value); erl_free_term(type); } erl_free_term(params); if (mysql_stmt_bind_param(handle, bind)) { resp = erl_format("{error, {mysql_error, ~i, ~s}}", mysql_stmt_errno(handle), mysql_stmt_error(handle)); } else { if (mysql_stmt_execute(handle)) { resp = erl_format("{error, {mysql_error, ~i, ~s}}", mysql_stmt_errno(handle), mysql_stmt_error(handle)); } else { set_mysql_results(handle); if (results) { resp = handle_mysql_result(); } else { if (mysql_stmt_field_count(handle) == 0) resp = erl_format("{updated, ~i}", numrows); else resp = erl_format("{error, {mysql_error, ~i, ~s}}", mysql_stmt_errno(handle), mysql_stmt_error(handle)); } } } for (i = 0; i < param_count; i++) { free(bind[i].length); free(bind[i].buffer); } free(bind); } } erl_free(q); mysql_stmt_close(handle); write_msg(resp); erl_free_term(resp); }
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; }