Ejemplo n.º 1
0
/**
 * Map/Setの要素を全て解放する
 * entryの配列は使いまわす
 */
static int map_clear(Value *vret, Value *v, RefNode *node)
{
    RefMap *r = Value_vp(*v);
    int i;

    if (r->lock_count > 0) {
        throw_error_select(THROW_CANNOT_MODIFY_ON_ITERATION);
        return FALSE;
    }
    for (i = 0; i < r->entry_num; i++) {
        HashValueEntry *p = r->entry[i];
        while (p != NULL) {
            HashValueEntry *prev = p;
            unref(p->key);
            unref(p->val);
            p = p->next;

            free(prev);
        }
        r->entry[i] = NULL;
    }
    r->count = 0;

    return TRUE;
}
Ejemplo n.º 2
0
/**
 * printf("format", ...)
 * printf(locale, "format", ...)
 */
static int textio_printf(Value *vret, Value *v, RefNode *node)
{
    int str = FUNC_INT(node);
    RefNode *v1_type = Value_type(v[1]);
    RefStr *s_fmt;
    Ref *r_loc = NULL;
    int start_arg;

    if (v1_type == fs->cls_str) {
        s_fmt = Value_vp(v[1]);
        start_arg = 2;
    } else if (v1_type == fs->cls_locale) {
        if (fg->stk_top > v + 2) {
            RefNode *v2_type = Value_type(v[2]);
            if (v2_type != fs->cls_str) {
                throw_error_select(THROW_ARGMENT_TYPE__NODE_NODE_INT, fs->cls_str, v2_type, 2);
                return FALSE;
            }
        } else {
            throw_errorf(fs->mod_lang, "ArgumentError", "2 or more arguments excepted (1 given)");
            return FALSE;
        }
        r_loc = Value_ref(v[1]);
        s_fmt = Value_vp(v[2]);
        start_arg = 3;
    } else {
        throw_error_select(THROW_ARGMENT_TYPE2__NODE_NODE_NODE_INT, fs->cls_str, fs->cls_locale, v1_type, 1);
        return FALSE;
    }

    if (str) {
        // sprintf
        StrBuf buf;
        StrBuf_init(&buf, 0);
        if (!textio_printf_sub(VALUE_NULL, &buf, s_fmt, start_arg, r_loc)) {
            return FALSE;
        }
        *vret = cstr_Value(fs->cls_str, buf.p, buf.size);
        StrBuf_close(&buf);
    } else {
        if (!textio_printf_sub(*v, NULL, s_fmt, start_arg, r_loc)) {
            return FALSE;
        }
    }

    return TRUE;
}
Ejemplo n.º 3
0
/**
 * 検索して見つかった場合/見つからなかった場合は
 * 1.true/falseを返す
 * 2.index/nullを返す
 */
