memptr func_list(memptr func_expr) {

    if (num_nodes(func_expr) == 1) {
        return nil;
    }

    memptr current_node, current_param, current_dup_node = safe_allocate_cons(),
                                        base = current_dup_node;
    cons_pool[current_dup_node].carKind = NIL;
    cons_pool[current_dup_node].cdrKind = NIL;

    current_node = cons_pool[func_expr].cdr;
    current_param = resolve_expr(cons_pool[current_node].car);
    if (current_param == NOT_FOUND) {
#ifdef DEBUG
        printf("29\n");
#endif
        ERROR(ERROR_LIST, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
        return NOT_FOUND;
    } else if (type(current_param) == TYPE_OBJECT) {
        memptr lu = object_lookup(current_param, cons_pool[func_expr].car);
        if (lu != NOT_FOUND) {
#ifdef EXTENDED_SECURITY
            memptr local_security = safe_allocate_cons();
            cons_pool[local_security].car = current_param;
            cons_pool[local_security].carKind = CONS;
            cons_pool[local_security].cdrKind = NIL;
#endif
            return resolve_func_expr(func_expr, current_param, lu, true);
        }
    }
    cons_pool[current_dup_node].car = current_param;
    cons_pool[current_dup_node].carKind = CONS;

    while (cons_pool[current_node].cdrKind == CONS) {

        current_node = cons_pool[current_node].cdr;
        cons_pool[current_dup_node].cdr = allocate_cons();
        cons_pool[current_dup_node].cdrKind = CONS;
        current_dup_node = cons_pool[current_dup_node].cdr;
        cons_pool[current_dup_node].carKind = NIL;
        cons_pool[current_dup_node].cdrKind = NIL;

        current_param = resolve_expr(cons_pool[current_node].car);
        if (current_param == NOT_FOUND) {
#ifdef DEBUG
            printf("30\n");
#endif
            ERROR(ERROR_LIST, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            return NOT_FOUND;
        }
        cons_pool[current_dup_node].car = current_param;
        cons_pool[current_dup_node].carKind = CONS;
    }

    cons_pool[current_dup_node].cdrKind = CONS;
    cons_pool[current_dup_node].cdr = nil;

    return base;
}
Exemple #2
0
static int wasFinalPass(void)
{
    int result = 1;
    struct map_iterator i[1];
    struct map_entry *me;
    for(map_get_iterator(s->guesses, i);
        (me = (struct map_entry*)map_iterator_next(i)) != NULL;)
    {
        struct expr *guess_expr;
        struct expr *sym_expr;

        LOG(LOG_VERBOSE, ("Checking guessed symbol %s: ", me->key));
        /* Was this guessed symbol used in this pass? */
        if((sym_expr = map_get(s->sym_table, me->key)) == NULL)
        {
            /* No, skip it */
            continue;
        }
        guess_expr = me->value;
        LOG(LOG_VERBOSE, ("expected %d, actual %d\n",
             resolve_expr(guess_expr),
             resolve_expr(sym_expr)));

        if(expr_cmp_cb(me->value, sym_expr) != 0)
        {
            /* Not the same, not the last pass.
             * copy the actual value from the sym table */
            me->value = sym_expr;
            result = 0;
        }
    }
    return result;
}
Exemple #3
0
struct atom *new_incbin(const char *name,
                        struct expr *skip, struct expr *len)
{
    struct atom *atom;
    long length;
    i32 len32;
    i32 skip32;
    struct membuf *in;

    /* find out how long the file is */
    in = get_named_buffer(s->named_buffer, name);
    length = membuf_memlen(in);

    skip32 = 0;
    if(skip != NULL)
    {
        skip32 = resolve_expr(skip);
    }
    if(skip32 < 0)
    {
        skip32 += length;
    }
    if(skip32 < 0 || skip32 > length)
    {
        LOG(LOG_ERROR,
            ("Can't read from offset %d in file \"%s\".\n", skip32, name));
        exit(-1);
    }
    length -= skip32;

    len32 = 0;
    if(len != NULL)
    {
        len32 = resolve_expr(len);
    }
    if(len32 < 0)
    {
        len32 += length;
    }
    if(len32 < 0 || len32 > length)
    {
        LOG(LOG_ERROR,
            ("Can't read %d bytes from offset %d from file \"%s\".\n",
             len32, skip32, name));
        exit(-1);
    }

    atom = chunkpool_malloc(s->atom_pool);
    atom->type = ATOM_TYPE_BUFFER;
    atom->u.buffer.name = name;
    atom->u.buffer.length = len32;
    atom->u.buffer.skip = skip32;

    if(len != NULL)
    {
        pc_add(len32);
    }
    return atom;
}
Exemple #4
0
static int expr_cmp_cb(const void *a, const void *b)
{
    int result = 0;
    i32 e1v = resolve_expr((struct expr*)a);
    i32 e2v = resolve_expr((struct expr*)b);

    if(e1v < e2v)
    {
        result = -1;
    }
    else if(e1v > e2v)
    {
        result = 1;
    }
    return result;
}
memptr func_true(memptr func_expr) {

    if (num_nodes(func_expr) != 2) {
#ifdef DEBUG
        printf("15\n");
#endif
        ERROR(ERROR_TRUE, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

#ifdef EXTENDED_SECURITY
    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
#endif
    memptr param = resolve_expr(cons_pool[cons_pool[func_expr].cdr].car);
#ifdef EXTENDED_SECURITY
    cons_pool[local_security].car = param;
    cons_pool[local_security].carKind = CONS;
#endif
    if (type(param) == TYPE_OBJECT) {
        memptr lu = object_lookup(param, cons_pool[func_expr].car);
        if (lu == NOT_FOUND) {
            param = object_lookup(param, core_symbol);
        } else {
            return resolve_func_expr(func_expr, param, lu, true);
        }
    }
    return ((param == t) ? t : nil);
}
Exemple #6
0
int resolve_symbol(const char *symbol, int *has_valuep, i32 *valuep)
{
    int found = 0;
    int has_value = 0;
    i32 value = 0;
    struct expr *e;
    const char *p;

    p = find_symref(symbol, &e);
    if(p == NULL)
    {
        if(e != NULL)
        {
            value = resolve_expr(e);
            has_value = 1;
        }
        found = 1;
    }
    if(found)
    {
        if(has_valuep != NULL)
        {
            *has_valuep = has_value;
        }
        if(has_value && valuep != NULL)
        {
            *valuep = value;
        }
    }
    return found;
}
Exemple #7
0
void asm_echo(const char *msg, struct atom *atom)
{
    struct vec_iterator i[1];
    struct expr **exprp;
    int count = 0;
    i32 e[10];

    if(atom != NULL)
    {
        if(atom->type != ATOM_TYPE_EXPRS || vec_count(atom->u.exprs) > 10)
        {
            LOG(LOG_ERROR, ("echo arguments must be a string followed by none "
                            "or at most ten expressions.\n"));
            exit(1);
        }

        vec_get_iterator(atom->u.exprs, i);
        while((exprp = vec_iterator_next(i)) != NULL)
        {
            e[count++] = resolve_expr(*exprp);
        }
    }
    for(; count < 10; ++count)
    {
        e[count] = 0;
    }
    fprintf(stdout, msg, e[0], e[1], e[2], e[3],
            e[4], e[5], e[6], e[7], e[8], e[9]);
    fprintf(stdout, "\n");
}
Exemple #8
0
struct expr *new_expr_incword(const char *name,
                              struct expr *skip)
{
    i32 word;
    i32 offset;
    long length;
    struct membuf *in;
    struct expr *expr;
    unsigned char *p;

    offset = resolve_expr(skip);
    in = get_named_buffer(s->named_buffer, name);
    length = membuf_memlen(in);
    if(offset < 0)
    {
        offset += length;
    }
    if(offset < 0 || offset > length - 2)
    {
        LOG(LOG_ERROR,
            ("Can't read word from offset %d in file \"%s\".\n",
             offset, name));
        exit(-1);
    }
    p = membuf_get(in);
    p += offset;
    word = *p++;
    word |= *p++ << 8;

    expr = new_expr_number(word);
    return expr;
}
memptr func_cons(memptr func_expr) {

    if (num_nodes(func_expr) != 3) {
#ifdef DEBUG
        printf("9\n");
#endif
        ERROR(ERROR_CONS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr res = safe_allocate_cons();
    cons_pool[res].carKind = NIL;
    cons_pool[res].cdrKind = NIL;

    memptr current_node, current_data;
    // first parameter
    current_node = cons_pool[func_expr].cdr;
    current_data = cons_pool[current_node].car;
    cons_pool[res].car = resolve_expr(current_data);
    cons_pool[res].carKind = CONS;
    if (type(cons_pool[res].car) == TYPE_OBJECT) {
        memptr lu = object_lookup(cons_pool[res].car, cons_pool[func_expr].car);
        if (lu == NOT_FOUND && OBJECT_OPERATE_CORE) {
            cons_pool[res].car = object_lookup(cons_pool[res].car, core_symbol);
        } else if (lu != NOT_FOUND) {
            return resolve_func_expr(func_expr, cons_pool[res].car, lu, true);
        }
    }

    // second parameter
    current_node = cons_pool[current_node].cdr;
    current_data = cons_pool[current_node].car;
    cons_pool[res].cdr = resolve_expr(current_data);
    cons_pool[res].cdrKind = CONS;
    if (type(cons_pool[res].cdr) == TYPE_OBJECT && OBJECT_OPERATE_CORE) {
        cons_pool[res].cdr = object_lookup(cons_pool[res].cdr, core_symbol);
    }

    return res;
}
memptr func_cdr(memptr func_expr) {

    if (num_nodes(func_expr) != 2) {
#ifdef DEBUG
        printf("12\n");
#endif
        ERROR(ERROR_CDR, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
    memptr param = resolve_expr(cons_pool[cons_pool[func_expr].cdr].car);
    cons_pool[local_security].car = param;
    cons_pool[local_security].carKind = CONS;

    while (true) {
        Type param_type = type(param);
        if (param_type == TYPE_CONS) {
            return cons_pool[param].cdr;
        } else if (param_type == TYPE_STRING) {
            memptr result;
            if ((cons_pool[param].cdr < 0) || (string_length(param) == 1)) {
                result = nil;
            } else {
                result = allocate_cons();
                cons_pool[result].car = cons_pool[param].car;
                cons_pool[result].cdr = cons_pool[param].cdr + 1;
                cons_pool[result].carKind = STRING;
                cons_pool[result].cdrKind = INTEGER;
            }
            return result;
        } else if (param_type == TYPE_OBJECT) {
            memptr lu = object_lookup(param, cons_pool[func_expr].car);
            if (lu == NOT_FOUND) {
                param = object_lookup(param, core_symbol);
                continue;
            } else {
                return resolve_func_expr(func_expr, param, lu, true);
            }
        }
        break;
    }

#ifdef DEBUG
    printf("13\n");
#endif
    ERROR(ERROR_CDR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
    return NOT_FOUND;
}
Exemple #11
0
void push_if_state(struct expr *arg)
{
    int val;
    LOG(LOG_DEBUG, ("resolving if expression\n"));
    val = resolve_expr(arg);
    LOG(LOG_DEBUG, ("if expr resolved to %d\n", val));
    if(val)
    {
        push_state_init = 1;
    }
    else
    {
        push_state_skip = 1;
    }
}
memptr func_value(memptr func_expr) {

    if (num_nodes(func_expr) < 2) {
#ifdef DEBUG
        printf("31\n");
#endif
        ERROR(ERROR_VALUE, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr next_node = cons_pool[func_expr].cdr, current_node, current_value;
    bool first_param = true;
    do {
#ifdef EXTENDED_SECURITY
        memptr local_security = safe_allocate_cons();
        cons_pool[local_security].carKind = NIL;
        cons_pool[local_security].cdrKind = NIL;
#endif
        current_node = next_node;
        current_value = resolve_expr(cons_pool[current_node].car);
#ifdef EXTENDED_SECURITY
        cons_pool[local_security].car = current_value;
        cons_pool[local_security].carKind = CONS;
#endif
        if (current_value == NOT_FOUND) {
#ifdef DEBUG
            printf("32\n");
#endif
            ERROR(ERROR_VALUE, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            return NOT_FOUND;
        } else if (first_param && (type(current_value) == TYPE_OBJECT)) {
            memptr lu = object_lookup(current_value, cons_pool[func_expr].car);
            if (lu != NOT_FOUND) {
                return resolve_func_expr(func_expr, current_value, lu, true);
            }
        }
        next_node = cons_pool[current_node].cdr;
        first_param = false;
    } while (cons_pool[current_node].cdrKind == CONS);

    return current_value;
}
memptr func_supps(memptr func_expr) {

    if (num_nodes(func_expr) != 3) {
#ifdef DEBUG
        printf("36\n");
#endif
        ERROR(ERROR_SUPPS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr symbol = cons_pool[cons_pool[func_expr].cdr].car;
    memptr value = resolve_expr(
                       cons_pool[cons_pool[cons_pool[func_expr].cdr].cdr].car);
    if (value == NOT_FOUND) {
#ifdef DEBUG
        printf("37\n");
#endif
        ERROR(ERROR_SUPPS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
        return NOT_FOUND;
    }

    return (supps(value, symbol) ? t : nil);
}
Exemple #14
0
void initial_symbol_dump(int level, const char *symbol)
{
    i32 value;
    struct expr *expr;

    expr = map_get(s->initial_symbols, symbol);
    if(expr != NULL)
    {
        value = resolve_expr(expr);
        LOG(level, ("symbol \"%s\" resolves to %d ($%04X)\n",
                    symbol, value, value));
    }
    else
    {
        if(map_contains_key(s->initial_symbols, symbol))
        {
            LOG(level, ("symbol \"%s\" defined but has no value\n", symbol));
        }
        else
        {
            LOG(level, ("symbol \"%s\" not found\n", symbol));
        }
    }
}
memptr func_assign(memptr func_expr) {

    if (num_nodes(func_expr) != 4) {
#ifdef DEBUG
        printf("33\n");
#endif
        ERROR(ERROR_ASSIGN, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
    memptr current_node = cons_pool[func_expr].cdr;
    memptr symbol = cons_pool[current_node].car;
    current_node = cons_pool[current_node].cdr;
    memptr value = cons_pool[current_node].car;
    current_node = cons_pool[current_node].cdr;
    memptr obj = cons_pool[current_node].car;

    // first resolve the object, then the value
    obj = resolve_expr(obj);
    if (obj == NOT_FOUND) {
#ifdef DEBUG
        printf("34\n");
#endif
        ERROR(ERROR_ASSIGN, ERROR_FAILURE, ERROR_INVALID, ERROR_MALFORMED);
        return NOT_FOUND;
    }
    cons_pool[local_security].car = obj;
    cons_pool[local_security].carKind = CONS;

    value = resolve_expr(value);
    if (value == NOT_FOUND) {
#ifdef DEBUG
        printf("35\n");
#endif
        ERROR(ERROR_ASSIGN, ERROR_FAILURE, ERROR_INVALID, ERROR_MALFORMED);
        return NOT_FOUND;
    }
    cons_pool[local_security].cdr = value;
    cons_pool[local_security].cdrKind = CONS;

    memptr result = NOT_FOUND;
    if (type(obj) == TYPE_OBJECT) {

        announce_allocation(2);
        memptr new_symbol = allocate_cons();
        cons_pool[new_symbol].car = cons_pool[symbol].car;
        cons_pool[new_symbol].carKind = STRING;
        cons_pool[new_symbol].cdr = value;
        cons_pool[new_symbol].cdrKind = CONS;
        object_remove_symbol(obj, new_symbol);
        object_insert_symbol(obj, new_symbol); // includes 1 allocation
        result = obj;
    } else {

        announce_allocation(5);
        memptr new_obj = allocate_cons();
        cons_pool[new_obj].carKind = NIL;
        cons_pool[new_obj].cdr = allocate_cons();
        cons_pool[new_obj].cdrKind = CONS;
        memptr new_node = cons_pool[new_obj].cdr;
        cons_pool[new_node].car = allocate_cons();
        cons_pool[new_node].carKind = CONS;
        cons_pool[new_node].cdr = allocate_cons();
        cons_pool[new_node].cdrKind = CONS;
        memptr new_symbol = cons_pool[new_node].car;
        cons_pool[new_symbol].car = cons_pool[symbol].car;
        cons_pool[new_symbol].carKind = STRING;
        cons_pool[new_symbol].cdr = value;
        cons_pool[new_symbol].cdrKind = CONS;
        memptr new_core_node = cons_pool[new_node].cdr;
        cons_pool[new_core_node].cdrKind = NIL;
        cons_pool[new_core_node].car = allocate_cons();
        cons_pool[new_core_node].carKind = CONS;
        memptr new_core_symbol = cons_pool[new_core_node].car;
        cons_pool[new_core_symbol].car = cons_pool[core_symbol].car;
        cons_pool[new_core_symbol].carKind = STRING;
        cons_pool[new_core_symbol].cdr = obj;
        cons_pool[new_core_symbol].cdrKind = CONS;
        result = new_obj;
    }
    return result;
}
memptr func_setq(memptr func_expr) {

    if (num_nodes(func_expr) != 3) {
        // invalid call
#ifdef DEBUG
        printf("22\n");
#endif
        ERROR(ERROR_SETQ, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;

    memptr current_node = cons_pool[func_expr].cdr;
    memptr current_param = cons_pool[current_node].car;
    Type first_type = type(current_param);
    if (first_type != TYPE_SYMBOL) {
        // first argument not a name
#ifdef DEBUG
        printf("23\n");
#endif
        ERROR(ERROR_SETQ, ERROR_FAILURE, ERROR_INVALID, ERROR_MALFORMED);
        return NOT_FOUND;
    }
    memptr symbol_name = current_param;

    current_node = cons_pool[current_node].cdr;
    current_param = cons_pool[current_node].car;
    memptr value = resolve_expr(current_param);
    if (value == NOT_FOUND) {
        // invalid value
#ifdef DEBUG
        printf("24\n");
#endif
        ERROR(ERROR_SETQ, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
        return NOT_FOUND;
    }
    cons_pool[local_security].car = value;
    cons_pool[local_security].carKind = CONS;

    // defining the new symbol
    memptr symbol = allocate_cons();
    cons_pool[local_security].cdr = symbol;
    cons_pool[local_security].cdrKind = CONS;
    cons_pool[symbol].car = cons_pool[symbol_name].car;
    cons_pool[symbol].carKind = STRING;
    cons_pool[symbol].cdr = value;
    cons_pool[symbol].cdrKind = CONS;
    memptr env = lookup(symbol, ENVIRONMENT);
    if (env == NOT_FOUND) {
        // inserting to current environment
        insert_symbol(environment, symbol); // includes 1 allocation
    } else {
        // replacing previous interpretation
        remove_symbol(env, symbol);
        insert_symbol(env, symbol); // includes 1 allocation
    }

    return value;
}
memptr func_cond(memptr func_expr) {

    if (num_nodes(func_expr) == 1) {
        // no parameters
#ifdef DEBUG
        printf("16\n");
#endif
        ERROR(ERROR_COND, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
        return NOT_FOUND;
    }

    memptr current_node, current_data, condition, result;
    current_node = func_expr;
    Type current_data_type;
    while (cons_pool[current_node].cdrKind == CONS) {

        current_node = cons_pool[current_node].cdr;
        current_data = cons_pool[current_node].car;
        current_data_type = type(current_data);
        if (current_data_type == TYPE_CONS) {
            // cons support
            condition = cons_pool[current_data].car;
            result = cons_pool[current_data].cdr;
        } else if (current_data_type == TYPE_USER_FUNCTION) {
            // "function" support (interpreted as a function by the translator)
            current_data = cons_pool[current_data].car;
            if (num_nodes(current_data) != 2) {
#ifdef DEBUG
                printf("17\n");
#endif
                ERROR(ERROR_COND, ERROR_FAILURE, ERROR_INVALID, ERROR_MALFORMED);
                return NOT_FOUND;
            }
            condition = cons_pool[current_data].car;
            result = cons_pool[cons_pool[current_data].cdr].car;
        } else {
            // invalid
#ifdef DEBUG
            printf("18\n");
#endif
            ERROR(ERROR_COND, ERROR_FAILURE, ERROR_INVALID, ERROR_MALFORMED);
            return NOT_FOUND;
        }

        memptr condition_result = resolve_expr(condition);
        if (condition_result == NOT_FOUND) {
#ifdef DEBUG
            printf("19\n");
#endif
            ERROR(ERROR_COND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            return NOT_FOUND;
        } else if (condition_result != nil && condition_result != t) {
#ifdef DEBUG
            printf("20\n");
#endif
            ERROR(ERROR_COND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            return NOT_FOUND;
        }
        if (condition_result == t) {
#ifdef EXTENDED_SECURITY
            memptr local_security = safe_allocate_cons();
            cons_pool[local_security].car = result;
            cons_pool[local_security].carKind = CONS;
            cons_pool[local_security].cdrKind = NIL;
#endif
            return resolve_expr(result);
        }
    }

#ifdef DEBUG
    printf("21\n");
#endif
    ERROR(ERROR_COND, ERROR_FAILURE, ERROR_INVALID, ERROR_MALFORMED);
    return NOT_FOUND;
}
Exemple #18
0
void output_atoms(struct membuf *out, struct vec *atoms)
{
    struct vec_iterator i[1];
    struct vec_iterator i2[1];
    struct atom **atomp;
    struct atom *atom;
    struct expr **exprp;
    struct expr *expr;
    struct membuf *in;
    const char *p;
    i32 value;
    i32 value2;

    dump_sym_table(LOG_DEBUG, s->sym_table);

    vec_get_iterator(atoms, i);
    while((atomp = vec_iterator_next(i)) != NULL)
    {
        atom = *atomp;

        LOG(LOG_DEBUG, ("yadda\n"));

        switch(atom->type)
        {
        case ATOM_TYPE_OP_ARG_NONE:
            LOG(LOG_DEBUG, ("output: $%02X\n", atom->u.op.code));
            membuf_append_char(out, atom->u.op.code);
            break;
        case ATOM_TYPE_OP_ARG_U8:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_u8(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
                            atom->u.op.code, value & 255));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            break;
        case ATOM_TYPE_OP_ARG_I8:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_i8(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
                            atom->u.op.code, value & 255));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            break;
        case ATOM_TYPE_OP_ARG_UI8:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_ui8(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: $%02X $%02X\n",
                            atom->u.op.code, value & 255));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            break;
        case ATOM_TYPE_OP_ARG_U16:
            /* op with argument */
            value = resolve_expr(atom->u.op.arg);
            if(!is_valid_u16(value))
            {
                LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n",
                                value, atom->u.op.code, (void*)atom));
                exit(1);
            }
            value2 = value / 256;
            value = value % 256;
            LOG(LOG_DEBUG, ("output: $%02X $%02X $%02X\n",
                            atom->u.op.code,
                            value, value2));
            membuf_append_char(out, atom->u.op.code);
            membuf_append_char(out, value);
            membuf_append_char(out, value2);
            break;
        case ATOM_TYPE_RES:
            /* reserve memory statement */
            value = resolve_expr(atom->u.res.length);
            if(!is_valid_u16(value))
            {
                LOG(LOG_ERROR, ("length %d for .res(length, value) "
                                "is out of range\n", value));
                exit(1);
            }
            value2 = resolve_expr(atom->u.res.value);
            if(!is_valid_ui8(value2))
            {
                LOG(LOG_ERROR, ("value %d for .res(length, value) "
                                "is out of range\n", value));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: .RES %d, %d\n", value, value2));
            while(--value >= 0)
            {
                membuf_append_char(out, value2);
            }
            break;
        case ATOM_TYPE_BUFFER:
            /* include binary file statement */
            value = atom->u.buffer.skip;
            if(!is_valid_u16(value))
            {
                LOG(LOG_ERROR, ("value %d for .res(length, value) "
                                "is out of range\n", value));
                exit(1);
            }
            value2 = atom->u.buffer.length;
            if(!is_valid_u16(value2))
            {
                LOG(LOG_ERROR, ("length %d for .incbin(name, skip, length) "
                                "is out of range\n", value2));
                exit(1);
            }
            LOG(LOG_DEBUG, ("output: .INCBIN \"%s\", %d, %d\n",
                            atom->u.buffer.name, value, value2));
            in = get_named_buffer(s->named_buffer, atom->u.buffer.name);
            p = membuf_get(in);
            p += value;
            while(--value2 >= 0)
            {
                membuf_append_char(out, *p++);
            }
            break;
        case ATOM_TYPE_WORD_EXPRS:
            vec_get_iterator(atom->u.exprs, i2);
            while((exprp = vec_iterator_next(i2)) != NULL)
            {
                expr = *exprp;
                value = resolve_expr(expr);
                if(!is_valid_ui16(value))
                {
                    LOG(LOG_ERROR, ("value %d for .word(value, ...) "
                                    "is out of range\n", value));
                }
                value2 = value / 256;
                value = value % 256;
                membuf_append_char(out, value);
                membuf_append_char(out, value2);
            }
            LOG(LOG_DEBUG, ("output: %d words\n", vec_count(atom->u.exprs)));
            break;
        case ATOM_TYPE_BYTE_EXPRS:
            vec_get_iterator(atom->u.exprs, i2);
            while((exprp = vec_iterator_next(i2)) != NULL)
            {
                expr = *exprp;
                value = resolve_expr(expr);
                if(!is_valid_ui8(value))
                {
                    LOG(LOG_ERROR, ("value %d for .byte(value, ...) "
                                    "is out of range\n", value));
                }
                membuf_append_char(out, value);
            }
            LOG(LOG_DEBUG, ("output: %d bytes\n", vec_count(atom->u.exprs)));
            break;
        default:
            LOG(LOG_ERROR, ("invalid atom_type %d @%p\n",
                            atom->type, (void*)atom));
            exit(1);
        }
    }
}
memptr do_join_operation(memptr func_expr, JoinOperation operation_type) {

    if (num_nodes(func_expr) != 3) {
#ifdef DEBUG
        printf("1\n");
#endif
        switch (operation_type) {
        case PLUS:
            ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case MINUS:
            ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case MULT:
            ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case DIV:
            ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case EQUAL:
            ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case SMALLER:
            ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case GREATER:
            ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case OR:
            ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case AND:
            ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        case XOR:
            ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_COUNT);
            break;
        default:
            break;
        }
        return NOT_FOUND;
    }

    memptr current_node = cons_pool[func_expr].cdr;
    memptr local_security = safe_allocate_cons();
    cons_pool[local_security].carKind = NIL;
    cons_pool[local_security].cdrKind = NIL;
    memptr first_param = resolve_expr(cons_pool[current_node].car);
    if (first_param == NOT_FOUND) {
#ifdef DEBUG
        printf("2\n");
#endif
        switch (operation_type) {
        case PLUS:
            ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MINUS:
            ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MULT:
            ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case DIV:
            ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case EQUAL:
            ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case SMALLER:
            ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case GREATER:
            ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case OR:
            ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case AND:
            ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case XOR:
            ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        default:
            break;
        }
        return NOT_FOUND;
    }
    cons_pool[local_security].car = first_param;
    cons_pool[local_security].carKind = CONS;
    Type first_param_type = type(first_param);
    if (first_param_type == TYPE_OBJECT) {
        memptr lu = object_lookup(first_param, cons_pool[func_expr].car);
        if (lu == NOT_FOUND) {
            first_param = object_lookup(first_param, core_symbol);
            first_param_type = type(first_param);
        } else {
            return resolve_func_expr(func_expr, first_param, lu, true);
        }
    }

    current_node = cons_pool[current_node].cdr;
    memptr second_param = resolve_expr(cons_pool[current_node].car);
    if (second_param == NOT_FOUND) {
#ifdef DEBUG
        printf("3\n");
#endif
        switch (operation_type) {
        case PLUS:
            ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MINUS:
            ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case MULT:
            ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case DIV:
            ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case EQUAL:
            ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case SMALLER:
            ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case GREATER:
            ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case OR:
            ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case AND:
            ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        case XOR:
            ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
            break;
        default:
            break;
        }
        return NOT_FOUND;
    }
    cons_pool[local_security].cdr = second_param;
    cons_pool[local_security].cdrKind = CONS;
    Type second_param_type = type(second_param);
    if (second_param_type == TYPE_OBJECT) {
        second_param = object_lookup(second_param, core_symbol);
        second_param_type = type(second_param);
    }

    memptr result = NOT_FOUND;
    if (operation_type == PLUS || operation_type == MINUS
            || operation_type == MULT || operation_type == DIV) {
        if (first_param_type != TYPE_INTEGER
                || second_param_type != TYPE_INTEGER) {
#ifdef DEBUG
            printf("4\n");
#endif
            switch (operation_type) {
            case PLUS:
                ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MINUS:
                ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MULT:
                ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case DIV:
                ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case EQUAL:
                ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case SMALLER:
                ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case GREATER:
                ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case OR:
                ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case AND:
                ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case XOR:
                ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            default:
                break;
            }
            return NOT_FOUND;
        }
        int first_value = fix_integer(cons_pool[first_param].car);
        int second_value = fix_integer(cons_pool[second_param].car);
        result = allocate_cons();
        cons_pool[result].carKind = INTEGER;
        cons_pool[result].cdrKind = NIL;
        switch (operation_type) {
        case PLUS:
            cons_pool[result].car = first_value + second_value;
            break;
        case MINUS:
            cons_pool[result].car = first_value - second_value;
            break;
        case MULT:
            cons_pool[result].car = first_value * second_value;
            break;
        case DIV:
            if (second_value == 0) {
#ifdef DEBUG
                printf("5\n");
#endif
                return NOT_FOUND;
            }
            cons_pool[result].car = first_value / second_value;
            break;
        default:
            break;
        }
    } else if (operation_type == EQUAL || operation_type == SMALLER
               || operation_type == GREATER) {
        if (first_param_type != second_param_type) {
#ifdef DEBUG
            printf("6\n");
#endif
            switch (operation_type) {
            case PLUS:
                ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MINUS:
                ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MULT:
                ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case DIV:
                ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case EQUAL:
                ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case SMALLER:
                ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case GREATER:
                ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case OR:
                ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case AND:
                ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case XOR:
                ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            default:
                break;
            }
        }
        int first_value;
        int second_value;
        if (first_param_type == TYPE_NIL_TRUE) {
            first_value = ((first_param == nil) ? 0 : 1);
            second_value = ((second_param == nil) ? 0 : 1);
        } else if (first_param_type == TYPE_INTEGER) {
            first_value = fix_integer(cons_pool[first_param].car);
            second_value = fix_integer(cons_pool[second_param].car);
        } else {
            // addresses comparison
            first_value = first_param;
            second_value = second_param;
        }
        // strings logic
        if (first_param_type == TYPE_STRING) {
            bool full_equal = false;
            int len1 = string_length(first_param);
            int len2 = string_length(second_param);
            if ((len1 == 1) || (len2 == 1)) {
                first_value =
                    strings_pool[get_string(cons_pool[first_param].car,
                                            cons_pool[first_param].cdr)];
                second_value = strings_pool[get_string(
                                                cons_pool[second_param].car,
                                                cons_pool[second_param].cdr)];
                if (len1 != 1) {
                    if (first_value == second_value) {
                        first_value++;
                    }
                }
                if (len2 != 1) {
                    if (first_value == second_value) {
                        second_value++;
                    }
                }
            } else {
                int iter1 = get_string(cons_pool[first_param].car,
                                       cons_pool[first_param].cdr), iter2 = get_string(
                                                   cons_pool[second_param].car,
                                                   cons_pool[second_param].cdr);
                first_value = second_value = 0;
                while (first_value == second_value
                        && strings_pool[iter1] != '\0'
                        && strings_pool[iter2] != '\0') {
                    first_value = strings_pool[iter1++];
                    second_value = strings_pool[iter2++];
                }
                if ((strings_pool[iter1] != '\0')
                        && (strings_pool[iter2] == '\0')
                        && (first_value == second_value)) {
                    first_value++;
                } else if ((strings_pool[iter1] == '\0')
                           && (strings_pool[iter2] != '\0')
                           && (first_value == second_value)) {
                    second_value++;
                }
            }
        }
        switch (operation_type) {
        case EQUAL:
            result = ((first_value == second_value) ? t : nil);
            break;
        case SMALLER:
            result = ((first_value < second_value) ? t : nil);
            break;
        case GREATER:
            result = ((first_value > second_value) ? t : nil);
            break;
        default:
#ifdef DEBUG
            printf("7\n");
#endif
            return NOT_FOUND;
            break;
        }
    } else if (operation_type == XOR || operation_type == OR
               || operation_type == AND) {
        if (first_param_type != TYPE_NIL_TRUE
                || second_param_type != TYPE_NIL_TRUE) {
#ifdef DEBUG
            printf("7.5\n");
#endif
            switch (operation_type) {
            case PLUS:
                ERROR(ERROR_PLUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MINUS:
                ERROR(ERROR_MINUS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case MULT:
                ERROR(ERROR_MULT, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case DIV:
                ERROR(ERROR_DIV, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case EQUAL:
                ERROR(ERROR_EQUALS, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case SMALLER:
                ERROR(ERROR_SMALLER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case GREATER:
                ERROR(ERROR_GREATER, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case OR:
                ERROR(ERROR_OR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case AND:
                ERROR(ERROR_AND, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            case XOR:
                ERROR(ERROR_XOR, ERROR_FAILURE, ERROR_INVALID, ERROR_EMPTY);
                break;
            default:
                break;
            }
            return NOT_FOUND;
        }
        switch (operation_type) {
        case XOR:
            result = ((first_param != second_param) ? t : nil);
            break;
        case OR:
            result = ((first_param == t || second_param == t) ? t : nil);
            break;
        case AND:
            result = ((first_param == t && second_param == t) ? t : nil);
            break;
        default:
#ifdef DEBUG
            printf("8\n");
#endif
            return NOT_FOUND;
            break;
        }
    }

    return result;
}