int embed_init(void) { // atoms must be initialised by now // bucket_raw -> bucket // name_raw -> name embed_buck_t *ptr_b = embed_bucks; embed_buck_t *end_b = ptr_b +nr_embed_bucks; while (ptr_b < end_b) { ptr_b->bucket = tag_atom(atoms_set(ptr_b->bucket_raw)); ptr_b++; } embed_bin_t *ptr_i = embed_bins; embed_bin_t *end_i = embed_bins +nr_embed_bins; while (ptr_i < end_i) { ptr_i->name = tag_atom(atoms_set(ptr_i->name_raw)); ptr_i++; } return 0; }
term_t bif_list_embedded0(process_t *ctx) { term_t l = nil, cons = nil; xmod_bin_t *mp, *me; mp = (xmod_bin_t *)module_bins->elts; me = mp + module_bins->nelts; while (mp < me) { //{Mod,Size,IsPreloaded} term_t mod = atom(atoms_set(proc_atoms(ctx), mp->name)); term_t size = intnum(mp->size); term_t is_preloaded = bool(mp->is_preloaded); term_t triple = make_tuple3(mod, size, is_preloaded, proc_gc_pool(ctx)); lst_add(l, cons, triple, proc_gc_pool(ctx)); mp++; } result(l); return AI_OK; }
term_t bin2term(apr_byte_t **data, int *bytes_left, atoms_t *atoms, heap_t *heap) { #define require(__n) \ do { \ if (*bytes_left < __n) \ return noval; \ (*bytes_left) -= __n; \ } while (0) #define get_byte() (*(*data)++) require(1); switch (get_byte()) { case 97: { require(1); return tag_int(get_byte()); } case 98: { int a, b, c, d; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); return int_to_term((a << 24) | (b << 16) | (c << 8) | d, heap); } case 99: { double value; require(31); sscanf((const char *)*data, "%lf", &value); (*data) += 31; return heap_float(heap, value); } case 100: { int a, b; int len; cstr_t *s; int index; require(2); a = get_byte(); b = get_byte(); len = ((a << 8) | b); if (len > 255) return noval; require(len); s = (cstr_t *)heap_alloc(heap, sizeof(cstr_t) + len); s->size = len; memcpy(s->data, *data, len); index = atoms_set(atoms, s); (*data) += len; return tag_atom(index); } case 104: { int arity, i; term_t tuple; term_box_t *tbox; require(1); arity = get_byte(); tuple = heap_tuple(heap, arity); tbox = peel(tuple); for (i = 0; i < arity; i++) { term_t e = bin2term(data, bytes_left, atoms, heap); if (e == noval) return noval; tbox->tuple.elts[i] = e; } return tuple; } case 105: { int a, b, c, d; int arity, i; term_t tuple; term_box_t *tbox; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); arity = ((a << 24) | (b << 16) | (c << 8) | d); tuple = heap_tuple(heap, arity); tbox = peel(tuple); for (i = 0; i < arity; i++) { term_t e = bin2term(data, bytes_left, atoms, heap); if (e == noval) return noval; tbox->tuple.elts[i] = e; } return tuple; } case 106: { return nil; } case 107: { int a, b; int len, i; term_t cons = nil; require(2); a = get_byte(); b = get_byte(); len = ((a << 8) | b); require(len); i = len-1; while (i >= 0) cons = heap_cons2(heap, tag_int((*data)[i--]), cons); (*data) += len; return cons; } case 108: { int a, b, c, d; int len, i; term_t *es; term_t tail; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); len = ((a << 24) | (b << 16) | (c << 8) | d); es = (term_t *)heap_alloc(heap, len*sizeof(term_t)); for (i = 0; i < len; i++) { term_t e = bin2term(data, bytes_left, atoms, heap); if (e == noval) return noval; es[i] = e; } tail = bin2term(data, bytes_left, atoms, heap); if (tail == noval) return noval; i = len-1; while (i >= 0) tail = heap_cons2(heap, es[i--], tail); return tail; } case 109: { int a, b, c, d; int len; term_t bin; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); len = ((a << 24) | (b << 16) | (c << 8) | d); require(len); bin = heap_binary(heap, len*8, (*data)); (*data) += len; return bin; } case 110: { int len; int sign; mp_size prec; mp_int mp; mp_err rs; require(1); len = get_byte(); sign = get_byte(); require(len); prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE; mp_init_size(&mp, prec, heap); //TODO: use mp_read_signed_bin rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap); if (rs != MP_OKAY) return noval; (*data) += len; if (sign == 1) mp_neg(&mp, &mp, heap); return mp_to_term(mp); } case 111: { int a, b, c, d; int len; int sign; mp_size prec; mp_int mp; mp_err rs; require(4); a = get_byte(); b = get_byte(); c = get_byte(); d = get_byte(); len = ((a << 24) | (b << 16) | (c << 8) | d); require(1); sign = get_byte(); require(len); prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE; mp_init_size(&mp, prec, heap); rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap); if (rs != MP_OKAY) return noval; (*data) += len; if (sign == 1) mp_neg(&mp, &mp, heap); return mp_to_term(mp); } default: return noval; // only a subset of tags are supported; inspired by BERT } }