int map_index_of(Value *vret, Value *v, RefNode *node)
{
    RefMap *rm = Value_vp(*v);
    int ret_index = FUNC_INT(node);
    Value v1 = v[1];
    RefNode *type = Value_type(v1);
    int i;

    RefNode *fn_eq = Hash_get_p(&type->u.c.h, fs->symbol_stock[T_EQ]);
    if (fn_eq == NULL) {
        throw_error_select(THROW_NO_MEMBER_EXISTS__NODE_REFSTR, type, fs->symbol_stock[T_EQ]);
        return FALSE;
    }

    rm->lock_count++;
    for (i = 0; i < rm->entry_num; i++) {
        HashValueEntry *ep = rm->entry[i];
        for (; ep != NULL; ep = ep->next) {
            Value va = ep->val;

            if (Value_type(va) == type) {
                if (type == fs->cls_str) {
                    if (refstr_eq(Value_vp(v1), Value_vp(va))) {
                        break;
                    }
                } else {
                    Value_push("vv", v1, va);
                    if (!call_function(fn_eq, 1)) {
                        goto ERROR_END;
                    }
                    fg->stk_top--;
                    if (Value_bool(*fg->stk_top)) {
                        unref(*fg->stk_top);
                        if (ret_index) {
                            *vret = Value_cp(ep->key);
                        } else {
                            *vret = VALUE_TRUE;
                        }
                        return TRUE;
                    }
                }
            }
        }
    }
    if (!ret_index) {
        *vret = VALUE_FALSE;
    }

    rm->lock_count--;
    return TRUE;
ERROR_END:
    rm->lock_count--;
    return FALSE;
}
Ejemplo n.º 4
0
// 削除した要素を返す
static int map_delete(Value *vret, Value *v, RefNode *node)
{
    RefMap *rm = Value_vp(*v);
    Value key = v[1];

    if (rm->lock_count > 0) {
        throw_error_select(THROW_CANNOT_MODIFY_ON_ITERATION);
        return FALSE;
    }
    if (!refmap_del(vret, rm, key)) {
        return FALSE;
    }

    return TRUE;
}
Ejemplo n.º 5
0
static int map_add_entry(Value *vret, Value *v, RefNode *node)
{
    RefMap *rm = Value_vp(*v);
    Ref *r = Value_ref(v[1]);
    HashValueEntry *ve;

    if (rm->lock_count > 0) {
        throw_error_select(THROW_CANNOT_MODIFY_ON_ITERATION);
        return FALSE;
    }
    ve = refmap_add(rm, r->v[0], TRUE, FALSE);
    if (ve == NULL) {
        return FALSE;
    }
    ve->val = Value_cp(r->v[1]);
    return TRUE;
}
Ejemplo n.º 6
0
static int strio_index(Value *vret, Value *v, RefNode *node)
{
    RefBytesIO *mb = Value_bytesio(*v);
    const char *src_p = mb->buf.p;
    int src_size = mb->buf.size;
    int idx = utf8_position(src_p, src_size, Value_int64(v[1], NULL));

    if (idx >= 0 && idx < src_size) {
        int code = utf8_codepoint_at(&src_p[idx]);
        *vret = int32_Value(code);
    } else {
        throw_error_select(THROW_INVALID_INDEX__VAL_INT, v[1], src_size);
        return FALSE;
    }

    return TRUE;
}
Ejemplo n.º 7
0
int set_add_value(Value *vret, Value *v, RefNode *node)
{
    RefMap *rm = Value_vp(*v);
    Value *v1 = v + 1;
    int argc = fg->stk_top - fg->stk_base - 1;
    int i;

    if (rm->lock_count > 0) {
        throw_error_select(THROW_CANNOT_MODIFY_ON_ITERATION);
        return FALSE;
    }
    for (i = 0; i < argc; i++) {
        if (refmap_add(rm, v1[i], TRUE, FALSE) == NULL) {
            return FALSE;
        }
    }

    return TRUE;
}
Ejemplo n.º 8
0
int main_fox(int argc, const char **argv)
{
    ArgumentInfo ai;
    RefNode *mod;
    RefStr *name_startup;
    int ret = FALSE;

    memset(&ai, 0, sizeof(ai));
    init_stdio();

    // デフォルト値
    fs->max_alloc = 64 * 1024 * 1024; // 64MB
    fs->max_stack = 32768;
    fv->err_dst = "alert";

    if (!parse_args(&ai, argc, argv)) {
        goto ERROR_END;
    }
    fox_init_compile(FALSE);

    if (ai.srcfile != NULL) {
        mod = get_module_by_file(ai.srcfile);
        if (mod != NULL) {
            mod->u.m.src_path = ai.srcfile;
        }
    } else {
        throw_errorf(fs->mod_lang, "ArgumentError", "Missing filename");
        goto ERROR_END;
    }

    // ソースを読み込んだ後で実行
    if (fs->running_mode == RUNNING_MODE_CGI) {
        throw_errorf(fs->mod_lang, "CompileError", "CGI mode is not supported");
        goto ERROR_END;
    }
    init_fox_stack();

    if (mod == NULL) {
        throw_error_select(THROW_CANNOT_OPEN_FILE__STR, Str_new(ai.srcfile, -1));
        goto ERROR_END;
    }
    if (fg->error != VALUE_NULL) {
        goto ERROR_END;
    }

    // 参照できない名前で登録
    name_startup = intern("[startup]", 9);
    mod->name = name_startup;
    Hash_add_p(&fg->mod_root, &fg->st_mem, name_startup, mod);

    if (!fox_link()) {
        goto ERROR_END;
    }
    if (!fox_run(mod)) {
        goto ERROR_END;
    }
    ret = TRUE;

ERROR_END:
    print_last_error();
    fox_close();
    return ret;
}
Ejemplo n.º 9
0
static int map_marshal_read(Value *vret, Value *v, RefNode *node)
{
    Value dumper = v[1];
    Value r = Value_ref(dumper)->v[INDEX_MARSHALDUMPER_SRC];
    int is_map = FUNC_INT(node);
    RefMap *rm;
    uint32_t size;
    int i;

    if (!stream_read_uint32(r, &size)) {
        return FALSE;
    }
    if (size > 0xffffff) {
        throw_errorf(fs->mod_lang, "ValueError", "Invalid size number");
        return FALSE;
    }
    if (size * sizeof(HashValueEntry) > fs->max_alloc) {
        throw_error_select(THROW_MAX_ALLOC_OVER__INT, fs->max_alloc);
        return FALSE;
    }
    rm = refmap_new(size);
    if (!is_map) {
        rm->rh.type = fs->cls_set;
    }
    *vret = vp_Value(rm);

    for (i = 0; i < size; i++) {
        Value key;
        Value_push("v", dumper);
        if (!call_member_func(fs->str_read, 0, TRUE)) {
            return FALSE;
        }
        fg->stk_top--;
        key = *fg->stk_top;
        if (is_map) {
            Value val;
            HashValueEntry *ve;

            Value_push("v", dumper);
            if (!call_member_func(fs->str_read, 0, TRUE)) {
                return FALSE;
            }
            fg->stk_top--;
            val = *fg->stk_top;

            ve = refmap_add(rm, key, TRUE, FALSE);
            if (ve == NULL) {
                unref(key);
                unref(val);
                return FALSE;
            }
            ve->val = val;
        } else {
            // Set
            if (refmap_add(rm, key, TRUE, FALSE) == NULL) {
                unref(key);
                return FALSE;
            }
        }
        unref(key);
    }

    return TRUE;
}
Ejemplo n.º 10
0
/**
 * 文字コードを変換しながらStreamに出力する
 * v : stream (optional,sb==NULLの場合必須)
 * sb : StrBuf : (optional)
 */
