int enif_inspect_iolist_as_binary(ErlNifEnv* env, Eterm term, ErlNifBinary* bin) { struct enif_tmp_obj_t* tobj; ErtsAlcType_t allocator; Uint sz; if (is_binary(term)) { return enif_inspect_binary(env,term,bin); } if (is_nil(term)) { bin->data = (unsigned char*) &bin->data; /* dummy non-NULL */ bin->size = 0; bin->bin_term = THE_NON_VALUE; bin->ref_bin = NULL; return 1; } if (erts_iolist_size(term, &sz)) { return 0; } allocator = is_proc_bound(env) ? ERTS_ALC_T_TMP : ERTS_ALC_T_NIF; tobj = erts_alloc(allocator, sz + sizeof(struct enif_tmp_obj_t)); tobj->allocator = allocator; tobj->next = env->tmp_obj_list; tobj->dtor = &tmp_alloc_dtor; env->tmp_obj_list = tobj; bin->data = (unsigned char*) &tobj[1]; bin->size = sz; bin->bin_term = THE_NON_VALUE; bin->ref_bin = NULL; io_list_to_buf(term, (char*) bin->data, sz); ADD_READONLY_CHECK(env, bin->data, bin->size); return 1; }
static char *pick_list_or_atom(Eterm name_term) { char *name = NULL; ErlDrvSizeT name_len; if (is_atom(name_term)) { Atom *ap = atom_tab(atom_val(name_term)); if (ap->len == 0) { /* If io_lists with zero length is not allowed, then the empty atom shouldn't */ goto error; } name = erts_alloc(ERTS_ALC_T_DDLL_TMP_BUF, ap->len + 1); memcpy(name,ap->name,ap->len); name[ap->len] = '\0'; } else { if (erts_iolist_size(name_term, &name_len)) { goto error; } name = erts_alloc(ERTS_ALC_T_DDLL_TMP_BUF, name_len + 1); if (erts_iolist_to_buf(name_term, name, name_len) != 0) { goto error; } name[name_len] = '\0'; } return name; error: if (name != NULL) { erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); } return NULL; }
static byte* convert_environment(Process* p, Eterm env) { Eterm all; Eterm* temp_heap; Eterm* hp; Uint heap_size; int n; Uint size; byte* bytes; if ((n = list_length(env)) < 0) { return NULL; } heap_size = 2*(5*n+1); temp_heap = hp = (Eterm *) erts_alloc(ERTS_ALC_T_TMP, heap_size*sizeof(Eterm)); bytes = NULL; /* Indicating error */ /* * All errors below are handled by jumping to 'done', to ensure that the memory * gets deallocated. Do NOT return directly from this function. */ all = CONS(hp, make_small(0), NIL); hp += 2; while(is_list(env)) { Eterm tmp; Eterm* tp; tmp = CAR(list_val(env)); if (is_not_tuple_arity(tmp, 2)) { goto done; } tp = tuple_val(tmp); tmp = CONS(hp, make_small(0), NIL); hp += 2; if (tp[2] != am_false) { tmp = CONS(hp, tp[2], tmp); hp += 2; } tmp = CONS(hp, make_small('='), tmp); hp += 2; tmp = CONS(hp, tp[1], tmp); hp += 2; all = CONS(hp, tmp, all); hp += 2; env = CDR(list_val(env)); } if (is_not_nil(env)) { goto done; } if (erts_iolist_size(all, &size)) { goto done; } /* * Put the result in a binary (no risk for a memory leak that way). */ (void) erts_new_heap_binary(p, NULL, size, &bytes); io_list_to_buf(all, (char*)bytes, size); done: erts_free(ERTS_ALC_T_TMP, temp_heap); return bytes; }