static int stream_write_sub_s(Value v, StrBuf *sb, const char *s_p, int s_size, RefTextIO *tio)
{
    if (s_size < 0) {
        s_size = strlen(s_p);
    }
    // TODO:未検証
    if (v != VALUE_NULL) {
        RefBytesIO *mb = Value_vp(v);
        if (mb->rh.type == fs->cls_bytesio) {
            sb = &mb->buf;
        }
    }
    if (sb != NULL) {
        // sprintfの場合tio==NULL
        if (tio == NULL || tio->cs->utf8) {
            if (!StrBuf_add(sb, s_p, s_size)) {
                return FALSE;
            }
            return TRUE;
        } else {
            if (tio->out.ic == (void*)-1) {
                if (!IconvIO_open(&tio->out, fs->cs_utf8, tio->cs, tio->trans ? "?" : NULL)) {
                    return FALSE;
                }
            }
            if (!IconvIO_conv(&tio->out, sb, s_p, s_size, TRUE, TRUE)) {
                return FALSE;
            }
            return TRUE;
        }
    } else {
        if (tio == NULL || tio->cs->utf8) {
            return stream_write_data(v, s_p, s_size);
        } else {
            Ref *r = Value_ref(v);
            IconvIO *ic = &tio->out;
            Value *vmb = &r->v[INDEX_WRITE_MEMIO];
            RefBytesIO *mb;
            int max = Value_integral(r->v[INDEX_WRITE_MAX]);

            if (max == -1) {
                throw_error_select(THROW_NOT_OPENED_FOR_WRITE);
                return FALSE;
            }
            if (tio->out.ic == (void*)-1) {
                if (!IconvIO_open(&tio->out, fs->cs_utf8, tio->cs, tio->trans ? "?" : NULL)) {
                    return FALSE;
                }
            }
            if (*vmb == VALUE_NULL) {
                *vmb = vp_Value(bytesio_new_sub(NULL, BUFFER_SIZE));
                max = BUFFER_SIZE;
                r->v[INDEX_WRITE_MAX] = int32_Value(max);
                // STDOUTだけ特別扱い
                if (fs->cgi_mode) {
                    if (r == Value_vp(fg->v_cio)) {
                        send_headers();
                    }
                }
            }
            mb = Value_vp(*vmb);

            ic->inbuf = s_p;
            ic->inbytesleft = s_size;
            ic->outbuf = mb->buf.p + mb->buf.size;
            ic->outbytesleft = max - mb->buf.size;

            for (;;) {
                switch (IconvIO_next(ic)) {
                case ICONV_OK:
                    mb->buf.size = ic->outbuf - mb->buf.p;
                    goto BREAK;
                case ICONV_OUTBUF:
                    mb->buf.size = ic->outbuf - mb->buf.p;
                    if (!stream_flush_sub(v)) {
                        return FALSE;
                    }
                    ic->outbuf = mb->buf.p;
                    ic->outbytesleft = max;
                    break;
                case ICONV_INVALID:
                    if (tio->trans) {
                        const char *ptr;
                        if (ic->outbytesleft == 0) {
                            mb->buf.size = ic->outbuf - mb->buf.p;
                            if (!stream_flush_sub(v)) {
                                return FALSE;
                            }
                            ic->outbuf = mb->buf.p;
                            ic->outbytesleft = max;
                        }
                        ptr = ic->inbuf;

                        *ic->outbuf++ = '?';
                        ic->outbytesleft--;

                        // 1文字進める
                        utf8_next(&ptr, ptr + ic->inbytesleft);
                        ic->inbytesleft -= ptr - ic->inbuf;
                        ic->inbuf = ptr;
                    } else {
                        RefCharset *cs = tio->cs;
                        throw_errorf(fs->mod_lang, "CharsetError", "Cannot convert %U to %S",
                                utf8_codepoint_at(ic->inbuf), cs->name);
                        return FALSE;
                    }
                    break;
                }
            }
        BREAK:
            return TRUE;
        }
    }
}
Ejemplo n.º 11
0
static int textio_gets_sub(Value *vret, Ref *ref, int trim)
{
    Value stream = ref->v[INDEX_TEXTIO_STREAM];
    StrBuf buf;
    Str result;
    int ret = TRUE;
    RefNode *s_type = Value_type(stream);

    if (s_type == fs->cls_bytesio) {
        buf.p = NULL;
        if (!bytesio_gets_sub(&result, stream)) {
            result.size = 0;
        }
    } else {
        StrBuf_init(&buf, 0);
        if (!stream_gets_sub(&buf, stream, '\n')) {
            StrBuf_close(&buf);
            return FALSE;
        }
        result = Str_new(buf.p, buf.size);
    }
    if (result.size > 0) {
        RefTextIO *tio = Value_vp(ref->v[INDEX_TEXTIO_TEXTIO]);
        if (trim) {
            // 末尾の改行を取り除く
            if (result.size > 0 && result.p[result.size - 1] == '\n') {
                result.size--;
                if (result.size > 0 && result.p[result.size - 1] == '\r') {
                    result.size--;
                }
            }
        }
        if (tio->cs == fs->cs_utf8) {
            if (invalid_utf8_pos(result.p, result.size) >= 0) {
                if (tio->trans) {
                    // 不正な文字をU+FFFDに置き換える
                    *vret = cstr_Value_conv(result.p, result.size, NULL);
                } else {
                    throw_error_select(THROW_INVALID_UTF8);
                    ret = FALSE;
                    goto FINALLY;
                }
            } else {
                *vret = cstr_Value(fs->cls_str, result.p, result.size);
            }
        } else {
            StrBuf buf2;
            if (tio->in.ic == (void*)-1) {
                if (!IconvIO_open(&tio->in, tio->cs, fs->cs_utf8, tio->trans ? UTF8_ALTER_CHAR : NULL)) {
                    ret = FALSE;
                    goto FINALLY;
                }
            }

            StrBuf_init(&buf2, result.size);
            if (!IconvIO_conv(&tio->in, &buf2, result.p, result.size, FALSE, TRUE)) {
                StrBuf_close(&buf2);
                ret = FALSE;
                goto FINALLY;
            }
            *vret = cstr_Value(fs->cls_str, buf2.p, buf2.size);
            StrBuf_close(&buf2);
        }
    }

FINALLY:
    if (buf.p != NULL) {
        StrBuf_close(&buf);
    }

    return ret;
}